Skip to main content

Protocol Reference

This document describes the A2A 1.0 surface exposed by the iac-code server and the Phase 1 client behavior used by iac-code a2a-client call. For exact CLI options, see Command Reference.

Lifecycle Overview

A typical A2A interaction follows this flow:

GET Agent Card -> SendMessage or SendStreamingMessage -> GetTask / follow-up / CancelTask
  1. Discover — Fetch /.well-known/agent-card.json.
  2. Send — Submit a text message to the JSON-RPC endpoint at /.
  3. Stream — Receive Task, Message, and TaskStatusUpdateEvent payloads.
  4. Continue — Send a follow-up message with the same contextId.
  5. Cancel or query — Use CancelTask, GetTask, or ListTasks.

Agent Card

The Agent Card is available at:

GET /.well-known/agent-card.json

Important fields:

FieldValueMeaning
nameiac-codeAgent name
supportedInterfaces[0].protocolBindingJSONRPCTransport binding
supportedInterfaces[0].protocolVersion1.0A2A protocol version
supportedInterfaces[0].urlhttp://<host>:<port>/JSON-RPC endpoint
capabilities.streamingtrueSupports streaming task updates
capabilities.pushNotificationsfalse or truetrue when push-notifications: true is configured
capabilities.extendedAgentCardtrueAuthenticated callers can request extended runtime details
capabilities.extensionsurn:iac-code:a2a:artifact-metadata:v1Optional iac-code metadata namespace for tool status and stored artifact metadata
defaultInputModestext, JSON, YAML, image, audio, and binary MIME typesAccepted input MIME modes
defaultOutputModes["text/plain"]Text output only

Agent Card responses include Cache-Control: public, max-age=60, ETag, and Last-Modified. Clients may send If-None-Match and receive 304 Not Modified when the card has not changed.

Advertised skills:

Skill IDPurpose
iac_generationGenerate Alibaba Cloud ROS and Terraform templates from natural language
iac_reviewInspect IaC templates and suggest fixes
aliyun_ros_operationsAssist with Alibaba Cloud ROS stack workflows
terraform_ros_conversionAssist Terraform-to-ROS conversion using bundled skill resources

When authentication is enabled, the Agent Card advertises the configured security schemes:

SchemeWhen advertised
bearerAuthtoken or IACCODE_A2A_HTTP_TOKEN is set
basicAuthBasic username and password are both set
apiKeyAuthapi-key or IACCODE_A2A_API_KEY is set

Routes

RouteMethodDescription
/healthGETReturns {"status":"healthy"}
/.well-known/agent-card.jsonGETReturns the Agent Card
/POSTHandles A2A JSON-RPC requests
REST routesmixedThe A2A SDK REST routes registered by create_rest_routes

Phase 1 Client and Transport Notes

The default interoperable Phase 1 transport is JSON-RPC over HTTP. HTTP mode also advertises HTTP+JSON for the SDK REST routes.

The server also has optional transports for stdio, Unix sockets, WebSocket, official gRPC, gRPC JSON-RPC envelope, and Redis Streams. stdio, Unix sockets, WebSocket, gRPC JSON-RPC, and Redis Streams are custom JSON-RPC transports. Official gRPC is advertised as grpc and requires optional gRPC dependencies.

The built-in client uses Agent Card discovery (GET /.well-known/agent-card.json) before message calls, selects the first advertised runnable supportedInterfaces[].url, then sends JSON-RPC requests with A2A-Version: 1.0 and A2A 1.0 method names such as SendMessage.

push-notifications: true enables A2A push notification configuration methods and terminal-state delivery.

Agent Card signing uses the A2A SDK signing utility and emits standard AgentCardSignature JWS fields. The symmetric-key mode uses HS256; verification can select a configured secret by protected-header kid, a local octet-key JWKS, or a remote JWKS URL. Server-side asymmetric signing and automatic key rotation are not implemented in Phase 1.

For the canonical list of unsupported Phase 1 behavior, see A2A Protocol.

Push Notification Delivery Backends

iac-code a2a --config a2a-server.yml supports two push delivery queues:

  • push-queue: local-file stores jobs below the A2A persistence directory and is intended for local single-node use.
  • push-queue: redis-streams stores jobs in Redis Streams and coordinates workers through a Redis consumer group.

Redis-backed push delivery requires the optional a2a-redis extra and is at-least-once. Callback receivers should handle task updates idempotently because a job can be delivered again after worker crashes, lease expiry, reconnects, or retry races.

Common Redis options:

push-notifications: true
push-queue: redis-streams
push-redis-url: redis://localhost:6379/0
push-stream: iac-code:a2a:push
push-retry-key: iac-code:a2a:push:retry
push-dead-stream: iac-code:a2a:push:dead
push-consumer-group: iac-code-push
push-consumer-name: worker-1
push-lease-timeout-ms: 300000

