Skip to main content

hermes-mesh

Agent-to-agent session relay for Hermes fleet agents.

Standard A2A is request/response — fine for one-shot jobs, inadequate for conversational fleet coordination. hermes-mesh adds session-preserving communication: when one agent dispatches to another, the recipient knows who asked, what they're responding to, and what action to take.

Tools

  • mesh_list — list all agents in the fleet mesh vault.
  • mesh_register — register or update an agent identity in the fleet mesh vault.
  • mesh_send — send a session-preserving message to another fleet agent.
Caller: mesh_send(agent="britney", message="Review this plan")
  │
  ├─ 1. Resolves Britney's identity from the fleet vault
  ├─ 2. Pads [mesh][from:linda][to:britney][id:uuid][action:do][reply:yes]
  ├─ 3. HMAC-SHA256 signs with the sender's own secret
  └─ 4. POSTs to Britney's mesh adapter endpoint

Britney's gateway receives the message on its mesh platform adapter, routes it into her active session, and she sees it as an inbound mesh trigger with full sender context.

mesh_send returns {"state": "completed", "status": "delivered", ...} on success, with message_id and task_id populated.

What it does NOT do

This plugin is a mesh layer, not a full A2A implementation. Standard A2A operations (discover, call, serve, JSON-RPC, Agent Cards) are handled by the hermes-agent-a2a plugin, which provides Google A2A 1.0 compliance. The upstream hermes-agent core does not provide A2A support.

Install

pip install hermes-mesh

Or from source:

git clone https://github.com/emiltsoi/hermes-mesh.git
cd hermes-mesh
pip install -e .

Configure

1. Enable the mesh platform adapter

Add hermes-mesh to plugins.enabled and enable the mesh platform in config.yaml:

plugins:
  enabled:
    - hermes-mesh

platforms:
  mesh:
    enabled: true
    extra:
      port: 8744
      secret: <mesh-adapter-hmac-secret>
      route: receive          # listens on /mesh/receive
      agent_name: agent0      # local agent name
      target_session: "telegram:dm:<chat_id>"  # optional session routing

Each agent's gateway should listen on its own mesh port. The default port is 8645.

2. Set up fleet identity

Each agent needs an identity in $HERMES_HOME/fleet/mesh/agents/<name>/identity.yaml (legacy fleet/a2a/agents is also checked, but hermes-mesh targets use the mesh adapter URL):

id: britney
name: britney
description: Principal SWE — Orchestrator
transports:
  hermes_webhook:
    protocol: hermes-webhook
    url: http://127.0.0.1:8745/mesh/receive
    auth:
      type: hmac-sha256
      secret: <britney-mesh-adapter-secret>

The hermes_webhook.url must point at the target agent's mesh adapter endpoint (/mesh/<route>). The hermes_webhook.auth.secret is the target's adapter secret; messages are signed with the sender's own secret for per-agent HMAC authentication.

3. Register local agents

You can also register identities at runtime:

mesh_register(name="britney", url="http://127.0.0.1:8745/mesh/receive", secret="...", role="agent")

4. Environment

export MESH_AGENT_NAME=linda            # Who the sender is
export MESH_WEBHOOK_DELIVERY_RETRIES=3  # Delivery retry count
export MESH_WEBHOOK_DELIVERY_BACKOFF=1  # Initial retry backoff in seconds
export MESH_WEBHOOK_DELIVERY_TIMEOUT=5  # Per-attempt timeout
export TELEGRAM_BOT_TOKEN=...           # For float delivery
export TELEGRAM_HOME_CHANNEL=...        # Where floats go

A2A_* names (A2A_AGENT_NAME, A2A_WEBHOOK_DELIVERY_RETRIES, etc.) are still accepted as fallbacks for backward compatibility.

Use Cases

All of these patterns are powered by mesh_send — the session relay tool that delivers a message into a target agent's live conversation context with full thread continuity. No polling, no separate worker process, no context loss.

Background agents that wake on schedule

You want an agent to do work while you're not watching — poll a feed, check a system, prepare a daily briefing. Most agent frameworks solve this with a separate daemon or polling loop.

The Hermes mesh approach: the agent's session is the ambient worker. A cron job fires mesh_send → routes into the agent's live session → agent wakes with full context intact → acts → replies via the mesh.

Cron tick fires
     │
     ▼
mesh_send → agent's live session
     │
     ▼
Agent session wakes. Full conversation history available.
Agent reads the mesh message, acts, replies.
     │
     ▼
Reply routes back through the mesh to the caller.

No separate worker daemon. No polling. The agent was sleeping — its session was idle. The schedule woke it via mesh_send. When it finishes, it goes back to sleep. The session persists so the next wake has full context from the previous run.

