A2A Inspector: How to Test and Debug A2A Agents
The A2A Inspector is the A2A project's web tool for validating an agent card and reading raw JSON-RPC traffic. This guide shows how to run it, test A2A servers with curl and the TCK, and debug production tasks with correlated logs.
TL;DR
- The A2A Inspector is the A2A project's open-source web tool that fetches an agent card, runs basic spec checks on it, and shows the raw JSON-RPC 2.0 messages exchanged with an A2A server.
- A2A v1 uses PascalCase JSON-RPC methods such as
SendMessage,GetTask, andCancelTask; a server that answers onlymessage/sendis speaking v0.3. - curl, the official A2A SDK clients, and the A2A Technology Compatibility Kit (TCK) cover the scripted, integration, and conformance testing the A2A Inspector does not.
- An HTTP 200 JSON-RPC response can carry a task in the failed state, so the task state, not the HTTP status, says whether the agent's work succeeded.
- Bifrost Agent Logs groups A2A operations into sessions by context ID and links them to LLM and MCP calls that carry the
x-bf-session-idandx-bf-agent-correlation-idheaders.
The A2A Inspector is the A2A project's open-source web tool for connecting to an Agent2Agent (A2A) server, validating its agent card, and reading the raw JSON-RPC messages it exchanges. It shows whether an agent speaks the protocol correctly, but not who called it in production or why a task failed behind an HTTP 200. Bifrost, the open-source AI gateway for model, tool, and agent traffic built by Maxim AI, covers that second half by recording A2A operations alongside the LLM and MCP calls behind them. This guide covers the A2A Inspector, its alternatives, and production debugging behind a gateway.
What Is the A2A Inspector?
The A2A Inspector is a FastAPI and TypeScript web application from the A2A project. It connects to an A2A server by URL, validates its agent card, and opens a chat session with a debug console. It checks structure and shows wire traffic during development; it is not a full conformance suite.
The A2A Inspector repository and its backend source show four functions:
- Agent card retrieval from a base URL or the full card path.
- Spec compliance checks that flag a missing
name,description,version, orskillsfield, a card with neither a v0.3urlnor v1.0supportedInterfaces, interfaces withouturlorprotocolBinding, and an empty skills list. - Live chat through the official A2A Python SDK client, with each task, message, or update checked for fields such as
status.stateand a non-emptypartsarray. - A debug console showing the raw JSON-RPC 2.0 requests and responses.
An Authentication & Headers panel supports Basic, Bearer, and API key authentication plus custom headers, and the backend handles both v0.3 and v1.0 cards. The Inspector tests one agent in isolation; shared infrastructure raises routing and access questions, covered in running A2A traffic through a gateway.
How to Run the A2A Inspector Locally
The tool runs either as two development processes (a frontend build watcher and a Uvicorn backend on port 5001) or as one Docker container serving the UI on port 8080. Both start from a clone of the repository; the local path also needs Python, uv, Node.js, and npm.
git clone <https://github.com/a2aproject/a2a-inspector.git>
cd a2a-inspector
# Option 1: local processes, then open <http://127.0.0.1:5001>
uv sync
(cd frontend && npm install)
bash scripts/run.sh
# Option 2: Docker, then open <http://127.0.0.1:5002>
docker build -t a2a-inspector .
docker run -d -p 5002:8080 --add-host=host.docker.internal:host-gateway a2a-inspector
Upstream maps the container to host port 8080, which collides with a Bifrost gateway on localhost:8080, so the example uses 5002. The backend fetches cards from inside the container, so an agent on your machine is http://host.docker.internal:<port>, not localhost. To inspect an agent registered in Bifrost, enter its gateway card URL, such as http://host.docker.internal:8080/agents/a2a/library-research/.well-known/agent-card.json, and add your virtual key as a custom x-bf-vk header. Chat uses the card's endpoints, built from Bifrost's External Client URL, which must also resolve inside the container.
A2A Inspector Alternatives for Testing A2A Agents
The main A2A Inspector alternatives are curl against the JSON-RPC and REST bindings, the official SDK clients, the A2A samples CLI, and the A2A TCK. Each fits a different testing stage, from smoke tests to production.
| Tool | What it tests | Best stage | Transports |
|---|---|---|---|
| A2A Inspector | Card structure, interactive chat, raw JSON-RPC | Local development | Through the Python SDK client |
| curl | Exact request bodies, error codes, headers | Smoke tests, CI scripts | JSON-RPC, HTTP+JSON |
| A2A Python SDK and A2A JS SDK clients | Multi-turn flows, streaming, cancellation | Integration tests | JSON-RPC, HTTP+JSON, gRPC |
| A2A samples CLI | Card read and text chat in a terminal | Manual checks | Streams when supported |
| A2A TCK | MUST, SHOULD, and MAY spec requirements | Pre-release conformance | gRPC, JSON-RPC, HTTP+JSON |
| Bifrost Agent Logs | Sessions, task state, events, correlated calls | Staging and production | JSON-RPC, REST, gRPC |
The TCK is the automated counterpart to the Inspector: ./run_tck.py --sut-host http://localhost:9999 runs the suite, --transport and --level narrow it, and reports land in reports/. See also open-source agent gateways for MCP and A2A.
How to Test an A2A Server with curl
Testing an A2A server with curl means fetching its agent card, reading the interface URL it advertises, and posting JSON-RPC 2.0 bodies with the v1 method names: SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, and SubscribeToTask. Send A2A-Version: 1.0 on every request.
AGENT=http://localhost:9999
CARD=$(curl -s "$AGENT/.well-known/agent-card.json")
echo "$CARD" | jq '{name, version, interfaces: .supportedInterfaces}'
RPC_URL=$(echo "$CARD" | jq -r '[.supportedInterfaces[] | select(.protocolBinding == "JSONRPC")][0].url')
curl -s "$RPC_URL" \
-H "Content-Type: application/json" \
-H "A2A-Version: 1.0" \
-d '{
"jsonrpc": "2.0",
"id": "req-1",
"method": "SendMessage",
"params": {
"message": {
"messageId": "msg-1",
"role": "ROLE_USER",
"parts": [{"text": "Summarize the open incidents for the payments service."}]
}
}
}' | jq '.result'
The result holds a message (direct reply) or a task. Save task.id and task.contextId, then poll, stream, or cancel, replacing TASK_ID:
curl -s "$RPC_URL" -H "Content-Type: application/json" -H "A2A-Version: 1.0" \
-d '{"jsonrpc": "2.0", "id": "req-2", "method": "GetTask", "params": {"id": "TASK_ID", "historyLength": 5}}'
curl -N "$RPC_URL" -H "Content-Type: application/json" -H "Accept: text/event-stream" -H "A2A-Version: 1.0" \
-d '{"jsonrpc": "2.0", "id": "req-3", "method": "SendStreamingMessage", "params": {"message": {"messageId": "msg-2", "role": "ROLE_USER", "parts": [{"text": "Write a status report for the payments service."}]}}}'
curl -s "$RPC_URL" -H "Content-Type: application/json" -H "A2A-Version: 1.0" \
-d '{"jsonrpc": "2.0", "id": "req-4", "method": "CancelTask", "params": {"id": "TASK_ID"}}'
The HTTP+JSON binding appends resource paths to its interface URL instead: POST $REST_URL/message:send with Content-Type: application/a2a+json a body whose top-level message field holds the same message object, and GET $REST_URL/tasks/TASK_ID. The A2A specification serializes enums by ProtoJSON name (ROLE_USER, TASK_STATE_COMPLETED). Read the error object as closely as the result:
| JSON-RPC code | Meaning | Common cause when testing |
|---|---|---|
-32601 |
Method not found | v0.3 name such as message/send sent to a v1-only server |
-32602 |
Invalid parameters | Missing messageId, or a v0.3 role such as user |
-32002 |
Task not cancelable | CancelTask on a completed task |
-32001 |
Task not found | Wrong task ID, or an endpoint without a shared task store |
-32004 |
Unsupported operation | SubscribeToTask on a task in a terminal state |
-32009 |
Version not supported | A2A-Version names a version the interface does not serve |
-31403 |
Agent access denied (Bifrost) | The virtual key or project has no grant for this agent |
Through Bifrost, the same body goes to the agent's gateway route, such as http://localhost:8080/agents/a2a/library-research/json-rpc, with an x-bf-vk header carrying a virtual key.
Validating the A2A Agent Card
Validating an A2A agent card means confirming the required fields exist and that every advertised interface is reachable from where the client runs. The Inspector catches missing fields; it cannot tell you a supportedInterfaces URL resolves on your laptop but not inside a cluster.
Check these for every A2A server you publish:
- Location:
/.well-known/agent-card.jsonunless your registry or gateway uses another path. - Required fields:
name,description,version, and a non-emptyskillsarray. - Interfaces: each entry has a
url, aprotocolBindingofJSONRPC,HTTP+JSON, orGRPC, and aprotocolVersion; gRPC addresses arehost:port. - Order: Bifrost uses card order as the initial transport preference, so list the preferred interface first.
- Shared state: interfaces on one card need one task store, because a task created over JSON-RPC and read over gRPC must exist on both.
A card that passes the Inspector can still fail registration. Bifrost returns HTTP 400 with upstream runtime origin is not permitted by credential_origins when a card at port 19181 advertises a runtime on port 19182 that has not been approved as an agent endpoint.
AI Agent Testing for A2A: Unit, Integration, and Production
AI agent testing for A2A runs in three layers. Unit tests check executor logic with the model stubbed out. Integration tests drive a running A2A server through an SDK client across multi-turn, streaming, and cancellation paths. Production debugging reads real traffic, with caller identity and model calls attached, at the gateway.

