Message Types
ANCP defines four semantic message types — Command, Event, Query, and Response — covering every interaction pattern between nodes, agents, and services in BizFirstGO.
Why Four Types?
Rather than leaving message semantics implicit in payload schemas, ANCP makes them explicit in the type field of every envelope. This allows routers to apply different delivery guarantees, allows observability tools to categorize message flows automatically, and makes code self-documenting.
| Type | Pattern | Reply Expected? | Typical Use |
|---|---|---|---|
| Command | Point-to-point | Optional | Trigger an action on a specific target |
| Event | Publish/Subscribe | No | Notify interested parties that something happened |
| Query | Request/Response | Yes (Response) | Request data or a computed result from an agent |
| Response | Point-to-point | No | Reply to a Query or acknowledge a Command |
Command
What it is
A Command instructs a specific node or agent to perform an action. The sender knows who should act and what they should do. Commands are directed — the destination field points to a single target, not a topic.
Reply Semantics
Commands are fire-and-forget by default. If the sender needs acknowledgement, it sets replyTo and correlationId, and the recipient sends a Response back. If no reply is needed, the recipient acts silently.
Example
{
"id": "cmd-001-uuid",
"type": "Command",
"source": "node://tenant-acme/flow-42/trigger",
"destination": "node://tenant-acme/flow-42/send-email",
"tenantId": "tenant-acme",
"timestamp": "2026-05-25T09:00:00.000Z",
"protocolVersion": "1.0",
"payload": {
"action": "sendEmail",
"to": "employee@acme.com",
"subject": "Your expense was approved",
"templateId": "expense-approved-v2"
}
}
Use a Command when you want something to happen. Use a Query when you want to know something. Commands drive state changes; Queries read state.
Event
What it is
An Event announces that something has occurred. The producer does not know who is listening — it simply publishes to a topic. Zero or more subscribers may react. This decouples producers from consumers entirely.
Reply Semantics
Events are always fire-and-forget. Do not set replyTo or correlationId on an Event. No response is expected or sent.
Topic Convention
The destination field on an Event is a topic path, not a node address. The router publishes to all active subscribers of that topic. Format: topic://{tenantId}/{domain}/{event-name}.
Example
{
"id": "evt-001-uuid",
"type": "Event",
"source": "node://tenant-acme/flow-42/approval-gate",
"destination": "topic://tenant-acme/expenses/approved",
"tenantId": "tenant-acme",
"timestamp": "2026-05-25T09:05:00.000Z",
"protocolVersion": "1.0",
"payload": {
"expenseId": "EXP-9981",
"approvedBy": "manager-joe",
"amount": 750.00,
"currency": "USD"
}
}
Wildcard Subscriptions
Subscribers can use wildcards to match multiple topics:
| Pattern | Matches |
|---|---|
topic://tenant-acme/expenses/* | All expense events (approved, rejected, submitted…) |
topic://tenant-acme/*/* | All events for this tenant |
topic://tenant-acme/expenses/approved | Only expense approved events |
Query
What it is
A Query requests data or a computed result from a specific agent or node. It is the ANCP equivalent of a function call — the sender asks a question and waits for the answer in a Response. Queries are point-to-point: the destination points to the agent that can answer.
Required Fields
Queries must set correlationId (so the Response can be matched) and replyTo (the address where the Response should be sent).
Example
{
"id": "qry-001-uuid",
"type": "Query",
"source": "node://tenant-acme/flow-42/policy-check",
"destination": "agent://tenant-acme/octopus/policy-agent",
"tenantId": "tenant-acme",
"timestamp": "2026-05-25T09:02:00.000Z",
"protocolVersion": "1.0",
"correlationId": "corr-qry-001-uuid",
"replyTo": "node://tenant-acme/flow-42/policy-check",
"payload": {
"query": "isExpenseAllowed",
"params": {
"employeeId": "E-1042",
"amount": 750.00,
"expenseType": "travel"
}
}
}
Response
What it is
A Response is the reply to a Query (or an optional acknowledgement to a Command). The recipient of the original Query sends a Response addressed to the sender's replyTo address, carrying the same correlationId.
Status Convention
Responses include a status field in the payload to indicate success or failure, along with an optional error object for failure cases.
Example
{
"id": "rsp-001-uuid",
"type": "Response",
"source": "agent://tenant-acme/octopus/policy-agent",
"destination": "node://tenant-acme/flow-42/policy-check",
"tenantId": "tenant-acme",
"timestamp": "2026-05-25T09:02:01.432Z",
"protocolVersion": "1.0",
"correlationId": "corr-qry-001-uuid",
"payload": {
"status": "success",
"data": {
"allowed": true,
"policyRef": "POL-2026-TRAVEL",
"maxAmount": 1000.00,
"requiresReceipt": true
}
}
}
Choosing the Right Type
Do you know who should handle it?
If yes, use Command or Query. If no (any interested party), use Event.
Do you need data back?
If yes, use Query. If you just need something to happen (possibly with an ack), use Command.
Are you replying to someone?
Use Response. Copy the correlationId from the Query or Command you received.
If you expect a specific target to act and you care about whether it succeeded, do not use Event. Events have no delivery guarantee beyond pub/sub dispatch — there is no built-in retry, timeout, or error reporting. Use Command or Query for reliability.