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 structuredmessage/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/taskIdto 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:- Initialization — Coval calls your
initialization_endpoint(typically OAuth2client_credentials) and captures the returned access token for use as theAuthorization: Bearer …header on subsequent requests. - Message turns — Coval sends each persona message to your
chat_endpointas a JSON-RPCmessage/sendrequest. After the first turn, every request echoes back thecontextIdandtaskIdreturned by the previous response so your agent can maintain conversation state. - Termination — When your agent’s response sets
result.status.statetocompletedorfailed(configurable), Coval shuts down the simulation cleanly and finalizes the transcript.
Configuration
| Field | Required | Description |
|---|---|---|
| Chat Endpoint | Yes | URL Coval POSTs each JSON-RPC message/send request to |
| Initialization Endpoint | No | URL Coval calls once per simulation to obtain credentials (e.g., OAuth2 token endpoint) |
| Initialization Payload | No | Body sent to the initialization endpoint. Stored as JSON; encoded based on Initialization Content-Type |
| Initialization Content-Type | No | application/x-www-form-urlencoded (default) or application/json |
| Authorization Header | No | Static auth value. Overridden automatically when the initialization response contains access_token |
| Custom Headers | No | Additional headers sent on every chat request |
| Response Message Path | No | Dot-notation path to the agent’s reply text. Default: result.artifacts.0.parts.0.text |
| Response State Extraction | No | JSON paths to the contextId and taskId Coval echoes back on each turn. Default: {"contextId": "result.contextId", "taskId": "result.id"} |
| End State Path | No | Dot-notation path to the conversation status field. Default: result.status.state |
| End State Values | No | List of status values that terminate the conversation. Default: ["completed", "failed"] |
| Custom Data | No | Arbitrary JSON object merged into params.metadata on every chat request (e.g., user identifiers required by your agent) |
Initialization
If your agent requires an access token, configure the initialization endpoint and payload. Coval calls it once at the start of each simulation, capturesaccess_token from the response, and uses it as Authorization: Bearer … for every subsequent chat request.
Example: OAuth2 client_credentials initialization
Example: OAuth2 client_credentials initialization
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.Message Format
Sending Messages (Coval to Agent)
Each persona turn is sent as a JSON-RPC 2.0message/send request. Coval auto-generates a fresh messageId (UUIDv4) per turn and echoes the previous turn’s contextId and taskId.
Example: Turn 1 request envelope
Example: Turn 1 request envelope
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.Example: Turn 2+ request envelope (with echoed state)
Example: Turn 2+ request envelope (with echoed state)
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.
Example: Expected response shape
Example: Expected response shape
- Reply text from
result.artifacts.0.parts.0.text→ played back to the persona contextIdfromresult.contextId→ echoed on the next requesttaskIdfromresult.id→ echoed on the next request- End-state from
result.status.state→ if"completed"or"failed", simulation terminates
parts[0] and the full content in parts[1]).
State Extraction
Response State Extraction tells Coval where to find thecontextId 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:
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
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.Configure initialization
If your agent requires authentication, set the initialization endpoint, payload, and content type. Otherwise leave them blank.
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.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.
Common Patterns
Pattern 1: OAuth2 client_credentials with default A2A v2 paths
Pattern 1: OAuth2 client_credentials with default A2A v2 paths
Pattern 2: Static bearer token, no init endpoint
Pattern 2: Static bearer token, no init endpoint
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
- Confirm the init response includes a top-level
access_tokenfield — 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/taskIdfrom the request and uses them to look up conversation history - A2A v2 expects state at both
params.contextIdandparams.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 inparts[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
| Requirement | Details |
|---|---|
| Protocol | A2A v2 JSON-RPC over HTTPS |
| Method | message/send |
| Content type (chat) | application/json |
| Content type (init) | Configurable (application/x-www-form-urlencoded default, application/json supported) |
| Accessibility | Endpoints must be publicly accessible from Coval servers |
| Payload size | Standard HTTP limits apply |

