Skip to main content

Overview

Chat A2A agents communicate over HTTPS using the A2A (Agent-to-Agent) v2 JSON-RPC protocol. Unlike the standard Chat (HTTP) integration which uses a free-form request/response shape, A2A defines a structured message/send envelope with stateful conversation tracking via contextId and taskId, and an explicit end-of-conversation signal via result.status.state. When to use Chat A2A instead of Chat (HTTP) or Chat WebSocket:
  • Your agent implements the A2A v2 JSON-RPC specification
  • Your agent requires OAuth2 token exchange before accepting messages
  • Your agent uses contextId / taskId to maintain conversation state across turns
  • Your agent signals end-of-conversation through a structured status field rather than a chat reply

Conversation Flow

A2A conversations follow a fixed three-phase shape:
  1. Initialization — Coval calls your initialization_endpoint (typically OAuth2 client_credentials) and captures the returned access token for use as the Authorization: Bearer … header on subsequent requests.
  2. Message turns — Coval sends each persona message to your chat_endpoint as a JSON-RPC message/send request. After the first turn, every request echoes back the contextId and taskId returned by the previous response so your agent can maintain conversation state.
  3. Termination — When your agent’s response sets result.status.state to completed or failed (configurable), Coval shuts down the simulation cleanly and finalizes the transcript.

Configuration

Initialization

If your agent requires an access token, configure the initialization endpoint and payload. Coval calls it once at the start of each simulation, captures access_token from the response, and uses it as Authorization: Bearer … for every subsequent chat request.
Configuration:
Request Coval sends:
Response your auth endpoint should return:
Coval extracts access_token and uses it as Authorization: Bearer eyJhbGc... for every chat request in the simulation. Other fields (token_type, expires_in, scope) are captured but not interpreted.
If you don’t need authentication, leave Initialization Endpoint blank — Coval will skip the init phase and call your chat endpoint directly.

Message Format

Sending Messages (Coval to Agent)

Each persona turn is sent as a JSON-RPC 2.0 message/send request. Coval auto-generates a fresh messageId (UUIDv4) per turn and echoes the previous turn’s contextId and taskId.
On turn 1, contextId and taskId are empty strings — your agent should treat that as a new conversation and return its own values in the response. The metadata object is whatever you configured under Custom Data.
contextId and taskId are present at both params.* and params.message.* for compatibility with strict A2A v2 implementations.

Receiving Messages (Agent to Coval)

Coval extracts the assistant text from the path configured under Response Message Path (default: result.artifacts.0.parts.0.text) and the conversation state from Response State Extraction.
From this response Coval extracts:
  • Reply text from result.artifacts.0.parts.0.text → played back to the persona
  • contextId from result.contextId → echoed on the next request
  • taskId from result.id → echoed on the next request
  • End-state from result.status.state → if "completed" or "failed", simulation terminates
A2A is text-only. All content the persona needs to act on must be serialized into parts[*].text. If your agent embeds rich content (lists, tables, attachments) as a structured non-text part or relies on a UI widget rendered outside the JSON-RPC payload, the simulator will not see it and the persona may loop or stall waiting for context that never arrives.
If your agent returns multiple parts on the same artifact, Coval automatically picks the longest text part (some A2A implementations return a short header in parts[0] and the full content in parts[1]).

State Extraction

Response State Extraction tells Coval where to find the contextId and taskId your agent returns on each turn so they can be echoed back on the next request. The defaults match the A2A v2 specification:
If your agent returns these values at different paths, override the map. The keys must be contextId and taskId (those are the slots Coval echoes back); the values are the dot-notation paths into your agent’s response. Once captured, both values are sent on the next request at params.contextId, params.taskId, params.message.contextId, and params.message.taskId for compatibility with strict A2A v2 implementations.

End-State Detection

Coval checks every response against End State Path / End State Values. When the value at End State Path matches one of End State Values, the simulation finalizes cleanly after the current turn. The defaults (result.status.state["completed", "failed"]) match the A2A v2 specification. Override them if your agent uses different terminal states:

Setup Instructions

1

Create the agent

Create a new agent from the Agents tab in the Coval platform, or via the Coval API with model_type: "MODEL_TYPE_CHAT_A2A" and the metadata fields described under Configuration above.
2

Configure initialization

If your agent requires authentication, set the initialization endpoint, payload, and content type. Otherwise leave them blank.
3

Pass user context via Custom Data

Any per-conversation identifiers your agent expects (user IDs, channel IDs, locale) go into Custom Data — they’re merged into params.metadata on every chat request.
4

Verify response shape

If your agent’s response paths differ from the defaults, set Response Message Path, Response State Extraction, End State Path, and End State Values to match what your agent actually returns.
5

Test with a single test case

Create a test set with one test case and launch a simulation to verify connectivity, state echoing, and end-state detection before scaling up.

Common Patterns

All response paths use defaults — no further configuration needed.
No initialization request — Coval sends the static Authorization header on every chat request. Use this when your agent accepts a long-lived API token instead of requiring an OAuth2 exchange per simulation.

Troubleshooting

Initialization Failures

“Failed A2A initialization request”
  • Verify the initialization endpoint URL is correct and reachable from Coval servers
  • Check that the content type matches what the endpoint expects (form vs JSON)
  • Confirm the credentials in the initialization payload are valid
Auth works on init but chat requests return 401
  • Confirm the init response includes a top-level access_token field — that’s what Coval extracts
  • If your token field has a different name, set it via Authorization Header directly and skip the init endpoint

State Not Persisting Across Turns

  • Check that Response State Extraction paths actually resolve in your agent’s response (test with a direct request)
  • Confirm your agent reads contextId / taskId from the request and uses them to look up conversation history
  • A2A v2 expects state at both params.contextId and params.message.contextId — Coval sends both

Conversation Never Ends

  • Verify End State Path resolves to a non-null value in your agent’s responses
  • Confirm at least one End State Value matches what your agent actually returns when the conversation completes
  • If your agent never sends a terminal state, configure a reasonable test-case length so the simulation isn’t open-ended

Persona Loops or Stalls Mid-Conversation

  • Check that all content the persona needs is serialized as plain text in parts[*].text
  • If your agent produces a short header in parts[0] and the full content in parts[1], Coval picks the longest — but neither should reference content that lives outside the JSON-RPC payload (e.g., “see the attached list”)

Technical Requirements