Callback URLs are validated before storage and again before dispatch. The default validator rejects non-HTTP(S) URLs, localhost hostnames, and literal private/local IP addresses. Callback receivers should still enforce their own authentication and idempotency policy.

JSON-RPC Methods

SendMessage

Runs a non-streaming A2A message turn. The response contains a task or message after the turn has completed.

Request

{
"jsonrpc": "2.0",
"id": "1",
"method": "SendMessage",
"params": {
"message": {
"messageId": "msg-1",
"role": "ROLE_USER",
"parts": [{"text": "Create a VPC with two vSwitches."}],
"metadata": {
"iac_code": {"cwd": "/absolute/path/to/project"}
}
},
"configuration": {
"acceptedOutputModes": ["text/plain"]
}
}
}

Required message fields

FieldTypeRequiredDescription
messageIdstringYesUnique client message ID
rolestringYesUse ROLE_USER for user input
partsarrayYesText-like, JSON data, raw text, local file URL, or bounded multimodal parts
metadata.iac_code.cwdstringRecommendedAbsolute workspace path; defaults to the server process directory if omitted

metadata.iac_code.cwd must be an existing absolute directory when provided. It must be inside an allowed workspace root. By default, allowed roots are the server process directory and the system temp directory; IACCODE_A2A_ALLOWED_CWDS can provide an OS-path-separated allowlist.

Supported input categories:

CategoryAccepted ShapeLimits and Behavior
Text-like partstext with text/plain, JSON, Markdown, YAML, or configured extra text MIME typesAppended directly to the prompt
JSON data partsdata with application/jsonSerialized into compact JSON; max 1 MiB inline
Raw text partsraw with a text-like MIME typeMust be valid UTF-8; max 1 MiB inline
Local text file URLsurl with file://... and text-like MIME typeFile must exist inside cwd and allowed roots; max 1 MiB
Multimodal raw/data/file partsimage, audio, or configured multimodal MIME typesConverted into a prompt manifest with filename, media type, byte size, hash, and source; raw/data max 5 MiB, file URL max 25 MiB

Remote HTTP(S) URL ingestion is not supported. File URL parts must use local file:// URLs and remain inside the allowed workspace.

SendStreamingMessage

Runs a streaming A2A message turn. The request body has the same shape as SendMessage, but the server streams JSON-RPC responses as Server-Sent Events.

{
"jsonrpc": "2.0",
"id": "2",
"method": "SendStreamingMessage",
"params": {
"message": {
"messageId": "msg-2",
"role": "ROLE_USER",
"parts": [{"text": "Review this ROS template."}],
"metadata": {
"iac_code": {"cwd": "/absolute/path/to/project"}
}
},
"configuration": {
"acceptedOutputModes": ["text/plain"]
}
}
}

GetTask

Returns the saved A2A task by ID. Use historyLength to limit returned history without mutating stored task history. Omit it to receive the server's current default history.

{
"jsonrpc": "2.0",
"id": "3",
"method": "GetTask",
"params": {
"id": "task-id",
"historyLength": 10
}
}

ListTasks

Returns known tasks visible to the authenticated caller. Results are sorted by status timestamp descending, then task ID descending for stable ordering. The server supports contextId, status, pageSize, pageToken, historyLength, and includeArtifacts.

{
"jsonrpc": "2.0",
"id": "4",
"method": "ListTasks",
"params": {
"contextId": "ctx-id",
"status": "TASK_STATE_WORKING",
"pageSize": 20,
"includeArtifacts": false
}
}

nextPageToken is returned when another page is available. includeArtifacts defaults to false, so list responses omit task artifacts unless explicitly requested.

CancelTask

Requests cancellation for a running task.

{
"jsonrpc": "2.0",
"id": "5",
"method": "CancelTask",
"params": {
"id": "task-id"
}
}

If the task is active, the server cancels the running agent turn and emits a canceled task state. If the task exists but is not running, the server returns the standard A2A TaskNotCancelableError.

SubscribeToTask

Subscribes to an active task update stream when supported by the client transport.

{
"jsonrpc": "2.0",
"id": "6",
"method": "SubscribeToTask",
"params": {
"id": "task-id"
}
}

For active tasks, the stream starts with the current Task, then emits subsequent task events and closes when the active turn finishes. Subscribing to a completed, failed, canceled, or input-required task returns a task-not-found style error instead of waiting indefinitely. For new turns, prefer SendStreamingMessage; it starts execution and streams the response in one request.

Push Notification Config Methods

When the server starts with push-notifications: true, it supports:

MethodPurpose
CreateTaskPushNotificationConfigStore a callback config for a task
GetTaskPushNotificationConfigFetch one callback config
ListTaskPushNotificationConfigsList callback configs for a task
DeleteTaskPushNotificationConfigDelete a callback config

