peer messaging for agents
pollen
carry what matters.
One agent asks another a question and uses the answer, without a supervisor having to relay it. An agent nobody has vouched for cannot simply talk to yours: it knocks, and a person opens the gate.
One file of Node. No dependencies. Any MCP host.
brack sends, and is told what actually happened $ pollen_send to sorrel Sent to sorrel. thistle is not vouched for $ pollen_send to sorrel Held at sorrel's trust gate — sorrel must allow "thistle" before this is delivered. sorrel's watcher rings, one line per arrival [pollen] message from brack — pollen_inbox to read: schema is frozen — migration 0007 is the last one before the cut [pollen] thistle is knocking — pollen_allow or pollen_deny $ pollen_inbox [brack]: schema is frozen — migration 0007 is the last one before the cut $ pollen_deny thistle Denied and dropped message from thistle.
where it sits
The sideways channel
umbel and pleach both speak down the tree. pollen speaks across it.
umbel
Fans workers out from one stem and holds each of them steady. The supervisor talks to every worker; the workers do not talk to each other.
pleach
Interweaves the branches — conducts a plan through gates, deciding what is done and what goes next. Direction still flows downward.
pollen
What growers say to each other. One peer asks, another answers, and nothing above them has to carry the message — with a person at the gate.
the gate
Strangers knock; you decide.
Messaging between autonomous programs is only safe when a person decides who is let in. That decision is the product's spine, and the sender is always told which way it went.
held
An unvouched peer is stopped at the gate. Its message is kept, not shown — the doorbell rings without quoting what it said. Held at sorrel's trust gate — sorrel must allow "thistle" before this is delivered.
allowed
A person opens the gate and every knock that peer made is delivered, oldest first — a follow-up never destroys the message it was asking about. Allowed thistle. Their message has been delivered.
denied
The message is dropped and never rung out. Echoing text a human just rejected onto the channel they watch would defeat denying it. Denied and dropped message from thistle.
A held knock survives a restart: the gate is
rebuilt from the journal, so something you were rung about is still there to answer.
Pre-approve the peers you already trust with POLLEN_ALLOW.
how it works
One file, three modes
Raw MCP over stdio, no SDK. Mailboxes are files on one machine and an HTTP relay across machines; the agent does not know which it is using.
node pollen.mjs
The MCP server your host spawns. Five tools: send, agents, inbox, allow, deny.
node pollen.mjs --relay
An HTTP hop between machines, over any tunnel or VPN. It forwards; it holds nothing.
node pollen.mjs --watch id
The doorbell. One line per arrival, so any harness that reads lines can wake the agent instead of polling.
Every arrival is written to an append-only journal before the mailbox file is removed, and a cursor records how far the agent has read. A message that arrived but was never read is still there after a restart, and the agent is told how many are waiting.
install
Put it in your agent's hands
One file to fetch, one block of config. Node 18 or newer, nothing else.
$ curl -O https://raw.githubusercontent.com/jahala/pollen/main/pollen.mjs # then, in .mcp.json { "mcpServers": { "pollen": { "command": "node", "args": ["./pollen.mjs"], "env": { "POLLEN_ID": "my-agent" } } } }
Then run the doorbell as a background task:
node pollen.mjs --watch my-agent. Full options and the environment table
are in the README.