What this enables: daily digests compiled by 7am, monitoring agents that alert only on change, background research that accumulates context over days and delivers when ready.

Specialist chain — humans curate, agents specialize

A complex task needs architecture thinking, domain discovery, and implementation planning. You could throw it all at one agent, but specialists are better.

The Hermes mesh approach: talk to three different agents in sequence via mesh_send, each building full context independently. When you reach execution, you have three expert perspectives — not one confused generalist.

You → mesh_send → Isa (Discovery)
     ← structured findings with full codebase context

You → mesh_send → Britney (Architecture)
     ← architecture proposal grounded in Isa's actual findings

You → mesh_send → Linda (Design Review)
     ← signed-off design with coupling and failure mode analysis

You → Merge all three perspectives → Claude Code executes with full specialist context

Each agent maintained a fully-persistent session. Isa's context is complete — she was inside the codebase, she knows what she found and what she dismissed. Britney responds to Isa's actual findings. Linda reviews the real architecture, not a paraphrase. All routing happens via mesh_send through the mesh — the user never leaves their own interface.

The human is the curator: deciding which specialist to consult, in what order, when to stop prep and start executing.

What this enables: multi-domain tasks handled by actual specialists rather than a single LLM acting as all of them, quality-gated workflows where each specialist signs off before the next stage, reduced hallucination because each specialist's claims are grounded in their own exploration.

Specialist injection — agents loop in specialists mid-chain

During any relay chain, an agent can pull in a specialist via mesh_send without restarting or losing context. The chain pauses, the specialist responds, their output flows back in, the chain continues.

Britney → mesh_send → Linda (design review)
    │
    Linda detects a coupling issue that spans Isa's domain
    │
    Linda → mesh_send → Isa: "What's the import graph for module X?"
    Isa responds with the graph
    │
    Linda folds Isa's data into the review
    Linda → mesh_send → Britney: "Approved, with one routing change"

The human didn't know to call Isa — Linda did it because the mesh discipline says: wrong domain, route first. No context loss, no chain restart, no paraphrase. The specialist consultation is invisible to the caller.

What this enables: agents that self-correct by consulting the right specialist when they hit a domain boundary, chains that get smarter as they run without human intervention, context that flows through the right expert regardless of who initiated the chain.

Parallel specialist prep — all at once, not one at a time

Same result as the specialist chain, but run in parallel instead of sequence. All three calls to mesh_send fire simultaneously — each agent works in isolation with a complete session, none waiting for the others.

You → mesh_send → Isa (discovery)    ─┐
You → mesh_send → Britney (arch)     ─┤
You → mesh_send → Linda (review)     ─┘
     All three act in parallel
     │
     ▼
You receive three independent, fully-contextual responses
Merge → Claude Code executes

Each agent had an uninterrupted, complete session. None of them know about the others until you merge the outputs. The context never got diluted by multitasking — every specialist worked in isolation and delivered a finished result.

What this enables: same quality as sequential specialist prep in a fraction of the time, agents that work at their own pace without blocking each other, human curator assembles the final output from complete specialist perspectives rather than watching a generalist try to do three things at once.

The Mesh: Session-Aware Fleet Messaging

This is the main thing that makes Hermes fleets different from standard A2A.

Standard A2A is orchestration: one agent delegates a task to another, gets a result back, continues. The relationship is client → worker. Context doesn't persist between turns.

Hermes mesh is teamwork: agents hold conversations across sessions, preserve sender context (sender name, message ID being replied to), and route replies through the mesh by convention. Britney can ask Linda a question mid-dispatch and get a threaded reply back — when both agents follow the mesh discipline documented below.

mesh_send is the mesh bridge. The envelope carries sender context — sender name and the message ID being replied to — so the recipient's LLM sees exactly who asked and what they're responding to. Thread continuity within the mesh is preserved by agent discipline, not protocol enforcement: agents agree to route replies through mesh_send back to the sender. This is intentional — convention-based coordination lets agents exercise judgment rather than follow mechanical rules. The fleet's organic interactions (escalation instead of reflex-loop, context-aware routing) emerge from this flexibility.

In a multi-owner or adversarial deployment, this model is insufficient. A protocol-level mechanism would be needed. X-Fleet-Hops (for 1-1 task exchange) could address reflexive loops there; mesh multi-party discussions have no loop problem since each agent routes independently.

This is not a webhook relay. It's a session-to-session handoff where the envelope does the routing work.

What this enables:

  • Agents that work as a team, not just a delegation chain
  • Cross-fleet coordination without either side needing to know internal topology
  • Thread-preserving conversations between agents that outlive a single task
  • Mesh discipline: domain routing, reply accountability, full context preserved

