Skip to content

Releases

v0.2.4

Choose a tag to compare

@benoitc benoitc released this 26 Oct 05:04
6289f8f

Changed

  • hackney 4.9.0 (was 4.8.4), h2 0.12.5 (was 0.12.3). Through them, certifi 2.18.0, quic 2.1.2 and webtransport 0.4.8.

v0.2.3

Choose a tag to compare

@benoitc benoitc released this 27 Sep 08:15
7e5fe3a

Dependency update. No API or behaviour change.

Changed

  • hackney 4.8.4 (was 4.7.4) and h2 0.12.3 (was 0.12.0). Through them, quic 2.0.1 and webtransport 0.4.7.
  • rebar3_lint 6.0.0 (development only).

v0.2.2

Choose a tag to compare

@benoitc benoitc released this 24 Sep 01:10
c55e730

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

Choose a tag to compare

@benoitc benoitc released this 23 Sep 22:33

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 a submitted or working task: the task gets a process again under its original id, and Fun(Ctx) runs in place of the handler. Its answer completes, fails or rejects the task like a handler result would. GetTask, CancelTask and streaming work as for any live task.
  • keep, for a task paused in input_required or auth_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, and barrel_a2a_push:open_store/3, close_store/1, store_owner/1.
  • The barrel_a2a_task_store callbacks take and return any map keyed by id (type entry()), which is how the stores already treated rows. Existing stores need no change.

Decision records 0007 and 0008 explain the design.

v0.2.0

Choose a tag to compare

@benoitc benoitc released this 20 Sep 18:44
1947a89

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_timeout defaults to infinity. A send with returnImmediately unset or false now waits for a terminal or interrupted state, as the specification requires, and ends early if the peer disconnects. Set blocking_timeout => 30000 for the old deadline, remembering that answering a blocking send with a non-final task is a deviation.
  • GetExtendedAgentCard refuses an anonymous caller with unauthenticated. A server running auth => none has no authenticated agent to serve it to; configure an authentication scheme, or supply a principal in 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 ListTasks pageSize outside 1 to 100 is rejected rather than clamped. ListTaskPushNotificationConfigs is unaffected: the specification gives it no bounds.
  • Unknown request fields are ignored by default, for forward compatibility. Set validate_schema => strict to 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_store with ETS and DETS backends.
  • Maintainer documentation under docs/internals/ and docs/decisions/.
  • Interop tests against a2a-python, @a2a-js/sdk and a2a-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.