KubeMQ
AiwayAI Agents (A2A)

Reference

Complete A2A endpoint, JSON-RPC, agent card schema, internal channel, config, error code, and metrics reference for KubeMQ.

The complete API surface of the KubeMQ A2A connector: HTTP endpoints, the JSON-RPC 2.0 wire format, the agent card schema, internal channels, configuration fields, error codes, and Prometheus metrics. The connector is a transparent JSON-RPC proxy — agents are plain HTTP servers registered by URL, reached through a per-agent virtual subscriber over the broker.

All HTTP endpoints are served on the shared HTTP server (default port 9090), which also hosts the REST, MCP, and CloudEvents connectors. Prometheus metrics are exposed separately on port 8080 (see Observability).

HTTP Endpoints

A2A endpoints

MethodPathDescriptionRequest bodySuccessError
POST/a2a/{agent_id}JSON-RPC 2.0 request (sync or stream)JSON-RPC 2.0 payloadJSON-RPC result or SSE streamJSON-RPC error
GET/a2a/{agent_id}Not supported405 Method Not Allowed
GET/a2a/{agent_id}/streamSSE stream via GETtext/event-stream

POST /a2a/{agent_id} is the primary endpoint. Its behavior depends on the JSON-RPC method: message/stream opens an SSE proxy; every other method is forwarded synchronously to the agent. GET /a2a/{agent_id} always returns 405 — use POST for JSON-RPC or GET /a2a/{agent_id}/stream for a server-pushed stream.

# Synchronous message/send
curl -X POST http://localhost:9090/a2a/echo-agent-01 \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"message/send","params":{"message":{"parts":[{"text":"Hello, agent!"}]}}}'

# SSE stream via GET
curl -N http://localhost:9090/a2a/echo-agent-01/stream \
  -H 'Accept: text/event-stream'

Registry endpoints

Standard HTTP JSON responses (not JSON-RPC). See Agent registry for the full workflow.

MethodPathDescriptionRequest bodySuccessError
POST/agents/registerRegister an agentAgent card JSON200 + enriched card400 / 403 / 409
GET/agentsList agents (filter by skill_tags, limit)200 + [<AgentCard>, …] (bare array)
GET/agents/{agent_id}Get one agent200 + agent card404
POST/agents/deregisterDeregister (JSON body){"agent_id":"…"}200 + {"ok":true}404
DELETE/agents/{agent_id}Deregister (REST, backward compat)200 + {"ok":true}404
POST/agents/heartbeatRefresh liveness{"agent_id":"…"}200 + {"ok":true}400

POST /agents/register errors: 400 (card validation), 403 (ownership conflict — a different principal owns this agent_id), 409 (MaxAgents limit reached). registered_by is set automatically from the caller's JWT claims.

# List agents tagged "search" or "nlp", capped at 10
curl 'http://localhost:9090/agents?skill_tags=search,nlp&limit=10'

Agent card endpoints

MethodPathDescriptionSuccessError
GET/.well-known/agent-card.jsonPlatform agent card (KubeMQ metadata)200 (name: "kubemq")
GET/a2a/{agent_id}/.well-known/agent-card.jsonIndividual agent card from registry200 + enriched card404

Both .well-known/agent-card.json paths are public — they bypass authentication. See Agent cards.

# Platform card — confirms the A2A connector is reachable
curl http://localhost:9090/.well-known/agent-card.json

JSON-RPC 2.0 wire format

The connector uses JSON-RPC 2.0 for all client-to-agent communication. A request carries three required fields plus an optional params object.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "message/send",
  "params": {
    "message": { "parts": [{ "text": "Hello, agent!" }] },
    "contextId": "optional-correlation-id",
    "configuration": { "timeout": 30 }
  }
}

Request fields

FieldTypeRequiredDescription
jsonrpcstringYesMust be "2.0"
idinteger or stringYesRequest identifier, echoed in the response
methodstringYesJSON-RPC method name (missing/empty → -32600)
paramsobjectNoMethod parameters
params.message.partsarrayNoMessage content; each part has a text field
params.contextIdstringNoCorrelation ID, passed to the agent unmodified
params.configuration.timeoutnumberNoRequest timeout in seconds (falls back to DefaultTimeoutSeconds, capped at MaxTimeoutSeconds)

Methods

KubeMQ is method-agnostic — it forwards any method to the agent unchanged. The five methods below are recognized for metrics labeling; all others are recorded as method="unknown".