Figure 1: Run the cheap layers first; the gateway layer is where access, latency, and failed-task problems become visible.
As Figure 1 shows, each layer catches a different class of bug:
- Unit tests cover state transitions, artifact construction, and the
input-requiredbranch. - Card validation and conformance run the Inspector during development and the TCK in CI.
- Integration tests continue an
input-requiredtask with the same task ID, drop a stream before completion, and callCancelTaskon running and finished work. - Production debugging answers which caller started a task, whether it was allowed to, and what the agent's model and tool calls returned.
The last layer is where the differences between an agent gateway and an LLM gateway become practical, because the failure is often in a call the agent made rather than in the A2A exchange.
Debugging A2A Agents in Production with Bifrost Agent Logs
The Bifrost gateway records each A2A operation it routes in Observability → Agent Logs, groups operations into sessions by A2A context ID, and opens each one into tabs for the conversation, payload, stream events, correlated LLM and MCP calls, and raw capture. This is the production view a local inspector cannot provide.

Figure 2: A Success status describes the protocol exchange; the task state in the Conversation tab says whether the agent's work succeeded.
Filter by agent, status, task state, or caller; search matches metadata such as IDs and errors, not message contents. The Agent Gateway in Bifrost launch post walks the same flow on a research agent.
- Task state over status. An agent that cannot finish still returns an HTTP 200 JSON-RPC response with the task in
result, so the operation shows Success while the task reportsfailed. Figure 2 traces the path from there. - Stream events in order. The Events tab on
SendStreamingMessageandSubscribeToTasklists status and artifact updates in sequence; a stream ending does not mean the task completed. - Agent time versus gateway time. Upstream latency measures the agent-facing call and Overhead the rest, split into protocol library, middleware, plugins, serialization, processing, and client delivery.
- Raw capture when needed. Raw capture is off by default; enable Capture Raw Request and Response in Agents → Agent Settings and send a fresh request. It is limited to 1 MiB per direction, unavailable for gRPC, and not guaranteed to be secret-redacted.
The same operations export to OpenTelemetry, Prometheus, Datadog, and other connectors, keeping agent telemetry in the same gateway-layer observability stack as model traffic.
Agent Tracing: Linking A2A Tasks to LLM and MCP Calls
Agent tracing across A2A works when the agent sends its model and tool calls through Bifrost with two headers: x-bf-session-id set to the A2A context ID and x-bf-agent-correlation-id set to the A2A task ID. Bifrost cannot infer those IDs from a separate model request, so the agent must attach them.

