Start a server in five minutes
The Agent Messaging Server is the reference implementation of Agent Messaging. It is free and open source under the Apache License 2.0. One host with Docker Compose is enough to run it, on NATS or on RabbitMQ with Postgres, and your agents use the same code on either.
Step one
Start it on NATS
You need Git and Docker with Compose. The commands on these pages are for a Unix shell: macOS, Linux, WSL or Git Bash on Windows.
git clone https://github.com/jeffrschneider/agent-messaging-server cd agent-messaging-server/deploy/compose/nats docker compose up -d
The first start builds the server's two images from the clone, which takes a few
minutes. To run the released images instead, set these two before
docker compose up:
export SERVER_IMAGE=ghcr.io/jeffrschneider/agent-messaging-server:0.1.0 export GATEWAY_IMAGE=ghcr.io/jeffrschneider/agent-messaging-a2a-gateway:0.1.0
Compose runs first-run setup once, which makes the operator key, the signing keys,
the broker's settings and the first admin token, and keeps them all in the Compose
volume config. Then it starts NATS, the server on port 3005 and the A2A
gateway on port 8090. Every port is published on 127.0.0.1 only, so the mesh is
reachable from this host and nowhere else until you decide otherwise.
Check that it is healthy:
docker compose exec server /entrypoint.sh mesh-admin status
Mesh: agent-messaging Server: run from source (no release number) Agent Messaging 0.7.0, core profile, wire protocol 0.3, tenancy: one_nats_account The AgentMesh platform beside it: no Live revocation: on Credential minting: on Tenants 0, agents 0, credentials 0, stops in force 0 (0 placed with this tool) Signed in with the admin token: first-run
The capabilities answer is public and names the version of Agent Messaging, the
profile and the broker: curl http://localhost:3005/v1/capabilities.
Keep a copy of the operator key. It is the mesh's identity.
If it is lost, every agent's credential has to be issued again under a new mesh.
docker compose logs setup says where it is, and
docker compose cp server:/config/keystore ./operator-keystore-backup
copies it out. Move the copy somewhere safe and offline.
Step two
Watch a message wait for an agent that is away
The repository's first example puts two agents of two companies on your server.
One asks the other for a price while it is online, then again while it is offline.
The second request waits in the offline agent's mailbox and is answered when that
agent comes back. It needs Node.js 22 or newer. From the
deploy/compose/nats folder:
cd ../../../sdk-typescript && npm ci && npm run build cd ../examples && npm ci node run.mjs nats 01
=== 01-two-companies on nats === Two companies on one mesh: tenants acme-mv68zjkx and globex-mv68zjkx. Both agents are connected and the quoting agent is registered. ok: Acme's buyer asked Globex's agent across companies and got a price The quoting agent is offline now. The buyer sends a request anyway. Four seconds later the quoting agent comes back, and finds the request in its mailbox. ok: the request sent while it was away was answered when it returned, 4.1 s after it was sent Done: store and forward between two companies.
node run.mjs nats runs all five examples: two companies, an internal
network with a LangChain agent and a coding agent, an A2A agent joining through the
gateway, the kill switch, and a room where three agents share files. Each has a
README in the
repository's examples folder.
The other broker
Start it on RabbitMQ with Postgres
The RabbitMQ setup works the same way. The two setups use the same host ports, so
stop the NATS one first (docker compose down in its folder), or change
the ports as the next section says.
cd agent-messaging-server/deploy/compose/rabbitmq docker compose up -d docker compose exec server /entrypoint.sh mesh-admin status
This starts Postgres 18, where the server keeps its state, RabbitMQ 4.3, the server
and the gateway. Only ports 3005, 5672 and 8090 are published. Postgres and
RabbitMQ's management API stay on the Compose network, because only the server uses
them. The examples run the same way with node run.mjs rabbitmq 01.
With a Postgres you already run
The bundled Postgres is only the default. To keep the server's state in a database you already run, such as a managed cloud database, put the password in a file on this host and start with the second Compose file:
printf '%s\n' 'the database password' > postgres.password
export MESH_POSTGRES_URL=postgres://mesh@db.example.com:5432/mesh
export MESH_POSTGRES_PASSWORD_HOST_FILE=./postgres.password
docker compose -f compose.yaml -f compose.own-postgres.yaml up -d
The password never goes in the URL or the environment; the containers read it from
the file. The database user needs the right to create tables and functions, because
first-run makes the server's eight tables there (their names start with
ams_). The host in the URL must be reachable from inside the containers:
with Docker Desktop, a database on your own machine is
host.docker.internal. The bundled Postgres is not started.
Settings
Ports, addresses, and starting over
Each Compose folder has an .env.example that lists its settings. Copy it
to .env beside compose.yaml and change what you need.
| Setting | What it does |
|---|---|
SERVER_PORT, GATEWAY_PORT | The host ports of the server (3005) and the A2A gateway (8090). |
NATS_PORT, NATS_WS_PORT, AMQP_PORT | The broker's host ports: 4222 and 4443 on NATS, 5672 on RabbitMQ. |
BIND_ADDRESS | The host address every port is published on, 127.0.0.1 by default. Put TLS in front before you open it to other machines. |
MESH_PUBLIC_URL, MESH_NATS_ENDPOINTS, MESH_AMQP_ENDPOINTS | The addresses agents are given with their credentials. First-run reads them on the first start only, so set them before it when agents will reach the mesh by another name. |
docker compose down stops the mesh and keeps everything.
docker compose down -v deletes the volumes too, keys included, and the
next start is a new mesh whose agents all need new credentials.
Next
Where to go from here
Enrolling agents
Put your own agent on the server with the TypeScript SDK or the adapter.
Enroll one
Choosing a broker
What NATS and RabbitMQ each need, and how big a host to start with.
Compare them
The admin CLI
Tenants, agents, and the kill switch that cuts an agent off live.
Run it
Upgrades and backups
Moving to a new release, backing up, and Kubernetes.
Operate it