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 ...
end

Most 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

@callback complete(pid(), run_id()) :: :ok

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.

@callback ended(pid(), run_id()) :: :ok

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.

Link to this callback

resource_load(pid, t, resource_load)

View Source
@callback resource_load(pid(), Agens.Message.t(), resource_load()) :: :ok

Invoked when a resource has been loaded for a Node (successfully or not).

Link to this callback

run(pid, job_id, run_id)

View Source
@callback run(pid(), job_id(), run_id()) :: :ok

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).

Link to this callback

status(pid, run_id, status)

View Source
@callback status(pid(), run_id(), status()) :: :ok

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.

Link to this callback

tool_call(pid, t, tool_call)

View Source
@callback tool_call(pid(), Agens.Message.t(), tool_call()) :: :ok

Invoked when a tool call has been performed (successfully or not).

Link to this callback

yield_done(pid, t, integer)

View Source
@callback yield_done(pid(), Agens.Message.t(), integer()) :: :ok

Invoked when all threads have converged on a yielding Node.

Link to this callback

yield_wait(pid, t, integer, integer)

View Source
@callback yield_wait(pid(), Agens.Message.t(), integer(), integer()) :: :ok

Invoked when a yielding Node is waiting on additional threads to converge.