feat: Talk to agents over A2A (agent card / send / task) - #33
Merged
Merged
Conversation
Every agent bound to a workspace answers over the A2A protocol. This binds the A2A v1.0 HTTP+JSON surface — the unversioned `/a2a/...` paths; the `/a2a/v1/` paths are protocol 0.3 despite their name — and leaves the JSON-RPC endpoint and the 0.3 REST surface alone. Core gains `get_json_with_headers` / `post_json_with_headers` for endpoints whose success body is a bare document rather than an envelope (errors still arrive as envelopes and decode as before), `post_event_stream` plus an SSE parser for `message:stream`, and `describe_a2a_error`, which lifts the A2A message and reason out of the escaped document the envelope carries. `agent send` blocks by default, prints the reply on stdout and the task / context / state on stderr. `--stream` prints fragments as they land and suppresses the closing artifact that repeats them; `--no-wait` sets `returnImmediately`; `--raw` prints the protocol JSON. `--actor`, `--project`, `--read-only-project`, `--skip-memory` map onto `metadata.memorylake`, with `--metadata-json` for the rest. `agent task get|feedback` send the `A2A-Extensions` header, without which the server hides ratings. Measured against production: default send is blocking, feedback records without the header but only reads back with it, a permission failure on the stream endpoint comes as a JSON envelope, and cancelling a finished task answers `TASK_NOT_CANCELABLE`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The CI account carries hundreds of scratch workspaces, so the default workspace is not on the first page there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Binds the A2A protocol endpoints in the open-api to the CLI, under the existing
agenttree:All take
--workspacewith the same default asagent bind.Design decisions
/a2a/...paths are v1.0; the/a2a/v1/paths are protocol 0.3 (confirmed by the agent card'ssupportedInterfaces). JSON-RPC and the 0.3 REST surface are not bound.serde_json::Value. The API documents them without a schema; success bodies are bare A2A documents, not envelopes. Errors still arrive as envelopes, anddescribe_a2a_errorlifts the A2A message +reasonout of the escaped document sotask cancelon a finished task saysTask cannot be canceled - current state: 3 (TASK_NOT_CANCELABLE)rather than a blob of\".sendblocks by default (measured: production returnsTASK_STATE_COMPLETEDwith artifacts in a few seconds). Reply text → stdout,task … context … state …→ stderr, so scripts can pipe the reply and still continue the thread.TASK_STATE_INPUT_REQUIREDprints how to answer.--streamreads the SSE body with a small parser incore::sse. Production streams the reply token-by-token instatusUpdateevents and then once more in full as anartifactUpdate; the artifact is printed only when nothing was streamed.A2A-Extensions: extensions://task-feedback/v1is sent ontask get,task listandtask feedback. Measured: feedback records without the header, buttask getonly showsmetadata."task-feedback/v1"with it.--actoris not defaulted toactor me; production accepts an actor that is not bound to the workspace, but the server's own default is the right fallback.Not in this PR
agent task subscribe(reattaching to a--no-waittask's stream), and flattened flags foroverrides— those go through--metadata-json.Tests
--stream/--no-waitconflict, feedback validation,--page-sizerange.a2a_round_trip_against_the_default_agent— card → send (--skip-memory) → task get → list → feedback → cancel refused → stream prints once. Passes locally; fullcargo test --workspacegreen apart from the known transport flakiness when live tests run in parallel.🤖 Generated with Claude Code