Example create request:

{
"jsonrpc": "2.0",
"id": "7",
"method": "CreateTaskPushNotificationConfig",
"params": {
"taskId": "task-id",
"id": "webhook-1",
"url": "https://hooks.example.com/a2a",
"token": "notification-token",
"authentication": {
"scheme": "bearer",
"credentials": "callback-token"
}
}
}

The server encrypts stored notification tokens and callback authentication credentials when the local push keyring is available.

GetExtendedAgentCard

Authenticated clients can request the extended Agent Card:

{
"jsonrpc": "2.0",
"id": "8",
"method": "GetExtendedAgentCard",
"params": {}
}

The extended card includes the public card plus authenticated runtime details.

Task and Context Behavior

iac-code maps A2A contexts to internal agent runtimes:

ConceptBehavior
contextId omittedThe SDK/server generates a new context ID
Same contextIdReuses the same internal iac-code session and conversation state
Same contextId, different cwdRejected as a different workspace
Same contextId, concurrent messageRejected with Task is already working.
Different contextId valuesCan execute concurrently
Idle contextEvicted from memory after the configured idle timeout

Task and context IDs must be non-empty, at most 128 characters, and contain only letters, digits, _, ., :, or -.

Task States

StateMeaning
TASK_STATE_SUBMITTEDThe task was accepted
TASK_STATE_WORKINGiac-code is running the agent turn
TASK_STATE_INPUT_REQUIREDThe turn completed and the agent is ready for follow-up input
TASK_STATE_CANCELEDCancellation was requested and applied
TASK_STATE_FAILEDThe task failed validation or execution

iac-code uses TASK_STATE_INPUT_REQUIRED as the normal completed state because the context remains available for follow-up messages.

Streaming Updates

During execution, iac-code emits TaskStatusUpdateEvent updates.

Assistant text is delivered as a status message:

{
"statusUpdate": {
"taskId": "task-1",
"contextId": "ctx-1",
"status": {
"state": "TASK_STATE_WORKING",
"message": {
"role": "ROLE_AGENT",
"parts": [{"text": "Here is the ROS template..."}]
}
}
}
}

Tool and usage details are delivered through metadata.iac_code:

Metadata PathDescription
iac_code.tool.statusstarted, input_delta, input_complete, completed, or failed
iac_code.tool.toolUseIdStable tool-use ID for correlating tool events
iac_code.tool.nameTool name when available
iac_code.tool.inputCompleted tool input, truncated to 4000 characters per field
iac_code.tool.resultTool result, truncated to 4000 characters per field
iac_code.permission.autoApprovedfalse when a tool permission request was rejected by A2A server mode
iac_code.thinking.typeraw_thinking when raw-thinking is enabled in thinking-exposure
iac_code.thinking.textRaw provider reasoning chunk, truncated to 4000 characters, emitted only for trusted configurations that enable raw-thinking
iac_code.usage.inputTokensInput token count for the turn
iac_code.usage.outputTokensOutput token count for the turn
iac_code.usage.totalTokensTotal token count for the turn

When a tool result includes a supported text artifact payload, the server stores the payload locally, emits a standard TaskArtifactUpdateEvent, and records the artifact in the task artifacts field. The artifact part uses a file:// URL plus metadata such as mediaType, byteSize, and sha256; the original artifact content is not duplicated inside tool metadata.

Extensions

The Agent Card advertises the optional iac-code artifact metadata extension:

urn:iac-code:a2a:artifact-metadata:v1

This extension identifies the metadata.iac_code namespace used for tool progress, permission decisions, token usage, and local artifact metadata. If the server is configured with any required extension, clients must include its URI in the A2A-Extensions header. Missing required extensions return the standard A2A ExtensionSupportRequiredError.

When thinking-exposure enables one or more signal types, the Agent Card also advertises:

urn:iac-code:a2a:thinking-exposure:v1

The extension params include enabledTypes, such as ["tool_trace", "raw_thinking"]. This is an iac-code metadata extension, not a core A2A streaming event type.

Error Handling

ScenarioResult
Empty text inputTASK_STATE_FAILED with A2A server currently accepts text input only.
Unsupported media typeValidation error or standard A2A content-type error, depending on where the SDK rejects the request
Remote URL partValidation error because URL parts must use local file:// URLs
File URL outside allowed workspaceValidation error
Missing required A2A extensionStandard A2A ExtensionSupportRequiredError
Invalid workspace metadataTASK_STATE_FAILED with an invalid workspace message
Missing or invalid authenticationHTTP 401 with {"error":"Unauthorized"}
Missing A2A server dependenciesCLI exits with an install hint for the a2a extra
Provider credentials missingSanitized authentication error
Unexpected runtime errorSanitized internal error

The server avoids returning local paths, secrets, and provider details in unexpected error messages.