View Source Changelog
0.2.0 (2026-05-22)
A substantial redesign of the framework around dynamic routing, MCP-shaped tools/resources, and a pluggable backend layer. Jobs are now a list of Agens.Job.Nodes instead of a sequence of Steps, routing is decided per-request by an Agens.Router on top of structured outputs, and observability/persistence are unified under the Agens.Backend behaviour. The framework is intentionally adapter-less: LM provider integration lives in your Serving's Agens.Serving.handle_message/3 callback, and tool calls are surfaced through the structured-output schema rather than per-provider tool-call APIs.
See Host Application Responsibilities and Design Philosophy for the new boundaries and the reasoning behind them.
Features
- Added
Agens.Job.Node— graph nodes referencing a Serving, with optional:agent_id,:objective,:tools,:resources, and:sub(Sub-Job) fields. - Added
Agens.Routerbehaviour withAgens.Router.outputs/1andAgens.Router.resolve/2. Supports graph-based, sequential, and LM-driven dynamic routing through a single behaviour. Seeexamples/router/. - Added
Agens.Router.OutputandAgens.Router.Conditionfor declaring structured-output schemas and branching on them. - Added parallel routing primitives:
{:route, node_id, count}for fan-out,{:yield, node_id}for aggregation,{:sub, job_id}for chained Sub-Jobs,:endfor explicit termination, and:retry(or{:retry, reason}) for validation-driven retries. - Added
Agens.Job.Suband Sub-Job composition. A Node can run a Sub-Job in place of inference (mapped back viaAgens.Serving.handle_sub/3) or chain one after inference via{:sub, job_id}. - Added
Agens.Backendbehaviour as the single extension point for observability and persistence. Backends are chainable; every configured backend receives every lifecycle/Node/tool/resource/Sub event in declaration order. - Added default backends: an in-process emit backend (sends events to the caller process) and a structured-log backend.
- Added
Agens.Resourcestruct for MCP-shaped resources (URI, name, optional description, content). - Added per-Serving FIFO queue and configurable in-flight limit via
use Agens.Serving, limit: N. - Added per-Serving timeout enforcement via
Agens.Serving.Config.timeout. - Added validation-driven retry loop:
Agens.Serving.handle_result/3can return{:retry, reason}to re-run the Node with the reason injected under theRetryprefix, bounded byAgens.Job.Config.max_retries. - Added MCP-shaped tools and resources. Tools attach per-Node via
:toolsand are executed byAgens.Serving.tool_call/3; resources attach via:resourcesand are loaded byAgens.Serving.load_resource/3. - Added strict structured outputs — JSON schema assembled per-request from the Router's declared
Agens.Router.Outputlist, compatible with OpenAI strict mode and similar grammar-constrained sampling. - Added layered prompt customization:
Agens.Prefixes(heading/detail per section),Agens.Serving.build_prompt/3(full prompt construction), andoutputs_schema/1/tools_schema/1/response_schema/1/build_schema/1(schema customization). - Added
Agens.Metricswith comprehensiveTelemetry.Metricsdefinitions covering Job, Node, Sub, Serving, tool, and resource lifecycle. - Added
Agens.Job.Config.from_json/1for JSON-defined Job configurations. - Added
run_id-keyed parallel execution. The sameAgens.Job.Configcan be started many times with distinctrun_ids viaAgens.Job.start/2+Agens.Job.run/3. - Added MCP example under
examples/mcp/usinghermes_mcpfor a working tool/resource server + client. - Added Host Application Responsibilities and Design Philosophy documentation.
Breaking Changes
- Removed
Agens.Agentmodule.agent_idsurvives as an opaquebinary()identifier used byAgens.Serving.load_context/2. - Removed
Agens.Job.Step. Jobs are now a map ofAgens.Job.Nodes with a designated:starting_node_id, not a sequence of Steps. - Removed static
:nextfield from Nodes. Routing is dynamic and decided per-request by the Serving's Router. - Removed first-class Bumblebee /
Nx.Servingintegration. Both are still supported throughAgens.Serving.handle_message/3like any other LM, but no longer ship as built-in adapters. - Removed
:prefixesoption fromAgens.Supervisor. Set prefixes per-Serving viaAgens.Serving.Config. - Changed Job addressing:
Agens.Job.start/2now takes arun_idandAgens.Job.run/3begins execution. Jobs are addressed byrun_id, not name. - Changed observability: lifecycle events now flow through the
Agens.Backendbehaviour instead of a single emit target. Defaults preserve the prior emit-to-caller behaviour. - Changed tool calls: now configured per-Node via
:toolsand executed byAgens.Serving.tool_call/3, modeled after MCP tool calls. - Changed identifiers from
any()tobinary()acrossjob_id,run_id,agent_id, and Node ids. - Removed
finalizefromAgens.Serving.Configin favor of Serving callbacks.
0.1.3
This release introduces a single-file Phoenix LiveView example that can be run with elixir examples/phoenix.exs.
In addition, this release removes the use of Registry, adds better error handling, and improves GenServer usage, including better child specs.
Features
- Added
examples/phoenix.exsexample - Added
Agens.Prefixes - Added pass-through
argsandfinalizefunction toAgens.Serving Added
{:job_error, {job.name, step_index}, {:error, reason | exception}}event toAgens.Job- Added child specs to
AgensandAgens.Supervisor - Added
{:error, :job_already_running}when calling Agens.Job.run/2 on running job - Added
{:error, :input_required}when callingMessage.send/1with emptyinput
Breaking Changes
- Removed
Registryusage andregistryconfiguration option - Changed
promptstoprefixesonAgens.Serving.Config - Added
inputto@enforce_keysand removednilas acceptedinputtype inAgens.Message
Fixes
- Removed
restart: :transientfromAgens.ServingandAgens.Agentchild specs
0.1.2
This release removes application environment configuration and moves to an opts-based configuration. See README.md for more info.
Features
- Configure
AgensviaSupervisoropts instead ofApplicationenvironment - Add
Agens.Agent.get_config/1 - Add
Agens.Serving.get_config/1 - Support sending
Agens.MessagewithoutAgens.Agent - Override default prompt prefixes with
Agens.Serving
Fixes
Agens.Job.get_config/1now wraps return value with:oktuple:{:ok, Agens.Job.Config.t()}Replaced
module() | Nx.Serving.t()withatom()inAgens.Agent.Config.t()
0.1.1
Initial release