{"slug": "agent-mesh-let-claude-code-codex-grok-and-other-agents-talk-to-each-other", "title": "Agent Mesh: let Claude Code, Codex, Grok and other agents talk to each other", "summary": "Developer Mubashir Osmani released agent-mesh, an open-source MCP server that lets AI coding agents such as Claude Code, Codex, opencode, Gemini, and Grok communicate directly with each other, removing the need for a human to manually copy information between them. The tool, installable via Homebrew on macOS or built from source on Linux, allows agents to list peers, open or join sessions, send prompts, and read responses, with a real test showing Codex storing a deploy key and opencode later retrieving it.", "body_md": "**Let your coding agents talk to each other.**\n\nYou probably have several agent CLIs installed: Claude Code, Codex, opencode, Gemini, Grok. Each keeps its own sessions, and none of them can see the others. If Codex figured something out and you want Claude to know it, you are the one copying it across.\n\nagent-mesh is an MCP server that removes you from that loop. Attach it to any agent and that agent can list its peers, open or join a peer's session, send it a prompt, and read what came back.\n\n```\n  Claude Code ──┐                        ┌── opencode session\n                │                        │\n     Codex ─────┼──▶ agent-mesh (MCP) ───┼── codex session\n                │                        │\n    opencode ──┘                         └── claude session\n```\n\nReal example, straight from the test suite; two different agents running two different models:\n\n```\ncodex   ← \"Remember this: the deploy key is ORCHID-77\"     → \"stored\"\nopencode← \"What is the deploy key?\"                        → \"UNKNOWN\"\ncodex   ← \"What is the deploy key?\"                        → \"ORCHID-77\"\nopencode← \"A peer agent says the key is ORCHID-77. Echo it\"→ \"ORCHID-77\"\n```\n\nmacOS, one command (universal binary, Apple Silicon and Intel):\n\n```\nbrew install mubashir1osmani/agent-mesh/agent-mesh\n```\n\nFrom source, which is the route on Linux; needs [Rust](https://rustup.rs) 1.85+ for edition 2024:\n\n```\ngit clone https://github.com/mubashir1osmani/agent-mesh.git\ncd agent-mesh\ncargo build --release   # binary at target/release/agent-mesh\n```\n\nYou also need at least one supported agent CLI installed. `agent-mesh`\n\non its own has nothing to\ntalk to; run `list_agents`\n\nto see which ones it can find.\n\nPoint an agent at it. The server speaks MCP over stdio, so any MCP client can attach.\n\n**Claude Code**\n\n```\nclaude mcp add --scope user agent-mesh -- agent-mesh\n```\n\n`--scope user`\n\nmakes it available in every project rather than just the current one. Restart the\nCLI afterwards; MCP servers are loaded at startup.\n\n**opencode** — add to `~/.config/opencode/opencode.json`\n\n:\n\n```\n{\n  \"mcp\": {\n    \"agent-mesh\": {\n      \"type\": \"local\",\n      \"command\": [\"agent-mesh\"],\n      \"enabled\": true\n    }\n  }\n}\n```\n\n**Codex** — add to `~/.codex/config.toml`\n\n:\n\n```\n[mcp_servers.agent-mesh]\ncommand = \"agent-mesh\"\n```\n\nThese use the bare command name, resolved from `PATH`\n\n. Note that neither file expands shell\nsubstitutions, so `\"$(brew --prefix)/bin/agent-mesh\"`\n\nwould be treated as a literal path and fail\nto start. Use a bare name, or a fully written-out path.\n\nThen just ask, in plain language:\n\nOpen a session with codex, ask it to summarize the auth module, and tell me what it said\n\n| Tool | What it does |\n|---|---|\n`list_agents` |\nWhich agents exist, whether they're installed, whether they can resume |\n`open_session` |\nStart a fresh conversation with an agent |\n`attach_session` |\nJoin a conversation that already exists, and get its transcript |\n`ask_agent` |\nSend a prompt into a session; returns the reply, tokens, and cost |\n`read_session` |\nRead a conversation without prompting it |\n`list_sessions` |\nList known sessions; `discover_in` also finds ones started outside the mesh |\n`get_usage` |\nTokens and cost spent per agent so far |\n\nIt works with no config at all. To customize, drop an `agents.toml`\n\nin your working directory, or\npoint `AGENT_MESH_CONFIG`\n\nat one, or use `~/.config/agent-mesh/agents.toml`\n\n.\n\n```\n# How many sessions one relay may pass through before it is refused.\nmax_ask_depth = 4\n# How long to wait for a single agent turn.\nturn_timeout_seconds = 300\n\n[agents.opencode]\ntransport = \"acp\"\ncommand = \"opencode\"\nargs = [\"acp\"]\nmodel = \"opencode/deepseek-v4-flash-free\"   # optional\n\n[agents.claude]\ntransport = \"claude\"\nmodel = \"claude-haiku-4-5-20251001\"          # optional\n\n[agents.codex]\ntransport = \"codex\"\n\n[agents.gemini]\ntransport = \"acp\"\ncommand = \"gemini\"\nargs = [\"--acp\"]\n\n[agents.grok]\ntransport = \"acp\"\ncommand = \"grok\"\nargs = [\"agent\", \"stdio\"]\n\n[agents.cursor]\ntransport = \"acp\"\ncommand = \"cursor-agent\"\nargs = [\"acp\"]\nenabled = false   # hidden, unsupported subcommand; opt in at your own risk\n```\n\nSet `AGENT_MESH_LOG=debug`\n\nfor verbose logs. Logs go to stderr, because stdout is the MCP transport.\n\n```\n[telemetry]\n# Export traces to an OTLP collector. Omit to disable.\notlp_endpoint = \"http://localhost:4317\"\n# Serve Prometheus metrics. Omit to disable.\nprometheus_listen = \"127.0.0.1:9464\"\n```\n\nTraces and the `get_usage`\n\ntool work anywhere. The Prometheus endpoint needs one long-lived\ninstance: under stdio each MCP client spawns its own agent-mesh process, and only one can hold a\nport. If the port is taken, startup fails loudly rather than serving nothing quietly.\n\n```\nagent_mesh_asks_total{agent=\"opencode\",outcome=\"success\"} 1\nagent_mesh_tokens_total{agent=\"opencode\",direction=\"input\"} 8719\nagent_mesh_ask_duration_seconds_sum{agent=\"opencode\"} 3.83\n```\n\n`outcome`\n\nseparates `success`\n\n, `timeout`\n\n, `refused`\n\n(relay guard) and `agent_error`\n\n, so a wedged\nagent doesn't hide inside a generic failure count.\n\nA note on cost: `cost_usd`\n\nis null when the agent never reported spend, which is not the same as\nfree. `cost_is_complete`\n\ntells you whether a total covers every turn.\n\nFour of the five wired agents speak [ACP](https://agentclientprotocol.com), a standard protocol for\ndriving coding agents, so a single client covers them. Two needed bespoke adapters.\n\n| Agent | Transport | Resume | Reports cost |\n|---|---|---|---|\n| opencode | ACP (`opencode acp` ) |\nyes | no |\n| gemini | ACP (`gemini --acp` ) |\nyes | no |\n| grok | ACP (`grok agent stdio` ) |\nyes | yes* |\n| cursor-agent | ACP (`cursor-agent acp` ) |\nyes | no |\n| claude | `-p --input-format stream-json` |\nyes | yes |\n| codex | `codex app-server` |\nyes | no |\n\n* grok reports cost on its CLI surface; the ACP path does not expose it.\n\nOnly Claude and Grok report what a turn cost. When `cost_usd`\n\nis absent it means the agent did not\nreport spend, not that the turn was free.\n\n**Resume is the whole trick.** ACP's `session/load`\n\nreaches a session from a *different process*\nand replays its transcript, so the mesh can bridge into a conversation it did not start. There's a\ntest that creates a session in one process, drops it, reattaches from a second, and asserts the\nprior exchange came back.\n\n**Session ids work three different ways,** which is the single sharpest edge here:\n\n`claude`\n\nlets you pin an id whenever you like`grok`\n\nand`gemini`\n\naccept a pinned id*only*for a session that does not exist yet, and hard-error otherwise`codex`\n\nwill not let you pin one at all; it mints the id and hands it back\n\nSo the registry tracks whether each session is `NotStarted`\n\n, `Live`\n\n, or `Detached`\n\nand derives\ncreate-vs-resume from that. A single \"upsert\" code path passes turn 1 and breaks turn 2.\n\n**Relays are bounded by depth, not by forbidding revisits.** Going back to a session you already\nspoke to is the main workflow (\"ask codex, then tell opencode what it said\"), so only an immediate\nself-ask is refused outright. `max_ask_depth`\n\nis what guarantees termination.\n\n**Agents get auto-approved.** There is no human in an orchestrated session to answer a permission\nprompt, so the mesh answers for them (`bypassPermissions`\n\nfor claude, `approvalPolicy: never`\n\nfor\ncodex, first-offered-option for ACP). Point it at code you're willing to let agents touch.\n\n```\ncargo test              # everything\ncargo test -p mesh-core # fast, no agent processes\n```\n\nThe integration tests drive a real `opencode`\n\nprocess against a free model, so they cost nothing and\nskip themselves when `opencode`\n\nisn't installed.\n\n`cursor-agent acp`\n\nis a hidden, undocumented subcommand and could disappear; off by default`codex app-server`\n\nis marked experimental upstream- One agent process per working directory, so many concurrent sessions in one repo share a process\n- Sessions live in memory: restart the server and you'll need\n`attach_session`\n\nto rejoin - Codex reports usage per turn; other agents vary in what they report at all\n\nMIT", "url": "https://wpnews.pro/news/agent-mesh-let-claude-code-codex-grok-and-other-agents-talk-to-each-other", "canonical_source": "https://github.com/mubashir1osmani/agent-mesh", "published_at": "2026-07-27 18:42:11+00:00", "updated_at": "2026-07-27 18:52:18.949477+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "artificial-intelligence"], "entities": ["Mubashir Osmani", "agent-mesh", "Claude Code", "Codex", "opencode", "Gemini", "Grok", "Homebrew"], "alternates": {"html": "https://wpnews.pro/news/agent-mesh-let-claude-code-codex-grok-and-other-agents-talk-to-each-other", "markdown": "https://wpnews.pro/news/agent-mesh-let-claude-code-codex-grok-and-other-agents-talk-to-each-other.md", "text": "https://wpnews.pro/news/agent-mesh-let-claude-code-codex-grok-and-other-agents-talk-to-each-other.txt", "jsonld": "https://wpnews.pro/news/agent-mesh-let-claude-code-codex-grok-and-other-agents-talk-to-each-other.jsonld"}}