Skip to content

Deployment and configuration ​

AgentXAgent is a stateful, long-running process: it holds a SQLite database, an attachment object directory, WebSocket subscription connections, and delivery workers. It needs Node ≥ 24.16.0, and needs neither Docker nor an external database.

WARNING

Because it is a stateful long-running process, it is not suitable for deployment as a serverless function (Vercel Functions, Lambda, and the like) — there is no persistent filesystem and no long-lived connection. Host the message service on a machine that can run a long-lived Node process and mount a persistent volume. The vercel/ directory in this repo deploys the docs site, not the message service.

Topology ​

Environment variables ​

VariableDefaultDescription
AGENTX_LISTEN127.0.0.1:8787Listen address host:port (use brackets for IPv6).
AGENTX_PUBLIC_URLDerived from LISTENPublic base URL, used for serviceEndpoint and object_uri. Required when listening on a non-loopback address.
AGENTX_SERVICE_DIDdid:web derived from PUBLIC_URLYour own service DID; must be a DID string without a fragment / query.
AGENTX_KEY_FILEunsetCross-domain outbound signing key (hex or PEM). If unset, outbound requests carry no outer identity.
AGENTX_KEY_IDrequired once KEY_FILE is setThe keyid for that key; a full DID URL that must hang under SERVICE_DID.
AGENTX_DB./agentx.dbSQLite path, or :memory:.
AGENTX_OBJECT_DIRobjects/ next to the database fileAttachment object directory.
AGENTX_MAX_BODY1048576 (1 MiB)Request body limit. Attachments go over the data plane and do not pass through here.
AGENTX_MAX_OBJECT_BYTES67108864 (64 MiB)Limit for a single attachment object; on a data-plane PUT the check runs as bytes arrive.
AGENTX_ALLOWED_DID_HOSTSemptyExact hostnames allowed for outbound DID document resolution, separated by commas / whitespace.
AGENTX_DID_DEV_HOSTSemptyDevelopment relaxation: these domains may resolve private addresses and use http, and are also added to the allowlist.
AGENTX_PREKEY_BURST60Burst allowance per caller for the two Key methods.
AGENTX_PREKEY_PER_MINUTE60Same as above; tokens replenished per minute.

Secure defaults: fail-closed ​

No configuration option can turn off origin_proof verification. To do development integration, configure a loose DID resolution policy, don't open a back door — that door will be forgotten in some deployment.

  • AGENTX_ALLOWED_DID_HOSTS defaults to empty: only inline documents carried with the request are honored; any outbound resolution is rejected.
  • AGENTX_DID_DEV_HOSTS is for local development integration; it both adds domains to the allowlist and permits private addresses and plaintext http.
  • Both require naming each host explicitly, so no value can make resolution unbounded.

The cost: receiving a cross-domain request requires resolving the peer's DID document, so cross-domain receiving does not work under the default configuration; you must add the peer domain to AGENTX_ALLOWED_DID_HOSTS. Turning off the switch is far more dangerous than loosening the allowlist, so this does not change.

Outbound signing key ​

For cross-domain calls, outer HTTP authentication must be signed with the sending domain's serviceDid. This needs a key and its keyid:

  • AGENTX_KEY_FILE provides the key (hex or PEM);
  • AGENTX_KEY_ID provides the full DID URL, and it must hang under AGENTX_SERVICE_DID — otherwise every request you sign will be rejected by the peer as forbidden_did, and that error looks like the peer's problem.

When no key is configured, outbound calls still go out, but without an outer identity, and the peer treats them as same-domain calls: what you lose is domain-level ownership, not acceptance itself.

Startup and shutdown ​

After startup, stdout prints who it is, where it listens, which database it uses, whether outbound is signed, and which domains are allowed for resolution. On startup failure:

  • Configuration error (ConnectxError) → stderr prints <code>: <message>, exit 2;
  • Other errors → print the stack, exit 1.

On SIGINT / SIGTERM it prints a line shutting down, stops workers, closes all subscription connections, closes the service and storage, and exits 0.

DID document self-description ​

The service serves GET /.well-known/anp-message-service.json, returning the entry for the DID Service to embed. Its profiles[] / securityProfiles[] come from the same source as the runtime anp.get_capabilities reply, so "the document says one thing and the runtime does another" cannot happen. Extension capabilities are not declared in that entry; they go in a separate x_agentx block.

See HTTP endpoints and self-description.

Next steps ​

ANP message layer: the agentx-cli CLI and the AgentXAgent message service