Repository navigation
Releases
v0.2.4
v0.2.3
v0.2.2
A task store can now be replicated or shared between nodes.
Fixed
Task store rows no longer carry the pid of the task process. The registry keeps pids in a table on its own node, keyed by task id. Before, a row written by another node (a replicated or shared task_store) made server start fail with badarg in is_process_alive/1. Such a row is now handled like one left by a restart: an unfinished task is failed or offered to resume, and a finished one is read from the store.
A pid left in a row by 0.2.1 is dropped on open. Stores need no change.
Decision record 0009 explains the design.
v0.2.1
Tasks and their webhooks can outlive a server restart when tasks are persisted. Nothing changes unless you set the new options.
Resuming unfinished tasks
The new resume server option, fun((Task) -> {resume, Fun} | keep | fail), is asked on start about each unfinished task found in the task store.
{resume, Fun}, for asubmittedorworkingtask: the task gets a process again under its original id, andFun(Ctx)runs in place of the handler. Its answer completes, fails or rejects the task like a handler result would.GetTask,CancelTaskand streaming work as for any live task.keep, for a task paused ininput_requiredorauth_required: the task stays paused, and the client's next message continues it through your handler.fail, no option, a crash, or an answer that does not fit the task's state: the task is failed with "Task interrupted by a server restart", as before.
When a resumed task is cancelled, its fun sees barrel_a2a_ctx:cancelled/1 answer true and has 5 seconds to return. See "Resuming unfinished tasks" in guides/server.md.
Push configs across restarts
The new push_config_store option takes any barrel_a2a_task_store, such as the DETS store, and keeps push notification configs across restarts. A webhook registered before a restart is now told how its task ends. On start, a config whose task has expired is dropped, and a config whose task already finished gets the task's final status delivered again (delivery is at least once). See "Across restarts" in guides/push-notifications.md.
API
barrel_a2a_task_registry:new/2, andbarrel_a2a_push:open_store/3,close_store/1,store_owner/1.- The
barrel_a2a_task_storecallbacks take and return any map keyed byid(typeentry()), which is how the stores already treated rows. Existing stores need no change.
Decision records 0007 and 0008 explain the design.
v0.2.0
Conformance work against A2A v1.0.1, maintainer documentation, and interop testing against three reference SDKs.
Breaking changes
Five changes are visible to a running deployment. Each says what to set to keep the old behaviour.
blocking_timeoutdefaults toinfinity. A send withreturnImmediatelyunset or false now waits for a terminal or interrupted state, as the specification requires, and ends early if the peer disconnects. Setblocking_timeout => 30000for the old deadline, remembering that answering a blocking send with a non-final task is a deviation.GetExtendedAgentCardrefuses an anonymous caller withunauthenticated. A server runningauth => nonehas no authenticated agent to serve it to; configure an authentication scheme, or supply aprincipalin the request context if your embedding authenticates the peer.- A duplicate JSON key keeps the last occurrence, as ProtoJSON requires. It previously kept the first.
- An explicit
ListTaskspageSizeoutside 1 to 100 is rejected rather than clamped.ListTaskPushNotificationConfigsis unaffected: the specification gives it no bounds. - Unknown request fields are ignored by default, for forward compatibility. Set
validate_schema => strictto reject them as before.
Conformance
ListTasks applies authorization inside the registry filter, so totalSize and nextPageToken no longer describe rows the caller cannot see, and statusTimestampAfter is inclusive. validate_schema => all now covers streamed events, not only unary replies. Push delivery never discards an event to make room: a full queue counts as a delivery failure, so a receiver that cannot keep up loses its configuration rather than silently missing notifications. A field sent as JSON null is read as unset, which is what ProtoJSON requires.
Resource bounds
Every buffer a peer can fill is bounded with a stated policy: task follow-ups (max_task_queue), stream subscribers (max_subscriber_queue), the push queue and worker mailbox (max_queue), client stream listeners (max_listener_queue), client replies and Agent Cards (max_body), and webhook responses. max_history optionally caps stored task history, defaulting to unlimited. A failed init/1 cleans up after itself, and losing a supervisor or the task store's writer stops the server so it is rebuilt.
Added
- Pluggable task storage:
barrel_a2a_task_storewith ETS and DETS backends. - Maintainer documentation under
docs/internals/anddocs/decisions/. - Interop tests against
a2a-python,@a2a-js/sdkanda2a-go: 102 cases, both directions, both HTTP bindings. make check-vectors, which compares the vendored schema and proto against what upstream publishes.
Full detail in CHANGELOG.md.