Portal Community

The Envelope at a Glance

The ANCP envelope is a flat JSON object. Every message — regardless of transport, message type, or payload content — shares this outer structure. The envelope contains all the metadata the router, security layer, and observability infrastructure need, while leaving the payload field free for arbitrary content.

{
  "id":              "3f7a9c1e-4b2d-4e8f-9a1c-0d5e7f8b3a2d",
  "type":            "Command",
  "source":          "node://tenant-acme/flow-42/data-transform",
  "destination":     "node://tenant-acme/flow-42/approval-gate",
  "tenantId":        "tenant-acme",
  "timestamp":       "2026-05-25T09:14:00.000Z",
  "protocolVersion": "1.0",
  "correlationId":   "corr-7e8a9b0c-1d2e-3f4a-5b6c-7d8e9f0a1b2c",
  "payload": {
    "formData": { "employeeId": "E-1042", "amount": 750.00 },
    "context":  { "requestedBy": "user-88", "workflowRunId": "run-9981" }
  }
}

Header Fields (Required)

These fields must be present on every ANCP message. A missing or malformed required field causes the router to reject the message before any handler sees it.

FieldTypeDescription
id required string (UUID v4) Globally unique message identifier. Producers must generate a fresh UUID for every message. Used for deduplication and audit trails.
type required "Command" | "Event" | "Query" | "Response" Semantic message type. Determines routing behaviour, expected reply semantics, and how the message is logged.
source required string Structured URI identifying the sender. Format: {scheme}://{tenantId}/{...path}. Example: node://tenant-1/flow-7/step-3.
destination required string Structured URI identifying the intended recipient. The router resolves this to a transport endpoint or pub/sub topic.
tenantId required string Tenant scope for this message. The router verifies that source, destination, and tenantId are all consistent. Cross-tenant messages are rejected.
timestamp required string (ISO 8601) UTC timestamp when the message was created by the producer. Always in ISO 8601 format with millisecond precision.
protocolVersion required string ANCP version this message conforms to. Consumers use this to choose the correct deserializer. Current value: "1.0".
payload required object Message-specific content. Schema is defined per message type and documented in the relevant node or agent specification. May be an empty object {} for Events with no data.

Header Fields (Optional)

FieldTypeDescription
correlationId optional string (UUID v4) Links a Response back to its originating Query or Command. The producer of the original request sets this; the responder copies it into the reply.
replyTo optional string Address (same URI format as source) where the recipient should send its Response. Used when the reply destination differs from the source.
ttl optional number (milliseconds) Time-to-live. The router discards the message if more than ttl ms have elapsed since timestamp. Useful for time-sensitive Commands.
priority optional number (0–9) Delivery priority hint for queuing transports. Higher values are processed first. Default is 5.
traceId optional string Distributed trace ID (W3C Trace Context format). Set by the entry-point service and propagated unchanged through the call chain for end-to-end tracing.
sessionId optional string User session identifier. Carried by messages originating from browser clients; used by EdgeStream to scope subscriptions to a session.

The Payload Field

The payload field is a free-form JSON object. ANCP does not constrain its schema — that is defined by the node, agent, or service that produces the message. The convention is to structure payload with two sub-objects:

"payload": {
  "data": {
    // The actual business content of the message
  },
  "meta": {
    // Optional message-level metadata beyond the header fields
    // e.g., pagination, content-type hints, schema reference
  }
}
Convention, Not Enforcement

The data/meta split inside payload is a recommended convention. Individual nodes may use a flat payload structure when appropriate. Routers and infrastructure only read the header fields above — the payload is opaque to them.

Relationship to EdgeStream IEnvelope

At the transport layer, ANCP messages travel inside EdgeStream's IEnvelope. The mapping is:

ANCP FieldIEnvelope LocationNotes
idmeta.idDirect mapping
typemeta.typeStored as string
sourcemeta.sourceDirect mapping
destinationmeta.topicRouter resolves destination URI to pub/sub topic
tenantIdbody.data.metadata.tenantIdAlso verified against SignalR JWT claim
timestampmeta.receivedAtTransport records its own receivedAt; original timestamp in payload
correlationIdmeta.correlationIdDirect mapping
payloadbodyThe ANCP payload becomes the envelope body

Validation Rules

1

Schema Check

All required fields (id, type, source, destination, tenantId, timestamp, protocolVersion, payload) must be present and non-null.

2

Type Enum Check

The type field must be exactly one of: Command, Event, Query, Response. Case-sensitive.

3

Tenant Consistency

The tenantId in the envelope must match the tenant claim in the bearer token (SignalR) or the API key scope (HTTP). Mismatch = 403.

4

TTL Check

If ttl is present, the router computes now - timestamp. If the result exceeds ttl, the message is discarded and a dead-letter event is emitted.

5

Route

Message passes validation and is routed to the resolved destination handler.

Tip: Use correlationId for Request/Response Pairing

When sending a Query, generate a UUID and set it as correlationId. Subscribe to your replyTo address and match incoming Responses by correlationId. This is the standard pattern for synchronous-style interactions over asynchronous ANCP.