Agentry Gateway Documentation
Run the gateway, connect your agents, and orchestrate multi-agent workflows.
Agentry Gateway implements AMTP v1.0: agents get an agent@domain address, messages are delivered across organizations through DNS discovery and domain signatures, and workflows run in the gateway.
Quick Start
Run a gateway locally, register two agents, and deliver your first message. You need Docker, Git, and OpenSSL.
1. Build and run the gateway
The admin API stays closed until an admin key file is configured, so create one first.
# Build the image
git clone https://github.com/amtp-protocol/agentry.git && cd agentry
make docker-build
# Create an admin key and start the gateway
mkdir -p keys && openssl rand -hex 32 > keys/admin.keys
export ADMIN_KEY=$(cat keys/admin.keys)
docker run -d -p 8443:8443 \
-e AMTP_DOMAIN=localhost \
-e AMTP_TLS_ENABLED=false \
-e AMTP_ADMIN_KEY_FILE=/app/keys/admin.keys \
-v $(pwd)/keys:/app/keys:ro \
agentry:latest
curl http://localhost:8443/health
2. Register two agents
A short address like alice becomes alice@localhost. Each response contains the agent's
api_key, which the agent uses to send messages and read its inbox.
for name in alice bob; do
curl -X POST http://localhost:8443/v1/admin/agents \
-H "Content-Type: application/json" \
-H "X-Admin-Key: $ADMIN_KEY" \
-d "{\"address\": \"$name\", \"delivery_mode\": \"pull\"}"
done
# Save the keys from the responses
export ALICE_KEY=...
export BOB_KEY=...
3. Send a message
Senders on the gateway's own domain authenticate with their agent API key.
curl -X POST http://localhost:8443/v1/messages \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ALICE_KEY" \
-d '{
"sender": "alice@localhost",
"recipients": ["bob@localhost"],
"subject": "Hello",
"payload": {"text": "Hello from Alice"}
}'
4. Read and acknowledge
Pull-mode agents poll their inbox and acknowledge each message once it is handled.
curl -H "Authorization: Bearer $BOB_KEY" \
http://localhost:8443/v1/inbox/bob@localhost
curl -X DELETE -H "Authorization: Bearer $BOB_KEY" \
http://localhost:8443/v1/inbox/bob@localhost/<message_id>
Core Concepts
AMTP borrows what email got right about talking to strangers, and adds structure and coordination.
Addressing and Discovery
- Every agent has an agent@domain address
- A
_amtp.<domain>DNS TXT record points to the domain's gateway - Each organization runs its own gateway, with no central registry
- Behind the gateway, an agent can use any framework or language
Delivery
- Push to the agent's webhook, or pull from its inbox
- At-least-once delivery, with idempotency keys to drop duplicates
- Retries with exponential backoff on retryable errors
- Per-recipient delivery status for every message
Trust
- Local agents authenticate with their own API key
- Remote gateways sign each message with the domain's key, like DKIM
- Public keys are published at
<keyid>._amtpkey.<domain> - Unsigned remote mail is accepted, flagged, or rejected by policy
Schemas
- Payloads can declare an AGNTCY schema ID, such as
agntcy:commerce.order.v1 - The gateway validates payloads before delivery
- Use a local directory or the database as the schema registry
- Manage schemas through the admin API
Message Format
An AMTP message is a JSON document. Send one with a single request to your gateway.
POST /v1/messages
Authorization: Bearer <sender agent api_key>
{
"sender": "orders@company.com",
"recipients": ["fulfillment@partner.com"],
"subject": "New order",
"schema": "agntcy:commerce.order.v1",
"headers": { "priority": "high" },
"payload": {
"action": "process_order",
"data": { "order_id": "ORD-001", "amount": 99.99, "currency": "USD" }
}
}
| Field | Required | Description |
|---|---|---|
| sender | Yes | Sender address, agent@domain |
| recipients | Yes | One or more recipient addresses |
| subject | No | Short human-readable summary |
| schema | No | AGNTCY schema ID used to validate the payload |
| payload | No | The message content, any JSON value |
| headers | No | Additional key-value metadata |
| attachments | No | File references with filename, content type, size, hash, and URL |
| coordination | No | Turns the message into a workflow, see Workflows |
| workflow_id, response_type | No | Set by an agent replying to a workflow step |
| in_reply_to | No | The message_id being answered |
The gateway fills in version, message_id (UUIDv7), idempotency_key, and
timestamp when the sender omits them. When a signing key is configured, it adds a
signature over the RFC 8785 canonical JSON body, using ES256 or RS256.
Workflows
Add a coordination block to any message, and the gateway runs it as a multi-agent workflow.
"coordination": {
"type": "sequential",
"timeout": 900,
"sequence": [
"research@acme.com",
"writer@acme.com",
"reviewer@acme.com"
],
"stop_on_failure": true
}
| Field | Description |
|---|---|
| type | parallel, sequential, or conditional |
| timeout | Deadline for the whole workflow, in seconds |
| required_responses | Parallel: who must answer |
| optional_responses | Parallel: who may answer |
| sequence | Sequential: agents in order |
| conditions | Conditional: if, then, and else branches |
| stop_on_failure | End early when a step fails |
Agents reply with the workflow_id and response_type: workflow_response, or
workflow_error to fail their step. When the workflow ends, the sender receives one message
with every participant's status and payload.
Deployment
Store state in PostgreSQL, terminate TLS at the gateway, and publish DNS records so other organizations can reach you.
Docker Compose with PostgreSQL
Shared PostgreSQL storage lets multiple gateway replicas run the same workflows. Run this from the root of the agentry repository: the schema in deployment/db is loaded when the database starts.
# docker-compose.yml
services:
agentry:
image: agentry:latest # built with make docker-build
ports:
- "8443:8443"
environment:
- AMTP_DOMAIN=yourcompany.com
- AMTP_TLS_CERT_FILE=/app/certs/tls.crt
- AMTP_TLS_KEY_FILE=/app/certs/tls.key
- AMTP_ADMIN_KEY_FILE=/app/keys/admin.keys
- AMTP_SIGNATURE_PRIVATE_KEY_FILE=/app/keys/signing.pem
- AMTP_STORAGE_TYPE=database
- AMTP_STORAGE_DATABASE_DRIVER=pgx
- AMTP_STORAGE_DATABASE_CONNECTION_STRING=host=postgres port=5432 user=agentry password=change-me dbname=agentry
volumes:
- ./certs:/app/certs:ro
- ./keys:/app/keys:ro
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
postgres:
image: postgres:16
environment:
POSTGRES_USER: agentry
POSTGRES_PASSWORD: change-me
POSTGRES_DB: agentry
volumes:
- ./deployment/db:/docker-entrypoint-initdb.d:ro
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U agentry"]
interval: 10s
retries: 5
volumes:
postgres_data:
DNS records
# Where other gateways deliver mail for your domain
_amtp.yourcompany.com. IN TXT "v=amtp1;gateway=https://amtp.yourcompany.com:443"
# Public key that verifies your domain signatures (selector k1)
k1._amtpkey.yourcompany.com. IN TXT "v=amtpkey1;alg=ES256;p=<base64-public-key>"
Key settings
| Variable | Default | Description |
|---|---|---|
| AMTP_DOMAIN | none | The domain this gateway serves |
| AMTP_SERVER_ADDRESS | :8443 | Listen address |
| AMTP_TLS_ENABLED | true | Serve HTTPS, with AMTP_TLS_CERT_FILE and AMTP_TLS_KEY_FILE |
| AMTP_ADMIN_KEY_FILE | none | Admin key file, required for the /v1/admin API |
| AMTP_STORAGE_TYPE | memory | memory or database |
| AMTP_SIGNATURE_PRIVATE_KEY_FILE | none | PEM key for signing outbound mail, empty disables signing |
| AMTP_SIGNATURE_VERIFY_POLICY | flag | Unsigned remote mail: accept, flag, or reject |
| AMTP_SCHEMA_REGISTRY_TYPE | none | local or database to enable schema validation |
On Kubernetes, use the Helm chart in deployment/chart. Every setting is listed in the configuration reference.
API Reference
A REST API over HTTPS. Agents authenticate with their API key, administrators with the X-Admin-Key header.
| Endpoint | Auth | Purpose |
|---|---|---|
| POST /v1/messages | Agent key or domain signature | Send a message or start a workflow |
| GET /v1/messages/{id}/status | Agent or admin key | Delivery status per recipient |
| GET /v1/messages, GET /v1/messages/{id} | Agent or admin key | List or fetch messages |
| GET /v1/inbox/{recipient} | Agent key | Read a pull-mode inbox |
| DELETE /v1/inbox/{recipient}/{id} | Agent key | Acknowledge a message |
| POST, GET /v1/admin/agents | Admin key | Register or list local agents |
| DELETE /v1/admin/agents/{address} | Admin key | Unregister an agent |
| POST /v1/admin/agents/{address}/rotate-key | Admin key | Rotate an agent's API key |
| /v1/admin/schemas | Admin key | Register, list, update, delete, and validate schemas |
| GET /v1/capabilities/{domain} | None | Discover a domain's gateway capabilities |
| GET /v1/discovery/agents | None | Discover registered agents |
| GET /health, GET /ready | None | Liveness and readiness checks |
Guides
In-depth references for the gateway, the protocol, and the SDK.
Workflow Orchestration
Parallel, sequential, and conditional workflows, agent replies, and failure handling.
Configuration
Every command line flag and AMTP_* environment variable, with examples.
Schema Framework
AGNTCY schema IDs, registries, and payload validation.
AMTP Specification
The protocol itself: addressing, delivery, signatures, and coordination.
Python SDK
Build agents in Python with asyncio. Install with pip install amtp.
Contributing
Build from source, run the tests, and send a pull request.
Need Help?
Ask the community on GitHub, or talk to us about Agentry Cloud and enterprise deployments.