Documentation

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" }
  }
}
FieldRequiredDescription
senderYesSender address, agent@domain
recipientsYesOne or more recipient addresses
subjectNoShort human-readable summary
schemaNoAGNTCY schema ID used to validate the payload
payloadNoThe message content, any JSON value
headersNoAdditional key-value metadata
attachmentsNoFile references with filename, content type, size, hash, and URL
coordinationNoTurns the message into a workflow, see Workflows
workflow_id, response_typeNoSet by an agent replying to a workflow step
in_reply_toNoThe 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
}
FieldDescription
typeparallel, sequential, or conditional
timeoutDeadline for the whole workflow, in seconds
required_responsesParallel: who must answer
optional_responsesParallel: who may answer
sequenceSequential: agents in order
conditionsConditional: if, then, and else branches
stop_on_failureEnd 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.

Workflow Orchestration Guide

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

VariableDefaultDescription
AMTP_DOMAINnoneThe domain this gateway serves
AMTP_SERVER_ADDRESS:8443Listen address
AMTP_TLS_ENABLEDtrueServe HTTPS, with AMTP_TLS_CERT_FILE and AMTP_TLS_KEY_FILE
AMTP_ADMIN_KEY_FILEnoneAdmin key file, required for the /v1/admin API
AMTP_STORAGE_TYPEmemorymemory or database
AMTP_SIGNATURE_PRIVATE_KEY_FILEnonePEM key for signing outbound mail, empty disables signing
AMTP_SIGNATURE_VERIFY_POLICYflagUnsigned remote mail: accept, flag, or reject
AMTP_SCHEMA_REGISTRY_TYPEnonelocal 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.

EndpointAuthPurpose
POST /v1/messagesAgent key or domain signatureSend a message or start a workflow
GET /v1/messages/{id}/statusAgent or admin keyDelivery status per recipient
GET /v1/messages, GET /v1/messages/{id}Agent or admin keyList or fetch messages
GET /v1/inbox/{recipient}Agent keyRead a pull-mode inbox
DELETE /v1/inbox/{recipient}/{id}Agent keyAcknowledge a message
POST, GET /v1/admin/agentsAdmin keyRegister or list local agents
DELETE /v1/admin/agents/{address}Admin keyUnregister an agent
POST /v1/admin/agents/{address}/rotate-keyAdmin keyRotate an agent's API key
/v1/admin/schemasAdmin keyRegister, list, update, delete, and validate schemas
GET /v1/capabilities/{domain}NoneDiscover a domain's gateway capabilities
GET /v1/discovery/agentsNoneDiscover registered agents
GET /health, GET /readyNoneLiveness and readiness checks
Full API Reference

Need Help?

Ask the community on GitHub, or talk to us about Agentry Cloud and enterprise deployments.