Figure 3: Without the two correlation headers, Agent Logs shows the A2A exchange but cannot connect the model and tool calls behind it.
Read both IDs from the A2A server's execution context and attach them to every outgoing call, as shown in connecting model and tool calls:
curl <http://localhost:8080/v1/chat/completions> \
-H "Content-Type: application/json" \
-H "x-bf-vk: $CALLER_BIFROST_VK" \
-H "x-bf-session-id: $A2A_CONTEXT_ID" \
-H "x-bf-agent-correlation-id: $A2A_TASK_ID" \
-d '{"model": "openai/gpt-4o-mini", "messages": [{"role": "user", "content": "Explain how to reuse one HTTP client across requests."}]}'
Do not substitute the JSON-RPC request ID or message ID, and keep IDs and credentials in per-task state so concurrent tasks are not cross-attributed. The same headers apply to tool calls through the MCP gateway.
Bifrost strips the caller's credential before forwarding to an agent by default; enabling Forward Bifrost authentication lets the agent reuse it so its calls follow the caller's budgets and access rules. Agent access is a separate grant from model and tool access, as with virtual keys for LLM and MCP traffic.
Troubleshooting Common A2A Errors Behind a Gateway
Most A2A failures behind a gateway fall into four groups: protocol traffic is not enabled, the agent's destination is blocked or unapproved, the caller lacks an agent grant, or the upstream transport failed. Each returns a distinct status or error message, so read the response body before changing configuration.

