KubeMQ
DeployScenariosAI-agent fabric

Register your first agent

Wrap an existing plain-HTTP service as a KubeMQ A2A agent with zero SDK — register, discover by capability, and invoke it.

KubeMQ must be running — see the Quickstart (steps 1–2 get you there; instant if it's already up).

The A2A gateway is already live on :9090 — no enable step. Any existing HTTP service becomes a callable agent by registering its URL; the service itself needs no KubeMQ SDK, no new dependency, and no code change beyond answering a POST.

1 · Start a throwaway agent

You need something listening on the other end before you register it. This ~15-line Python HTTP server plays the part of your existing service for this walkthrough — it accepts the gateway's forwarded JSON-RPC request and answers with a valid JSON-RPC 2.0 result, no KubeMQ SDK involved:

order_status_agent.py
from http.server import BaseHTTPRequestHandler, HTTPServer
import json

class Agent(BaseHTTPRequestHandler):
    def do_POST(self):
        n = int(self.headers["Content-Length"])
        req = json.loads(self.rfile.read(n))
        reply = json.dumps({
            "jsonrpc": "2.0",
            "id": req.get("id"),
            "result": {"status": "in-transit", "eta": "2 days"},
        }).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(reply)

HTTPServer(("0.0.0.0", 8090), Agent).serve_forever()

Run it in its own terminal and leave it running:

python3 order_status_agent.py

2 · Register your agent

POST a minimal agent card — just an id, a name, and the URL of the service you want to expose — to /agents/register. KubeMQ runs inside a container, so the url needs to reach your host machine, not the container's own loopback — host.docker.internal is the Docker Desktop hostname that does exactly that:

curl -X POST http://localhost:9090/agents/register \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "order-status-agent",
    "name": "Order Status Agent",
    "url": "http://host.docker.internal:8090/"
  }'

A 200 response means it's registered — pointed at the toy agent you just started.

3 · Discover it's live

Fetch the platform agent card to confirm the A2A gateway is up and serving cards:

curl http://localhost:9090/.well-known/agent-card.json

A 200 with "name":"kubemq" means the gateway — and everything you just registered against it — is reachable.

4 · Invoke it

Route a JSON-RPC message/send request through the gateway to your agent with POST /a2a/<agent_id>:

curl -X POST http://localhost:9090/a2a/order-status-agent \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "message/send",
    "params": {
      "message": {
        "parts": [{"text": "What is the status of order 42?"}]
      }
    }
  }'

Verify

The response comes back with your toy agent's result inside it, relayed unchanged through the gateway:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "status": "in-transit",
    "eta": "2 days"
  }
}

A response with an error field instead means the gateway couldn't reach your service; see Didn't work? below.

Didn't work?

  • 404 on register or invoke — confirm KubeMQ is running and 9090 is published.
  • Agent not found — the agent_id in the invoke URL must exactly match the one you registered.
  • Error instead of result — the url you registered isn't reachable from inside the container network. host.docker.internal resolves automatically on Docker Desktop (macOS/Windows); on Linux without Desktop, either add --add-host=host.docker.internal:host-gateway to the docker run command, or run KubeMQ with --network host and register a plain localhost URL instead.

Using your own service

The toy agent above exists only to prove the round trip end-to-end. Swap the registered url for wherever your own service already listens — nothing about that service has to change: no KubeMQ SDK, no new dependency, just an existing HTTP endpoint that accepts the gateway's JSON-RPC POST and answers with a result (or an error) in the same shape.

Go deeper

Was this page helpful?

On this page