MethodBehaviorResponse
message/sendSynchronous proxy to the agentJSON-RPC response
message/streamSSE stream proxy via the virtual subscribertext/event-stream
tasks/getForwarded to the agentJSON-RPC response
tasks/cancelForwarded to the agentJSON-RPC response
tasks/sendForwarded to the agentJSON-RPC response
(any other method)Forwarded to the agentJSON-RPC response

JSON-RPC batch requests (an array of request objects) are not supported — send individual requests. Notifications (requests without an id) are forwarded to the agent but receive no response.

Success and error responses

On success, the agent's return value is placed verbatim in result — KubeMQ does not modify the payload. On failure, the response carries an error object instead.

{ "jsonrpc": "2.0", "id": 1, "result": { "…": "agent output, unmodified" } }
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32002, "message": "agent not found: nonexistent-agent" } }

Agent card schema

The AgentCard is submitted on registration and returned, enriched with server-managed timestamps, from the list/get/well-known endpoints. Required fields are agent_id, name, and url.

FieldJSON keyTypeRequiredDescription
AgentIDagent_idstringYesUnique ID; 2–128 chars, ^[a-z0-9][a-z0-9-]{0,126}[a-z0-9]$
NamenamestringYesHuman-readable name (max 256 chars)
DescriptiondescriptionstringNoAgent description (max 2048 chars)
VersionversionstringNoAgent version (max 64 chars)
URLurlstringYesAbsolute http:// or https:// URL (max 2048 chars)
RegisteredByregistered_bystringNoJWT principal that registered the agent (server-set)
CapabilitiescapabilitiesobjectNoFree-form capability map
SkillsskillsarrayNoList of AgentSkill (see below)
DefaultInputModesdefaultInputModesstring[]NoDefault input modes
DefaultOutputModesdefaultOutputModesstring[]NoDefault output modes
SupportedInterfacessupportedInterfacesJSONNoOpaque JSON
SecuritySchemessecuritySchemesJSONNoOpaque JSON
SecuritysecurityJSONNoOpaque JSON
ProtocolVersionsprotocolVersionsstring[]NoSupported versions (default ["1.0"])
MetadatametadataobjectNoKey-value metadata
LastSeenlast_seentimestampLast heartbeat/registration (server-set)
RegisteredAtregistered_attimestampOriginal registration time, preserved across re-registrations (server-set)

AgentSkill

FieldJSON keyTypeRequiredDescription
IDidstringYesSkill identifier
NamenamestringYesSkill name
DescriptiondescriptionstringNoSkill description
Tagstagsstring[]NoSkill tags, used by the skill_tags filter
{
  "agent_id": "echo-agent-01",
  "name": "Echo Agent",
  "url": "http://localhost:18080/",
  "skills": [{ "id": "echo", "name": "Echo", "tags": ["test", "echo"] }]
}

Internal channel map

The connector and registry use the reserved _AGENTS_. prefix internally. User channels carrying this prefix are rejected (IsReservedChannel). Callers never address these channels directly — the connector and virtual subscriber own them.

Channel patternPurposeTransport
_AGENTS_.agents/{agent_id}Request/reply to an agent via its virtual subscriber (including stream_cancel)Query
_AGENTS_.stream/{stream_id}Temporary SSE stream events relayed by the virtual subscriberEvents
_AGENTS_.discoveryRegistry replication across cluster nodesEvents Store

Caller HTTP headers are forwarded to the agent as a2a_hdr_* tags on the broker request; the virtual subscriber always sets X-KubeMQ-Caller-ID to the original caller's identity. See Architecture.

SSE event types

Streaming responses (message/stream or GET /a2a/{agent_id}/stream) are delivered as Server-Sent Events. Each event has an event: line and a data: line carrying the stream envelope. A keepalive comment (: keepalive) is sent every 30 seconds; the idle timeout is MaxSSEIdleSeconds (default 300s). See Streaming.

SSE eventEnvelope typeDescriptionTerminal
task.statusstatus_updateProgress updateNo
task.artifactartifactIntermediate artifactNo
task.donedoneSuccessful completionYes
task.errorerrorFailureYes
message(default)Any other envelope typeNo
event: task.status
data: {"stream_id":"…","type":"status_update","payload":{"status":"working"}}

event: task.done
data: {"stream_id":"…","type":"done","payload":{"final_result":"completed"}}

Error codes