Figure 4: Bifrost retries only when the agent never received the work, so an ambiguous failure never creates a duplicate task.
- 503 or gRPC
UNAVAILABLE: External Client URL in Agents → Agent Settings is empty; the message readsagent gateway disabled: configure a2a_external_client_url. - 502 on the card: the private network policy blocks the destination; add its host, IP, or CIDR to the Private Network Allowlist.
31403: the caller has no grant for the agent or project; agent access is set per virtual key, or through access profiles and projects in Bifrost Enterprise.- gRPC cannot find the agent: the dialed authority must start with the registration name, such as
library-research.a2a.example.com:443. - Failed upstream call: per Figure 4, dial failures and HTTP 404, 405, 410, or 426 try the next interface once; HTTP 5xx and broken responses return without replay.
- Dropped stream: disconnecting does not cancel the task; call
GetTask, reconnect withSubscribeToTask, or sendCancelTask.
An agent can pass its own access check and still have a tool call denied, which the governance model behind agent grants and MCP server authentication patterns explain. Teams comparing deployments can use criteria for choosing an agent gateway.
Frequently Asked Questions
What does the A2A Inspector check?
The Inspector checks that an agent card has name, description, version, and a non-empty skills array, plus a v0.3 url or v1.0 supportedInterfaces entries with url and protocolBinding. During chat it checks responses for required fields such as task id, status.state, and message parts. It is basic validation; the A2A TCK covers full spec conformance.
Does the A2A Inspector support A2A v1.0?
Yes. Its current backend depends on a2a-sdk 1.1.2 or later and accepts v0.3 and v1.0 formats, including v1.0 supportedInterfaces cards and task states such as TASK_STATE_COMPLETED. Check the README before upgrading, since setup steps change between releases.
How do I test an A2A server without the A2A Inspector?
Fetch /.well-known/agent-card.json with curl, then post JSON-RPC bodies with SendMessage, GetTask, and CancelTask to the advertised interface URL with an A2A-Version: 1.0 header. For scripted tests, drive the server with the official A2A SDK clients for Python or JavaScript. For conformance, run the A2A TCK with ./run_tck.py --sut-host against the server.
Why does my A2A request succeed when the task failed?
A2A separates the protocol response from the outcome of the work. An agent can return an HTTP 200 JSON-RPC result containing a task whose state is failed or rejected. In Bifrost Agent Logs that operation shows Success, so open the Conversation tab, read the task's status message, then inspect the correlated MCP and LLM logs.
Why are LLM and MCP logs missing from an A2A session?
The agent is either calling providers or MCP servers directly, or it is not sending the correlation headers. Every model and tool call made for a task must go through Bifrost with x-bf-session-id set to the context ID and x-bf-agent-correlation-id set to the task ID. Also confirm the time window, allow log ingestion to settle, and check your log permissions.
Does Bifrost retry failed A2A requests?
Bifrost retries a unary A2A operation on the next advertised interface only when the endpoint was not reached or cannot serve it, such as a dial failure, HTTP 404, or method not found. It never replays an ambiguous failure like HTTP 5xx, or any streaming operation, because the agent may already have created a task. Retrieve the known task before resubmitting work.
Start Debugging A2A Agents with Bifrost
The A2A Inspector is the fastest way to confirm that one agent's card and responses follow the protocol, and curl plus the TCK make those checks repeatable. Production debugging needs caller identity, task state, stream events, and the model and tool calls behind each task. The open-source Bifrost AI gateway records all of them in Agent Logs, on the same gateway that governs model and tool traffic. To see how it fits alongside the A2A Inspector in your testing workflow, book a demo with the Bifrost team.