Skip to main content

Use the CLI for A2A workflows

Message responses and errors default to readable text for interactive use. Pass --output json for full protocol responses, or --output ndjson before streaming commands when you need structured event output for automation or agent-driven workflows. Commands without a custom text formatter may still emit JSON in the default mode. Warnings print to stderr by default, so you see when an agent requires an extension you did not request or when its card routes requests somewhere unexpected. Add -v for informational logs or -d for debug logs.

Inspect an agent card first

Fetch the card for a configured server:
Some agents offer an extended card to authenticated clients that reveals skills or interfaces the public card omits. Fetch it when the public card advertises extendedAgentCard:
If the agent does not offer one, or advertises one but has none configured, Handler says so in one clear message instead of a raw protocol error. Validate the configured server’s card:
Validate a saved agent card file:
Use card validation before deeper debugging when you’re not sure whether the agent itself is advertising a valid card.

Send a message

Send a basic message to a configured server:
You can target a URL directly instead of a configured server:

Send files and structured data

Messages are not limited to text. Attach files with --file and structured data with --data; both options are repeatable and work on message send and message stream. A local path is read and sent inline as a file part, with the media type sniffed from the file:
An http(s) URL is sent by reference, so the agent fetches it:
Inline files are limited to 10 MiB; larger files are refused before anything is read, with a pointer at the URL form. Attach a JSON value as a data part:
--text is optional when at least one part is attached. When an agent replies with non-text parts, the text output summarizes them rather than dumping bytes into the terminal. A file part renders as [file: pixel.png, image/png, inline bytes, 70 bytes] (or with its URI when sent by reference), and a data part renders as a fenced JSON block. Whole numbers in data parts render as integers even though the protocol carries every number as a double. Use --output json to get the full parts, including inline bytes as base64.

Save what the agent sends back

Received file and data parts are summarised on screen; to get them onto disk, pass --save-artifacts DIR to message send, message stream, or task get:
Inline files are written under their declared filename, files by reference are downloaded (with the server’s credentials only if the file lives on the same origin), and data parts become <task-id>-<n>.json. Names are kept to their final component and never overwrite an existing file (report-2.pdf). Text parts are not saved; they are already on screen. In --output json mode the saved paths go to stderr so stdout stays a single JSON document.

Shape the request

The CLI exposes the SendMessageConfiguration fields the protocol attaches to a message. Tell the agent which media types you can render:
Ask for recent history on the task the agent returns:
Return as soon as the agent acknowledges with a task instead of waiting for it to finish. The submitted task is printed with its ID so you can poll it with task get or attach with task resubscribe:
--no-wait and --stream are mutually exclusive.

Request A2A extensions

Agents can declare extensions on their card. Ask for one on a single call with -e/--extension (repeatable):
Handler sends the URIs in the A2A-Extensions header on every request. To request an extension on every call to a server, list it in the server’s configuration instead; see Servers. If an agent marks an extension as required and you did not request it, Handler warns, since the agent may refuse or degrade the request.

Stream the response

Stream task events and response text from a configured server:
In text mode, streaming prints lightweight event: summaries for task state changes, tool calls, tool results, data/file parts, and response text before the final answer content. That makes it clear when the agent is still working even if the model’s text arrives in one larger chunk. Handler also prints the full task ID once when the stream starts so you can resubscribe if the server connection is interrupted. If you already use message send in scripts, adding --stream switches that same command to streaming mode. Otherwise, prefer the more explicit message stream command in examples and documentation. Use newline-delimited JSON when you want structured stream events:
Handler negotiates the transport from the agent card: it speaks JSON-RPC and HTTP+JSON out of the box, and gRPC when installed with the grpc extra (uv tool install 'a2a-handler[grpc]'). The card’s preference order decides. When the agent offers no binding this install speaks, the error names what the agent offers and what Handler can do about it. If you need to tune networking behavior, Handler exposes global timeout flags and matching environment variables. Values are seconds, or none to disable a specific timeout:
The same timeout settings are available as HANDLER_CONNECT_TIMEOUT, HANDLER_READ_TIMEOUT, HANDLER_WRITE_TIMEOUT, HANDLER_POOL_TIMEOUT, and HANDLER_STREAM_READ_TIMEOUT, including from a workspace .env file. Streaming disables the read timeout by default so long-running tasks are not aborted during idle gaps between SSE events.

Continue a saved conversation

Handler persists conversation identifiers locally so you can continue later:
Continue using Handler’s saved context and task IDs:
This is also how you answer an agent that paused in input-required: the saved task is still open, so --continue sends your reply on it. Inspect the saved session for a configured server:
If you already know the IDs you want, you can pass them explicitly:

Send custom payloads or headers

For agent-friendly invocation and integration testing, Handler exposes raw JSON input, structured output, and repeatable header flags:
You can also override saved auth with --bearer-env or --api-key-env. Custom headers and credentials are only sent to the origin of the agent URL you configured; see Authentication.

List an agent’s tasks

List every task the agent holds, following pagination to the end:
Text output is one line per task with its state and context. Narrow the listing by context or state:
States are submitted, working, completed, failed, canceled, input_required, rejected, and auth_required; hyphens are accepted too. Tune what each page carries. All pages are always fetched, so --page-size only changes the number of round trips; the protocol caps it at 100:
Handler stops a listing that is not making progress (a server repeating a page token, or more than 1000 pages) rather than looping forever. When that happens the result is marked truncated: text output says so, --output json carries a truncated field, and --output ndjson emits a final truncated record.

Work with tasks directly

Fetch the latest task status:
Include recent message history with the task response:
Cancel a running task:
Reconnect to a task’s SSE stream after interruption:
resubscribe is useful when a task uses streaming events and you need to attach again after a dropped server connection, or to follow a task you started with --no-wait.

Configure push notifications for tasks

Point a task at a webhook receiver:
You can also attach the webhook when you send the message, so the agent has it from the first event:
Inspect the current push config later. The protocol needs a config ID; when a task has exactly one config, Handler looks it up for you:
A task with several configs needs one named with --config-id. List them, with tokens redacted:
Remove a config. Handler checks it exists first, so a mistyped ID fails loudly instead of being silently accepted by a server that treats deletes as idempotent:
For a local receiver you can run the bundled webhook server described in Local servers.

Manage saved sessions

Handler stores session metadata locally so repeated CLI calls can reuse conversation state. List all saved sessions:
Show the saved session for a configured server:
Clear the saved session for one configured server:
Clear all saved sessions:
Use session clear when you want a clean slate without deleting the server definition itself.