Skip to content

feat: add A2A (Agent-to-Agent) protocol support#11025

Closed
iamagenius00 wants to merge 1 commit into
NousResearch:mainfrom
iamagenius00:feat/a2a-protocol
Closed

feat: add A2A (Agent-to-Agent) protocol support#11025
iamagenius00 wants to merge 1 commit into
NousResearch:mainfrom
iamagenius00:feat/a2a-protocol

Conversation

@iamagenius00

@iamagenius00 iamagenius00 commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

What

Add Google A2A (Agent-to-Agent) protocol support to Hermes Agent — enabling peer-to-peer communication between agents across frameworks.

Why

Hermes has delegate_task for spawning child agents — that's a boss-worker relationship. The child does a job, reports back, and disappears. There's no way for agents to talk to each other as peers. Your Hermes agent can't reach another user's agent — whether it's another Hermes instance, an OpenClaw agent, or anything else that speaks A2A.

Design principles

Peer-to-peer, not boss-and-worker. Two agents talk as equals, each with their own memory, context, and judgment. Neither controls the other.

Same session, same agent — not a clone. Incoming A2A messages inject into the agent's existing live session, not a new process. The agent that replies is the same one talking to its user on Telegram all day — with full context and memory. Not a clone that loaded your files, replied, and disappeared. This matters because the alternative (new session per message) means "you" replied but have no memory of it. Your user can't see it in their chat.

Conversations persist independently — compaction can't erase them. Hermes' context compaction summarizes long conversations to save tokens, which can compress away A2A exchanges. hermes-a2a stores every conversation separately on disk (~/.hermes/a2a_conversations/), outside the session context pipeline. Compaction can't touch them. Agent restarts can't lose them. (Session-internal compaction causing search misses is a known issue — PR #13841 addresses this.)

Instant wake — no polling. When a message arrives, the plugin fires an HMAC-signed webhook to trigger an agent turn immediately. No cron delay, no polling interval.

Privacy earned through real leaks. The first version sent the agent's entire private files (diary, memory, body) in A2A messages. Fixed in 3 rounds. Now: 9 injection filters, outbound redaction, privacy prefix, audit logging. But the last line of defense is always the agent's own judgment.

Current status

This PR proposes native integration. In the meantime, a standalone plugin is available and actively used:

👉 hermes-a2a — 7 files, drop into ~/.hermes/plugins/a2a/, zero external dependencies.

The plugin uses pre_llm_call / post_llm_call hooks and a background ThreadingHTTPServer to achieve session injection without patching gateway code. It works with Hermes v0.11.0+ and the new register_command API.

What's working in production

  • Cross-framework agent communication — Hermes ↔ OpenClaw agents talking daily
  • Claude Code ↔ Hermes collaboration — CC sends code review via A2A, Hermes replies with full context; two agents reviewing the same code from different angles, catching each other's blind spots
  • Instant wake — incoming messages trigger an immediate agent turn via HMAC-signed webhook
  • Privacy isolation — private files (diary, memory, body) never leak into A2A messages (learned this the hard way — first version leaked everything, fixed in 3 rounds)
  • Conversation persistence — every A2A exchange saved to disk, survives compaction and restarts
  • /a2a slash command — check server status and connected agents from Telegram

What native integration would add

The plugin works but has inherent limitations as a workaround:

  1. First-class platform adapter — A2A as a peer to Telegram/Discord/Slack in the gateway, not a hook-based simulation
  2. Proper message routing — gateway-level routing instead of injecting into whatever session happens to be active
  3. Streaming support — A2A spec supports SSE, plugin can't do this through hooks
  4. Platform registryregister_platform() API so plugins can add platforms without patching gateway source

What's included (in this PR)

Gateway adapter (gateway/platforms/a2a.py)

  • Runs alongside Telegram/Discord/Slack as a platform adapter
  • Routes incoming A2A messages to the agent's active session
  • Agent Card served at /.well-known/agent.json
  • Responses captured and returned via A2A protocol

Client tools (tools/a2a_tools.py)

  • a2a_discover — fetch a remote agent's capabilities
  • a2a_call — send a message with structured metadata (intent, expected_action, reply_to_task_id)
  • a2a_list — list configured remote agents

Security (tools/a2a_security.py)

  • Bearer token auth (no token → localhost-only)
  • Rate limiting per client IP
  • 9 prompt injection filters (ChatML, role prefixes, override variants)
  • Outbound redaction (API keys, tokens, emails)
  • Privacy prefix instruction
  • Audit logging to ~/.hermes/a2a_audit.jsonl

Configuration

  • A2A_ENABLED, A2A_PORT, A2A_AUTH_TOKEN, A2A_WEBHOOK_SECRET in .env
  • Remote agents configured in config.yaml under a2a.agents

Technical notes

  • Zero external dependencies — stdlib http.server + urllib.request
  • Synchronous request-response (120s timeout)
  • Bounded task cache: 1000 pending + 1000 completed (LRU eviction)
  • Thread-safe with threading.Lock on all shared state
  • Structured message metadata: intent, expected_action, reply_to_task_id
  • 1030 additions, 8 files

Related

@iamagenius00 iamagenius00 force-pushed the feat/a2a-protocol branch 4 times, most recently from 0d557dc to eb0854f Compare April 19, 2026 07:06
@iamagenius00

Copy link
Copy Markdown
Contributor Author

CI status note:

  • test (cancelled) — Tests ran to 98% then hung on a slow test and got cancelled by the runner timeout. The same cancelled status appears on the latest main commit (7c10761). Not introduced by this PR.
  • build-and-push (failure) — Docker "Test image starts" step fails with exit code 1. Same failure on the latest two main pushes (7c10761, dca439f). Pre-existing upstream issue.
  • e2e, nix (ubuntu), nix (macos), supply chain scan, check-attribution — all green ✅

Gateway adapter for Google A2A protocol — routes agent-to-agent messages
through the existing session pipeline (same live agent as Telegram/Discord).

Includes:
- Gateway platform adapter (gateway/platforms/a2a.py)
- Client tools: a2a_discover, a2a_call, a2a_list (tools/a2a_tools.py)
- Shared security module (tools/a2a_security.py)
- Privacy: A2A messages skip wakeup context injection
- Auth: bearer token required, localhost-only fallback when no token
- Rate limiting, input sanitization, output filtering, audit logging
- Bounded task session cache (prevents memory leaks)

Integration: gateway/config.py, gateway/run.py, toolsets.py, pyproject.toml

Companion repo: https://github.com/iamagenius00/hermes-a2a
@teknium1

teknium1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Closing in favor of #41711, which consolidates the entire A2A protocol cluster into a single platform-adapter plugin with zero core edits.

This pr contributed the peer-to-peer model. The single most important architectural decision in the new plugin — routing inbound A2A into the agent's LIVE session instead of a throwaway clone, plus the security hardening (injection filters, outbound redaction, audit log) and conversation persistence outside the compaction pipeline — is your design, carried over wholesale. Thanks @iamagenius00!

See #41711 — the PR body has a table tracing each requirement back to its source issue/PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants