View Source Agens.Backend behaviour (agens v0.2.0)
Behaviour for side-effecting backends that observe and extend a running Job.
A backend receives callbacks for lifecycle events (run, status changes, completion, explicit end, errors), per-Node activity (started, retried, result), tool calls, resource loads, prompt finalization, yield coordination, and Sub-Job resolution.
Backends are configured via the :backends application environment key:
config :agens, backends: [MyApp.LogBackend, MyApp.EmitBackend]When unset, Agens defaults to [Agens.Backend.Emit, Agens.Backend.Log]. All configured
backends receive each callback in declaration order.
Implementing a backend
defmodule MyApp.LogBackend do
@behaviour Agens.Backend
@impl true
def run(_caller, _job_id, run_id), do: IO.puts("running #{run_id}")
# ... other callbacks ...
endMost callbacks return :ok. sub/1 is special: it returns an Agens.Job.Sub struct
describing a Sub-Job to be started, or nil if the backend does not handle that job_id.
Returning nil lets a later backend in the list resolve the Sub-Job.
Summary
Types
A Job identifier.
A Node identifier within a Job.
Normalized record of a resource load as observed by a backend.
A run identifier for a single Job invocation.
A Job status atom (e.g. :running, :complete, :error).
Normalized record of a tool call invocation as observed by a backend.
Callbacks
Invoked when a Job completes by running every Node to completion (no Node returned :end).
Invoked when a Job terminates because a Serving's next returned an :end instruction.
Invoked when a Job errors out. Receives the failing Agens.Message and the error reason.
Invoked when a Node has produced a result from its Serving.
Invoked when a Node is being retried.
Invoked when a Node begins processing.
Invoked with the finalized Agens.Message after Agens.Prompt has built the system and user prompts.
Invoked when a resource has been loaded for a Node (successfully or not).
Invoked when a Job begins execution, immediately after Agens.Job.run/3 is accepted.
Invoked when a Job's status transitions (e.g. :init → :running).
Resolves a Sub-Job declaration to a concrete Agens.Job.Sub.
Invoked when a tool call has been performed (successfully or not).
Invoked when all threads have converged on a yielding Node.
Invoked when a yielding Node is waiting on additional threads to converge.
Types
@type job_id() :: binary()
A Job identifier.
@type node_id() :: binary()
A Node identifier within a Job.
@type resource_load() :: %{resource: Agens.Resource.t(), error: binary() | nil}
Normalized record of a resource load as observed by a backend.
:resource is the resolved Agens.Resource when loading succeeded, or the original
declaration when it failed (the runtime falls back to the bare resource). :error is
nil on success or an inspected error reason string on failure.
@type run_id() :: binary()
A run identifier for a single Job invocation.
@type status() :: atom()
A Job status atom (e.g. :running, :complete, :error).
@type tool_call() :: %{ tool: %{name: binary(), arguments: map(), result: any() | nil}, error: binary() | nil }
Normalized record of a tool call invocation as observed by a backend.
The :tool key carries the call data (name, arguments, and the resolved result on success).
:error is nil on success or an inspected error reason string on failure. The outer shape
mirrors resource_load/0 to keep backend implementations symmetric.
Callbacks
Invoked when a Job completes by running every Node to completion (no Node returned :end).
Paired with the [:agens, :job, :complete] telemetry event. For Jobs that terminate because a
Serving's next returned :end, see ended/2.
Invoked when a Job terminates because a Serving's next returned an :end instruction.
Paired with the [:agens, :job, :end] telemetry event. Distinct from complete/2, which fires
when the Job runs to natural completion of all Nodes.
@callback error(pid(), Agens.Message.t(), any()) :: :ok
Invoked when a Job errors out. Receives the failing Agens.Message and the error reason.
@callback node_result(pid(), Agens.Message.t()) :: :ok
Invoked when a Node has produced a result from its Serving.
@callback node_retry(pid(), Agens.Message.t()) :: :ok
Invoked when a Node is being retried.
@callback node_started(pid(), Agens.Message.t()) :: :ok
Invoked when a Node begins processing.
@callback prompt(Agens.Message.t()) :: :ok
Invoked with the finalized Agens.Message after Agens.Prompt has built the system and user prompts.
Useful for logging, persistence or external prompt-rendering hooks.
@callback resource_load(pid(), Agens.Message.t(), resource_load()) :: :ok
Invoked when a resource has been loaded for a Node (successfully or not).
Invoked when a Job begins execution, immediately after Agens.Job.run/3 is accepted.
Fires once per Job run, paired with the [:agens, :job, :run] telemetry event. Distinct from
Agens.Job.start/2 (which only starts the supervised process and emits the [:agens, :job, :start]
telemetry event but no backend callback).
Invoked when a Job's status transitions (e.g. :init → :running).
@callback sub(job_id()) :: Agens.Job.Sub.t() | nil
Resolves a Sub-Job declaration to a concrete Agens.Job.Sub.
Backends in the configured list are consulted in order; the first to return a Sub wins.
Backends that don't handle the given job_id must return nil.
@callback tool_call(pid(), Agens.Message.t(), tool_call()) :: :ok
Invoked when a tool call has been performed (successfully or not).
@callback yield_done(pid(), Agens.Message.t(), integer()) :: :ok
Invoked when all threads have converged on a yielding Node.
@callback yield_wait(pid(), Agens.Message.t(), integer(), integer()) :: :ok
Invoked when a yielding Node is waiting on additional threads to converge.