Jido.AgentServer.DirectiveExec protocol
(Jido v2.0.0)
View Source
Protocol for executing directives in AgentServer.
Implement this protocol for custom directive types to extend AgentServer with new effect handlers without modifying core code.
Return Values
{:ok, state}- Directive executed successfully, continue processing{:async, ref | nil, state}- Async work started (ref for tracking, nil if fire-and-forget){:stop, reason, state}- Hard stop the agent process (see warning below)
⚠️ WARNING: {:stop, ...} Semantics
{:stop, reason, state} is a hard stop that terminates the AgentServer immediately:
- Pending directives are dropped - Any directives still in the queue will NOT be executed
- Async work is orphaned - In-flight tasks may complete but their signals go nowhere
- Hooks don't run -
on_after_cmd/3and similar callbacks will NOT be invoked - State may be incomplete - External pollers may see partial state or get
:noproc
When to use {:stop, ...}
Reserved for abnormal or framework-level termination only:
- Irrecoverable errors during directive execution
- Framework decisions (e.g.,
on_parent_death: :stop) - Explicit shutdown requests (with reason like
:shutdown)
Do NOT use {:stop, ...} for normal completion
For agents that complete their work (e.g., ReAct finishing a conversation):
- Set
state.statusto:completedor:failedin your agent/strategy - Store results in state (e.g.,
last_answer,final_result) - Let external code poll
AgentServer.state/1and check status - Process stays alive until explicitly stopped or supervised
This matches Elm/Redux semantics where completion is a state concern, not a process lifecycle concern.
Example Implementation
defimpl Jido.AgentServer.DirectiveExec, for: MyApp.Directive.CallLLM do
def exec(%{model: model, prompt: prompt}, _input_signal, state) do
Task.Supervisor.start_child(Jido.TaskSupervisor, fn ->
MyApp.LLM.call(model, prompt)
end)
{:async, nil, state}
end
endFallback for Unknown Directives
Unknown directive types are logged and ignored by default. The fallback
implementation uses @fallback_to_any true.
Summary
Functions
Execute a directive, returning an updated state.
Types
@type t() :: term()
All the types that implement this protocol.
Functions
@spec exec(struct(), Jido.Signal.t(), Jido.AgentServer.State.t()) :: {:ok, Jido.AgentServer.State.t()} | {:async, reference() | nil, Jido.AgentServer.State.t()} | {:stop, term(), Jido.AgentServer.State.t()}
Execute a directive, returning an updated state.
Parameters
directive- The directive struct to executeinput_signal- The signal that triggered this directivestate- The current AgentServer.State
Returns
{:ok, state}- Continue processing with updated state{:async, ref | nil, state}- Async work started{:stop, reason, state}- Stop the agent