Normandy.Agents.Turn (normandy v1.1.1)

View Source

The pure finite-state-machine core of an agent turn.

A turn is plain data (Normandy.Agents.Turn.State) advanced by step/2, a pure function: step(state, event) -> {state', [effect]}. It performs no I/O. Events come from the shell (LLM responses, tool results, errors); effects are data the shell interprets (call the LLM, dispatch tools, append to memory, emit telemetry, finalize, fail). Keeping the core pure makes every transition unit/property testable without processes, and makes the state serializable for the durable/suspendable shells added in later phases.

States

Seven statuses are defined. :awaiting_approval (suspend/resume for human approval) is entered when a dispatched batch parks calls. :steering is a resting state entered at every tool-batch boundary: the core emits a {:maybe_compact, info} effect there and resumes on {:compaction_done, _}, which is where context-window compaction (Phase 5) runs in the shell.

Summary

Functions

Builds the initial :provisioning state for a turn.

Re-derives the effects to continue a turn from a persisted, non-terminal state (used by an eager shell after passivation/handoff). Pure.

Advances the turn one event. Pure: returns {state', [effect]} and does no I/O.

Functions

new(opts \\ [])

Builds the initial :provisioning state for a turn.

Options: :max_iterations (default 5), :response_model (the response model for normal tool-loop LLM calls, e.g. %ToolCallResponse{}), :output_schema (the response model for the forced final call when the iteration cap is hit).

Raises ArgumentError if :max_iterations is not an integer >= 1, enforcing the pos_integer() contract on State.max_iterations (mirrors the check BaseAgent.init/1 applies at the shell boundary).

resume(s)

Re-derives the effects to continue a turn from a persisted, non-terminal state (used by an eager shell after passivation/handoff). Pure.

Only states the core persists are resumable: :steering (per-batch boundary) re-issues compaction then continues; :awaiting_approval waits for a decision (no effects). Terminal states yield no effects.

step(s, event)

Advances the turn one event. Pure: returns {state', [effect]} and does no I/O.