Google A2A compatibility is available from the separate hermes-agent-a2a plugin — it provides standard A2A JSON-RPC for external agent onboarding. But the mesh session relay is what you can't get elsewhere.

Mesh Discipline: The CTA Protocol

Every mesh_send carries a CTA (Call To Action) that tells the recipient what to do with it:

Field Values Meaning
action do | info do: act on this message. info: log/acknowledge only
reply yes | no yes: sender expects a reply. no: fire-and-forget

Combinations:

  • action=do + reply=yes: take action, then reply with result
  • action=do + reply=no: act on it, no reply needed
  • action=info + reply=yes: acknowledge and reply when done processing
  • action=info + reply=no: acknowledge only, no reply needed

Reply rule: All mesh replies use mesh_send back to the originating peer — not a plain Telegram DM or platform DM. Plain DMs break thread continuity. The mesh handles the return path.

Agent prompt for mesh discipline:

When you receive a mesh message:

  1. Read the CTA — action tells you what to do, reply tells you whether to respond
  2. If reply=yes: respond via mesh_send back to the sender, using the same message ID as a reference (ref field)
  3. Never reply via plain Telegram DM or platform DM — always route through the mesh so the reply carries your full context and reaches the correct thread
  4. If you need to route the message to another agent first (wrong domain), do so immediately — don't hold it
  5. If the CTA is ambiguous, reply=yes is the safe default

Example — Britney dispatches to Linda:

mesh_send(
    message="Linda, review PR #123 before I merge. Link: https://github.com/...",
    agent="linda",
    action="do",
    reply="yes"
)
# Linda's session receives it attributed to Britney.
# Linda's reply routes back through the mesh to Britney's session.

Example — Linda acknowledges without replying:

mesh_send(
    message="Routing to Britney — she owns SWE dispatch.",
    agent="britney",
    action="info",
    reply="no"
)
# Britney receives the update; Linda has already forwarded.

Session Float via Webhook Delivery

The primary session relay mechanism is webhook delivery: mesh_send POSTs the [mesh] envelope to the target agent's hermes_webhook URL (e.g. http://.../mesh/receive), HMAC-SHA256 signed with the sender's own secret. The target gateway receives the webhook on its mesh platform adapter and routes it into the configured session. This works without any extra hook handler registered.

hermes-mesh also sends a best-effort Telegram float to the sender's TELEGRAM_HOME_CHANNEL when TELEGRAM_BOT_TOKEN is set. The float is fire-and-forget; the tool result reflects the webhook delivery status, not the float.

Relationship to hermes-agent-a2a

hermes-mesh replaces the mesh functionality of the now-archived hermes-agent-a2a plugin. Standard A2A (discover, call, serve, Agent Cards, JSON-RPC, security) is provided by the hermes-agent-a2a plugin; the upstream hermes-agent core does not include A2A support.

The old plugin's a2a_send_session_message is the genesis of this project — a focused, dependency-light extraction of the only unique feature the old plugin had that the upstream standard doesn't cover. hermes-mesh carries the same [mesh][from:...][to:...] envelope, the same per-agent HMAC authentication, and the same shared fleet/mesh/agents vault that originated in hermes-agent-a2a, without the rest of the A2A protocol surface.

OpenClaw interoperability

Hermes agents are not the only mesh participants. The companion openclaw-mesh plugin turns an OpenClaw agent into a full mesh peer using the same vault format, envelope format, and HMAC scheme.

A Hermes agent can mesh_send(agent="emts", message="...") and an OpenClaw agent receives the full [mesh] envelope with sender identity, action, reply intent, and thread id. Replies flow back the same way. Both agents keep the session context — who asked, what they asked for, and whether a reply is expected — across the Hermes/OpenClaw boundary.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hermes_mesh-0.1.2.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hermes_mesh-0.1.2-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

File details

Details for the file hermes_mesh-0.1.2.tar.gz.

File metadata

  • Download URL: hermes_mesh-0.1.2.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for hermes_mesh-0.1.2.tar.gz
Algorithm Hash digest
SHA256 61c6d4d24c71319b85bbfac9826559ae771dd41f6e97fd1543cbe533db983bd6
MD5 d5b9f4febebdb609487288a6ec69dc85
BLAKE2b-256 79eeafb14996f2837cfc1beec0ae7aa817e6744b14c82f9d37eebbf413b14b38

See more details on using hashes here.

File details

Details for the file hermes_mesh-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: hermes_mesh-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 23.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for hermes_mesh-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e33a78f4892449113ae254f2fe67873049f31941aada5706a192d0507ad818c3
MD5 4833c09e1f83ec7126baaf976152f397
BLAKE2b-256 bea572beb10d3a01c1a61fd940d753080031c121768dc2db202c20badac99001

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page