The connector returns standard JSON-RPC 2.0 base codes plus four A2A-specific codes. See Error handling for the transport-vs-application distinction and retry guidance.

CodeNameTrigger
-32700Parse ErrorMalformed JSON body, or Content-Type is not application/json
-32600Invalid RequestMissing method field, jsonrpc != "2.0", or empty/invalid agent_id
-32601Method Not FoundReserved — KubeMQ forwards all methods to agents and does not raise this
-32602Invalid ParamsMalformed params object
-32603Internal ErrorServer-side failure
-32010Authentication FailureJWT auth error on /a2a/* (REST endpoints return HTTP 401 instead)
-32001Agent TimeoutAgent did not respond within the timeout
-32002Agent Not FoundNo agent registered with the given agent_id
-32003Agent UnavailableAgent rejected the request
-32004Invalid ResponseInvalid response from the agent

Transport vs application errors

The virtual subscriber sets Executed: false on transport failures (the agent never processed the request) and Executed: true on application errors (the agent processed it and returned an error body). This lets callers choose a retry strategy.

Agent resultpb.ResponseCategory
Connection refused / DNS failureExecuted: false, Error: "agent unreachable: …"Transport
HTTP timeoutExecuted: false, Error: "agent timeout"Transport
HTTP 502 / 503 / 504Executed: false, Error: "agent unavailable: …"Transport
Response exceeds AgentMaxResponseBytesExecuted: false, Error: "agent response too large"Transport
Concurrency limit reachedExecuted: false, Error: "server busy: concurrency limit reached"Transport
HTTP 200–299Executed: true, Body: responseSuccess
HTTP 400 / 401 / 403 / 404 / 409 / 422 / 500Executed: true, Body: responseApplication

Configuration fields

A2aConfig is configured in Connectors.A2A.*. The connector is enabled by default — set CONNECTORSA2_A_ENABLE=false to disable it. See Configuration and the shared HTTP server enable model for the irregular env-var naming.

FieldDefaultDisable/override env varDescription
EnabletrueCONNECTORSA2_A_ENABLEEnable the A2A connector (set =false to disable)
AgentTTLSeconds300CONNECTORSA2_A_AGENT_TTL_SECONDSAgent expiry TTL (liveness check)
DefaultTimeoutSeconds300CONNECTORSA2_A_DEFAULT_TIMEOUT_SECONDSDefault request timeout
MaxTimeoutSeconds3600CONNECTORSA2_A_MAX_TIMEOUT_SECONDSMaximum allowed request timeout (must be ≥ DefaultTimeoutSeconds)
MaxAgents0 (unlimited)CONNECTORSA2_A_MAX_AGENTSMaximum registered agents
MaxSSEIdleSeconds300CONNECTORSA2_A_MAX_SSE_IDLE_SECONDSSSE stream idle timeout
TrustedOrigins["auto"]CONNECTORSA2_A_TRUSTED_ORIGINSTrusted origins for browser requests
AgentMaxResponseBytes10485760 (10 MB)CONNECTORSA2_A_AGENT_MAX_RESPONSE_BYTESMax agent HTTP response size; larger → Executed: false
AgentTLSSkipVerifyfalseCONNECTORSA2_A_AGENT_TLS_SKIP_VERIFYSkip TLS verification for outbound agent calls (dev only)
AgentMaxConcurrency100CONNECTORSA2_A_AGENT_MAX_CONCURRENCYMax concurrent in-flight requests per agent; overflow → "server busy"

The gateway adds a GatewayTimeoutBuffer of 10 seconds on top of the caller-specified timeout so it does not time out before the downstream agent.

Metrics

Prometheus metrics are exposed on port 8080 at /metrics. See Observability for the full surface and the web AI dashboard.

MetricTypeLabelsDescription
kubemq_a2a_requests_totalCounteragent_id, method, statusA2A requests forwarded to agents
kubemq_a2a_request_duration_secondsHistogramagent_idA2A request duration
kubemq_a2a_errors_totalCounteragent_id, error_codeA2A gateway errors
kubemq_a2a_registry_operations_totalCounterop, statusRegistry operations (register, deregister, heartbeat, expire)
kubemq_a2a_sse_streams_activeGaugeCurrently active SSE streams

The method label is sanitized against the five standard methods; any other value is recorded as method="unknown" to bound Prometheus label cardinality.

curl http://localhost:8080/metrics 2>/dev/null | grep kubemq_a2a_

Was this page helpful?

On this page