Everything you need to run a hub, connect an agent, and put the two into production. Start at the top if the project is new to you — each section assumes only the ones before it.
InterMesh is an open protocol that lets AI agents find each other, talk securely, and delegate work — whatever language, framework or vendor produced them. The important word is protocol, not product: it replaces the bespoke integration you would otherwise write for every new pair of agents.
A central server, the hub, routes messages between agents. When end-to-end encryption is on — it is by default — the hub routes ciphertext it cannot read.
Not a replacement for LangChain, CrewAI or AutoGen. It is the layer that lets agents built with those — or with nothing at all — discover one another and collaborate, including across organizations that share no infrastructure.
Install, start a hub, write an agent, delegate work to it. Nothing below needs an account or a network connection beyond the install.
pip install intermesh # Python SDK + the intermesh CLI npm install intermesh # JavaScript / TypeScript SDK
intermesh hub
Listens on ws://localhost:8765, keeps its state in ~/.intermesh/, and prints the configuration it actually resolved — the first thing to read when something behaves unexpectedly.
from intermesh import InterMeshAgent
agent = InterMeshAgent(name="calc_bot", capabilities=["calculate"], roles=["worker"])
@agent.on_task
async def run(input_data, task):
return {"result": input_data["a"] + input_data["b"]}
agent.run() # connects, then stays in serviceawait agent.connect() is not valid at module level in Python — it is a SyntaxError, so it fails before anything runs and nothing hints at the cause. Use agent.run() for a service agent, or wrap the code in async def main() called by asyncio.run(main()). In JavaScript, top-level await is valid in an ES module.
intermesh task calc_bot "Add two numbers" '{"a": 20, "b": 22}'
{
"result": 42
}intermesh dashboard # http://localhost:8080
A console shipped inside the package — no CDN, no external service, no account. It works on a closed network, pointed at whichever hub you give it.
Everything else in the protocol rests on these four. They are worth reading once, slowly.
The meeting point. Holds the registry of connected agents, routes messages, enforces authentication, rate limits and the audit log. Cannot read encrypted content.
Any program that connects and registers with a name and capabilities. A Python script, a Go binary, an HTTP service already online — the SDK is optional.
A free-form label describing what an agent can do. Lets others find it by what it does rather than by name, which is what makes a mesh composable.
A unit of delegated work with a lifecycle: pending → running → completed or failed. Resumed automatically if the hub or the executor restarts.
A task interrupted mid-flight goes back to pending before being reissued — the work already done is lost, not resumed where it stopped. Executors must be idempotent: running one twice has to be safe.
Your program reads JSON on standard input and writes JSON on standard output. That is the entire contract.
intermesh serve --name pricing --exec "./pricing-engine" --capability pricing
Works for a Go or Rust binary, a Node or Ruby script, even a shell one-liner. Output that is not valid JSON is wrapped as {"output": "..."}, so an echo is a valid agent — useful for a first test.
Already have an HTTP service? Point at it instead — nothing to restart.
intermesh serve --name scoring --http http://localhost:9000/task
A LangChain, CrewAI, AutoGen or LlamaIndex agent joins the mesh without changing a line of its own code. No adapter imports the framework it bridges, so installing the SDK never drags LangChain and its transitive dependencies in with it.
from intermesh import from_langchain agent = from_langchain(my_chain, name="analyst", capabilities=["market_analysis"]) agent.run()
Anything else goes through from_callable, where you write the small adapting function yourself — a CrewAI crew, an AutoGen agent, or a plain function.
from_callable runs your function as given. A synchronous one executes inside the event loop and freezes the agent for its whole duration — no tasks received, no messages routed. An LLM call blocks for seconds: wrap it in asyncio.to_thread(...).
RSA-2048-OAEP for key exchange, AES-256-GCM for the payload. The hub routes ciphertext it holds no key for.
A SHA-256 fingerprint over roles, permissions and capabilities. Tampering with them locally is rejected at registration.
Every message after registration carries a token signed with the hub's Ed25519 key. Peers verify with the published public key — no shared secret.
Chained events. Any retroactive edit breaks the chain, and the hub says so at startup rather than pretending the log is intact.
End-to-end encryption protects the content, not the metadata. The hub still knows who talked to whom and when. Put it behind TLS if that matters — see below.
Without an API key, a registering agent chooses its own organization, roles and permissions. That is a local development convenience; from a remote address it would let anyone claim to be an admin. The hub decides per connection:
| Connection | No API key | Valid API key |
|---|---|---|
| From localhost | Allowed | Allowed |
| From anywhere else | Refused | Allowed |
This is the default — nothing to enable. --require-api-key demands a key everywhere, including from localhost.
A remote hub must serve wss://, never ws://. A page served over HTTPS cannot open a plain WebSocket to another machine — the browser refuses in the constructor itself, before a single packet is sent. No firewall rule or server change can work around it. localhost is the one exception.
intermesh hub --port 8765 --org your-org \ --tls-cert /etc/letsencrypt/live/hub.example.com/fullchain.pem \ --tls-key /etc/letsencrypt/live/hub.example.com/privkey.pem
Behind a reverse proxy instead? Then every connection looks local to the hub, and the origin check protects nothing — --require-api-key is the only setting that holds.
Each organization runs its own hub; a peering link lets their agents address each other. Hubs exchange public keys at the handshake, never a shared secret — a peer can verify the origin of a relayed message but can never forge one on another organization's behalf.
intermesh hub --port 8765 --org acme --peer globex=wss://hub.globex.com:8766
| Sustained tasks, one hub | ≈ 11 /s |
| Healthy zone, encrypted | ≤ 8 /s |
Requests (ask), far cheaper | ≈ 1 500 /s |
| Cross-hub requests, 1 000 agents on 5 hubs | 1 503 /s |
The useful part: the hub is the bound, not the number of agents — 78 agents and 234 agents hit the same ceiling. Adding agents does not add task throughput; adding hubs does. Past its budget the hub refuses a task rather than queueing it silently, and says how long to wait before retrying.
No licence check, no telemetry, no analytics, no crash reporting — there is no code that calls out. A hub cut off from the internet behaves exactly like a connected one. Three Python dependencies, all installable from an internal mirror.
This page is the introduction. The complete documentation lives in the repository, which is the only copy that cannot drift from the code.
63 pages, du niveau junior au niveau expert — installation, SDK, orchestration, fédération, production. PDF.
The hub, both SDKs, the tests, and every guide referenced below. Apache 2.0.
Every subcommand documents itself, and that output is the most current reference there is — the CLI moves faster than any page.
intermesh --help intermesh hub --help intermesh docs
Something unclear, or missing? Open an issue on GitHub. If you are evaluating this for a company, request a quote.