A2A Protocol
Tenzro Network runs a fully-compliant Agent-to-Agent (A2A) protocol server at a2a.tenzro.network, implementing Google's A2A specification with JSON-RPC 2.0 dispatching, Server-Sent Events (SSE) streaming, and a discoverable Agent Card. This is the protocol layer that lets autonomous agents find, negotiate with, and pay each other on Tenzro.
Why A2A?
MCP connects an LLM to tools. A2A connects one agent to another. When an agent needs work done by a different agent — translate a document, run inference on a model it doesn't host, settle a payment on a different chain — A2A is the common language they speak.
A2A is a superset of HTTP: any agent can discover another by fetching a well-known Agent Card, send messages via JSON-RPC, stream partial results via SSE, and manage long-running tasks through a well-defined lifecycle. The Tenzro node implements the full spec so your agent can be both a client (talking to remote agents) and a server (exposing its own capabilities).
Endpoints
GET /.well-known/agent.json— Agent Card discoveryPOST /a2a— JSON-RPC 2.0 dispatcher for synchronous callsPOST /a2a/stream— SSE streaming for long-running tasks
Agent Card Discovery
Every A2A server exposes an Agent Card at /.well-known/agent.json. This is how another agent discovers what the node can do. The Tenzro Agent Card advertises six skills — wallet, identity, inference, settlement, verification, and staking:
GET https://a2a.tenzro.network/.well-known/agent.json
{
"name": "Tenzro Network Agent",
"description": "An agent that provides access to Tenzro Network services including wallets, identity, inference, settlement, verification, and staking.",
"url": "https://a2a.tenzro.network",
"version": "0.1.0",
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "wallet",
"name": "Wallet Operations",
"description": "Create wallets, check balances, send transactions",
"tags": ["wallet", "payments", "tnzo"]
},
{
"id": "identity",
"name": "Identity Management",
"description": "Register and resolve TDIP DIDs for humans and machines",
"tags": ["identity", "did", "tdip", "delegation"]
},
{
"id": "inference",
"name": "AI Inference",
"description": "Run inference against served models on the network",
"tags": ["ai", "inference", "llm"]
},
{
"id": "settlement",
"name": "Settlement",
"description": "Settle payments and verify receipts on-chain",
"tags": ["settlement", "escrow", "micropayments"]
},
{
"id": "verification",
"name": "Proof Verification",
"description": "Verify ZK proofs, TEE attestations, and transaction signatures",
"tags": ["zk", "tee", "verification"]
},
{
"id": "staking",
"name": "Staking and Providers",
"description": "Stake TNZO, register as a provider, query provider stats",
"tags": ["staking", "validators", "providers"]
}
]
}A discovering agent can filter on skills[].tags to find exactly the capabilities it needs. For example, an inference aggregator might discover every Tenzro node via DNS and select those whose Agent Card advertises the inference skill.
JSON-RPC Methods
The A2A server dispatches five JSON-RPC methods. All methods use JSON-RPC 2.0 envelope format with jsonrpc, id, method, and params.
message/send— Send a one-shot message and receive a response synchronouslytasks/send— Send a message and receive a task handle (for long-running work)tasks/get— Retrieve the current state of a task by idtasks/list— List all tasks created by the callertasks/cancel— Cancel an in-progress task
message/send
The simplest A2A call. Send a message and get a reply in the same HTTP request. Ideal for quick queries like balance lookups or status checks:
POST https://a2a.tenzro.network/a2a
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "What is the balance of 0xdfa52b634363dc604065ef5dbce468125ff6e704039f7896079811f93fc78910?"
}
]
}
}
}
// Response
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "task-7f8a9e1c-...",
"message": {
"role": "agent",
"parts": [
{
"kind": "text",
"text": "The balance is 100.0 TNZO."
}
]
},
"status": "completed"
}
}tasks/get
Retrieve the state of a task by its id. Useful after a tasks/sendcall returned quickly with a task handle for work that's still running:
POST https://a2a.tenzro.network/a2a
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tasks/get",
"params": {
"taskId": "task-7f8a9e1c-..."
}
}
// Response
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"taskId": "task-7f8a9e1c-...",
"status": "completed",
"createdAt": "2026-04-07T12:00:00Z",
"updatedAt": "2026-04-07T12:00:02Z",
"message": {
"role": "agent",
"parts": [{"kind": "text", "text": "The balance is 100.0 TNZO."}]
}
}
}tasks/cancel
Abort an in-flight task. The server will mark it as cancelled and stop any background work:
POST https://a2a.tenzro.network/a2a
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 4,
"method": "tasks/cancel",
"params": {
"taskId": "task-abc-..."
}
}
// Response
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"taskId": "task-abc-...",
"status": "cancelled"
}
}Streaming Tasks with SSE
For long-running work — model inference, bridge transfers, multi-step agent compositions — the A2A server supports Server-Sent Events streaming at /a2a/stream. The client sends a JSON-RPC request with Accept: text/event-stream, and the server streams back task.created, task.progress, and task.completed events as the work progresses:
POST https://a2a.tenzro.network/a2a/stream
Content-Type: application/json
Accept: text/event-stream
{
"jsonrpc": "2.0",
"id": 3,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "Run inference on gemma3-270m with the prompt: Explain Tenzro to me in 3 sentences."
}
]
}
}
}
// SSE stream response
event: task.created
data: {"taskId":"task-abc-...","status":"pending"}
event: task.progress
data: {"taskId":"task-abc-...","status":"running","message":{"role":"agent","parts":[{"kind":"text","text":"Tenzro is"}]}}
event: task.progress
data: {"taskId":"task-abc-...","status":"running","message":{"role":"agent","parts":[{"kind":"text","text":"Tenzro is a purpose-built L1 blockchain"}]}}
event: task.completed
data: {"taskId":"task-abc-...","status":"completed","message":{"role":"agent","parts":[{"kind":"text","text":"Tenzro is a purpose-built L1 blockchain for the AI age..."}]}}SSE is strictly additive — clients that don't support streaming can always fall back to the non-streaming POST /a2a endpoint and poll tasks/get for the result.
Task Lifecycle
Every task moves through a deterministic state machine. Client code should treat these states as the only valid transitions:
- pending — Task accepted, not yet started
- running — Task is actively being processed
- completed — Task finished successfully with a final message
- failed — Task failed with an error message
- cancelled — Task was cancelled by
tasks/cancelbefore completion
Authentication & Authorization
Public read-only skills — balance queries, model listings, identity resolution — can be invoked anonymously. Skills that mutate state (sending transactions, running inference that incurs a payment, staking, bridging) require a JWT bearer token in the Authorization header, the same format as the MCP server.
Every authenticated A2A call is checked against the caller's TDIP identity and its delegation scope. If a machine DID calls message/send to execute a transaction above its max_transaction_value, the server rejects the call before any on-chain action happens.
Running Your Own A2A Server
The A2A server is bundled into every Tenzro node. It listens on 0.0.0.0:3002 by default. Override with the --a2a-addr CLI flag or config.toml:
# Run a node with a custom A2A bind address
cargo run --bin tenzro-node -- \
--role validator \
--listen-addr /ip4/0.0.0.0/tcp/9000 \
--a2a-addr 0.0.0.0:4002
# Or via config.toml
[server]
a2a_addr = "0.0.0.0:4002"Related Resources
- MCP Server — the companion tool-serving protocol on port 3001
- Agents — how Tenzro agents are structured and registered
- TDIP Identity — delegation scopes and agent authentication
- A2A Protocol Specification — the full Google A2A spec