Call an agent
Send a request to a registered agent.
Endpoint
Each registered agent has its own address at the gateway:
https://gateway.corevalue.dev/a2a/<agent-id>Its agent card is at:
https://gateway.corevalue.dev/a2a/<agent-id>/.well-known/agent-card.jsonThe card is the agent's own, rewritten so that every endpoint in it points at the gateway. Reading it needs the same key as a call, and the caller must be one the agent allows.
Authentication
Send a CoreValue API key as Authorization: Bearer <CoreValue API key>. Keys in the URL are refused. The agent never sees your CoreValue key: CoreValue sends the agent the credential stored for it, if any.
Protocol versions
A2A 0.3 and 1.0 clients both work, whichever version the agent speaks: the gateway translates the request and the answer, streamed answers included. The caller's version is read from its A2A-Version header, or from the method's name when it sends none. A field that one version cannot carry is refused with an error that names it, never dropped.
curl https://gateway.corevalue.dev/a2a/billing \
-H "Authorization: Bearer $COVA_API_KEY" \
-H "Content-Type: application/json" \
-H "A2A-Version: 1.0" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "SendMessage",
"params": {
"message": {
"messageId": "4f8c2a1e-6b1d-4c3e-9a57-0d2e8b7f1c90",
"role": "ROLE_USER",
"parts": [{ "text": "What is the balance on invoice 1042?" }]
}
}
}'Task trace
Every answer carries two response headers:
Cova-Task-Trace: the task trace this call joined, as<trace-id>;parent=<call-id>.Cova-Call-Id: this call's id.
CoreValue also sends Cova-Task-Trace to the agent. An agent that passes it on in its own LLM, MCP and A2A calls lets CoreValue tie that spend back to the task and the agent that asked for it. A call without the header starts a new trace, unless the agent requires one.
Refusals
| Status | When |
|---|---|
403 A2aGatewayNotEntitled | Your organisation's plan does not include the agent gateway. |
404 UnknownA2aAgent | No agent is registered with that ID. |
403, reason caller_not_allowed | The caller is not one the agent's Who may call it setting allows. |
403, reason access_rule | An enforced access rule refuses the caller. |
403, reason trace_required | The agent requires a task trace and the call has none. |
403, reason loop_limit | One agent has called this one more times within a task than the loop limit allows, and the limit is enforced. |
A refusal on a call is a JSON-RPC error whose data.reason names the cause. A caller that may not reach the agent is refused the agent card too, with 403 A2aCallerNotAllowed. Every refused call is still recorded, so owners can tell a rejected request from an agent failure.
Changes to an agent's settings and to access rules reach the gateway within a minute.
Cost
A2A calls are currently unpriced: the call's row carries no cost. The LLM and MCP spend an agent makes is priced as usual on its own rows.