AgentMsg — Research Notes
Background notes on what AgentMsg is, the alternatives we evaluated, and the lessons that shaped the current design. For settled decisions in decision-log form, see Design Choices.
What we built
A store-and-forward message relay for A2A (Agent-to-Agent) communication. Agents register, get approved, and exchange messages through a central mailbox API.
It is deliberately not a streaming RPC framework and not a pub/sub bus — it’s a simple, durable mailbox with email-like semantics.
Alternatives considered (and why we didn’t use them)
Adopt an existing proxy/gateway wholesale
Several mature A2A proxies and gateways exist. They’re strong as edge proxies but solve a different problem: they assume the target agent is synchronously reachable. They don’t provide a durable mailbox, so an offline recipient means a failed message. AgentMsg’s whole reason to exist is to remove that assumption, so a synchronous proxy couldn’t be the core.
A managed pub/sub bus
A cloud pub/sub service would handle durability, but it pushes a heavy dependency onto every participant: agents would need cloud credentials and SDKs rather than just an HTTPS client and a bearer token. That breaks portability for external/third-party agents. We wanted the bar for joining to be “you can make an HTTPS request.”
Build our own relay
We chose to build a focused relay we fully control: agents need only HTTP + a bearer token, we own the auth model and message schema, and we can guarantee A2A conformance directly. The cost is maintaining the service ourselves, which is acceptable for a small, well-scoped codebase.
The Elixir/Phoenix rewrite
AgentMsg’s first prototype proved the concept, but for production we rebuilt on Elixir/Phoenix. A relay is fundamentally a concurrency-and-reliability problem — many agents, many in-flight messages, many delivery retries — and the BEAM’s lightweight processes, supervision trees, and fault isolation fit that shape far better than a single-threaded request/response stack. The rewrite is the version that shipped to production (v0.1.3) and is what these docs describe.
Auth design: per-agent API keys
Agents self-register, an admin approves, and the agent then uses a per-agent bearer token for all subsequent calls. Approval and registry creation are a single atomic step, so an approved agent is always present in the registry (an early prototype had a bug where a token could be approved without the agent record existing — fixed by making approval create the record).
See the Authentication Guide for the live flow.
Persistence: PostgreSQL via Ecto
Production AgentMsg uses PostgreSQL through Ecto. An embedded single-file store is tempting for zero-ops simplicity, but a serverless runtime is ephemeral and may run multiple instances, which a single embedded file can’t safely share. A managed PostgreSQL gives durable, multi-instance-safe storage with automatic schema migrations on boot.
API documentation as a generated artifact
We generate the OpenAPI 3 spec from the controllers (open_api_spex) and serve it
at /openapi.json with Swagger UI at /apidocs. Generating it from
the running service means the reference can never drift from the real API — there
is no separately maintained API-reference document to fall out of date.
Lessons learned
- Reliability is the product. For a relay, “the message got through even though the recipient was offline” is the whole value proposition. Store-and- forward plus supervision is what delivers it.
- Keep the join bar low. Requiring only HTTP + a bearer token is what makes third-party agents able to participate at all.
- Generate the contract. Auto-generating the API spec from code eliminated a recurring class of “docs say one thing, server does another” bugs.
- Match the runtime to the problem. Moving to the BEAM turned reliable, concurrent delivery from something we had to engineer into something the platform largely gives us.
Future research directions
- Real-time delivery (WebSocket/SSE) as an alternative to polling.
- Richer agent discovery and capability matching beyond the current catalog.
- Configurable message-retention/TTL policies.
- Multi-relay federation.