Normandy.Agents.Turn.Inline
(normandy v1.0.0)
View Source
Inline (synchronous) interpreter for the pure Normandy.Agents.Turn core.
Drives a turn to completion in the calling process: it feeds :start into
Turn.step/2, performs each returned effect's side-effect, and feeds the
resulting event back into step/2 until the turn reaches :stopped (returns
{:ok, state}) or :failed (returns {:error, reason, state}).
This is the library / scripted-run shell. It does NOT (yet) replace
BaseAgent.run/2; it exists to prove the FSM core runs a real turn against a
real Dispatch chokepoint. Compaction at the :steering boundary is
supported via the optional :compact dep (default no-op); streaming,
guardrails, validation, persistence and approval shells come in later phases.
deps is a map of side-effecting functions:
:call_llm—fn request -> {:ok, response} | {:error, reason} end(required):dispatch—fn calls -> [%ToolResult{}] end(required):append—fn role, content -> any end(optional, defaults to no-op):emit—fn name, meta -> any end(optional, defaults to no-op):convert—fn raw, response_model -> converted end(optional, defaults to identity:returns `raw` unchanged):validate—fn value -> validated end(optional, defaults to identity: returnsvalueunchanged):guard—fn value -> any end(optional, defaults to no-op: side-effecting, returnis ignored and the input `value` is fed forward via `{:output_guarded, value}`):compact—fn info -> any end(optional, defaults to no-op). Invoked at the`:steering` boundary; the inline shell does not thread memory, so a real impl must compact external state by side effect.
By design, step/2 always places the single blocking/terminal effect
(:call_llm, :dispatch_tools, :finalize, :fail) last in its effect list,
so the interpreter performs the leading :append_message / :emit_event
effects in order and then acts on the terminal one.
Summary
Functions
@spec run(Normandy.Agents.Turn.State.t(), map()) :: {:ok, Normandy.Agents.Turn.State.t()} | {:error, term(), Normandy.Agents.Turn.State.t()}