NPAMP-CC-MSG — Messaging / Performative Carriage Class (companion to draft-bubblefish-npamp-01)¶
Status: DRAFT companion specification. The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals, as shown here. This document defines the Messaging carriage class (NPAMP-CC-MSG): the carriage of message-passing and performative (speech-act) agent-communication protocols over the N-PAMP Bridge channel
0x000D. It builds on NPAMP-BRIDGE (the bridge framework) and draft-bubblefish-npamp-01 (the core specification). It consumes only code points the core specification and NPAMP-BRIDGE already reserve, and it introduces no change to the core wire format.
1. Scope¶
1.1 What this document carries¶
A message-passing or performative protocol communicates by exchanging messages each
of which is labelled with a performative — a speech act such as inform, request,
query-ref, agree, refuse, propose, or failure — that declares the
communicative intent of the message independently of its content. Protocols in this
family (the FIPA Agent Communication Language family, and message-passing
agent-communication languages with the same shape) carry, alongside the performative, a
small set of well-known message parameters: a sender, one or more receivers, a
conversation identifier that groups related messages into a dialogue, an
ontology that names the vocabulary the content is expressed in, a
content-language that names the formal language the content is encoded in, and
dialogue-threading parameters such as a reply-with token and an in-reply-to
token.
This document defines how such a message is carried over N-PAMP: how its performative and its dialogue-threading parameters are projected onto the NPAMP-BRIDGE envelope, and how the message itself is carried verbatim. It is a carriage class: it specifies the structural carriage common to the whole family. A per-protocol mapping document (for example a FIPA-ACL mapping) pins protocol-specific particulars — the protocol's identifier, its performative vocabulary, and its parameter names — against that protocol's own published specification; this class does the structural work.
1.2 Relationship to NPAMP-BRIDGE¶
NPAMP-CC-MSG is a profile of NPAMP-BRIDGE, not a replacement for it. Every requirement of NPAMP-BRIDGE applies unchanged to a message carried under this class: The foreign message is carried octet-for-octet (NPAMP-BRIDGE §1), the BridgeEnvelope TLV is REQUIRED (NPAMP-BRIDGE §4), correlation is enforced by identifier (NPAMP-BRIDGE §5), foreign errors are preserved (NPAMP-BRIDGE §6), the SafetyLabel TLV governs side effects (NPAMP-BRIDGE §7), and one-way messages carry no reply (NPAMP-BRIDGE §8). This document adds only the rules that are specific to the performative message shape; where this document is silent, NPAMP-BRIDGE governs.
1.3 Not in scope¶
The following are explicitly NOT defined by this document:
- No new wire fields, frame types, TLV types, or channels. This class reuses the NPAMP-BRIDGE frame types and the BridgeEnvelope and SafetyLabel TLVs as the core specification and NPAMP-BRIDGE define them. It reserves nothing of its own. (See §9 for an OPEN QUESTION on an OPTIONAL future metadata TLV that would require a code point not reserved at the time of writing.)
- No performative vocabulary. The set of performatives, their preconditions, and their feasibility/rational-effect semantics belong to the carried protocol's own specification and to its per-protocol mapping document. This class transports a performative label; it does not interpret it.
- No content-language or ontology processing. The message content, the ontology it draws on, and the content-language it is encoded in are carried verbatim inside the foreign message. This class does not parse, validate, translate, or reason over content, ontologies, or content-languages.
- No sender authentication of its own. This class does not establish, attest, or verify the identity asserted in a message's sender parameter (§6). It defines only how a self-asserted sender is carried and how a verified binding, when one exists, is represented.
- No multicast or receiver-set fan-out. An N-PAMP association is point-to-point. A message addressed to multiple receivers is carried as defined in §5.3; this document does not define fan-out delivery to a receiver set across associations.
2. Terminology¶
In addition to the terms of the core specification and NPAMP-BRIDGE:
Performative:
: The speech-act label of a message, declaring its communicative intent (for example
inform, request, agree). Carried as the BridgeEnvelope method field (§4).
Conversation: : A sequence of messages exchanged between agents that are grouped, by a shared conversation identifier, as one logical dialogue.
Conversation identifier: : The protocol's own token that groups messages into a conversation. Distinct from the per-message correlation identifier of NPAMP-BRIDGE (§5).
Sender: : The agent identifier that a message asserts as its originator. Self-asserted unless bound to an N-PAMP identity (§6).
Receiver: : An agent identifier that a message asserts as an intended recipient.
Message metadata: : The well-known message parameters other than content — performative, sender, receiver, conversation identifier, ontology, content-language, and dialogue-threading tokens.
3. Carriage model¶
3.1 Carriage by projection plus verbatim body¶
A performative message is carried by projecting two of its parameters onto the NPAMP-BRIDGE envelope and carrying the entire message verbatim as the foreign message:
BridgeEnvelope TLV (Type 0x0010, REQUIRED)
protocol_id = the message-passing protocol's identifier (§4.1)
message_kind = derived from the performative class (§4.2)
content_type = the foreign-message encoding (§4.3)
method = the performative label (§4.4)
correlation_id = the dialogue-threading token (§5)
SafetyLabel TLV (Type 0x0013, OPTIONAL; REQUIRED per §7)
<foreign message> (the complete performative message, carried verbatim)
The projection is a non-destructive index, not a re-serialization. The performative and the dialogue-threading token are projected into the envelope so that an N-PAMP implementation can route, correlate, and apply safety policy without parsing the foreign message; the message's own copy of those parameters, and every other parameter (sender, receiver, conversation identifier, ontology, content-language, content), remain present and authoritative inside the verbatim body.
A receiver MUST treat the foreign message as the authoritative source of every message parameter. Where a projected envelope field and the foreign message's own field disagree, the foreign message's field is authoritative for protocol semantics; see §8 for the handling of such a disagreement.
3.2 Transparency is preserved¶
Because the message is carried octet-for-octet (NPAMP-BRIDGE §1), this class does not canonicalize, reorder, re-encode, or strip any message parameter. A self-asserted sender, an omitted optional parameter, and the message's own encoding are all preserved exactly as the originating agent emitted them. An implementation MUST NOT rewrite the foreign message to add, remove, normalize, or reconcile a projected parameter.
4. Mapping onto the BridgeEnvelope¶
4.1 protocol_id¶
The protocol_id field of the BridgeEnvelope identifies the message-passing protocol
being carried, drawn from the Bridge Protocol Identifier value space defined by
NPAMP-BRIDGE (protocol_id, §4). A per-protocol mapping document assigns the value used
for a given protocol; until such an assignment is registered, a deployment carrying a
message-passing protocol MUST use a value from the experimental range that NPAMP-BRIDGE
designates for the protocol_id field, and the two peers MUST agree on that value out of
band. This document does not assign any protocol_id value (§9, OPEN QUESTION 1).
4.2 message_kind and frame type¶
The performative determines the NPAMP-BRIDGE message kind and, with it, the frame type, according to the performative's reply discipline:
| Performative class | message_kind | Frame type | Reply discipline |
|---|---|---|---|
Expects exactly one reply (for example a request or query-ref that names a reply token) |
0x01 request | BRIDGE_REQUEST 0x0100 |
A single reply, correlated per §5. |
Is itself a reply to an earlier request (for example agree, refuse, inform answering a query, failure) |
0x02 response, or 0x04 error | BRIDGE_RESPONSE 0x0101, or BRIDGE_ERROR 0x0102 |
Echoes the originating request's correlation identifier (§5). |
Expects no reply (a one-way announcement, for example an unsolicited inform) |
0x03 notification | BRIDGE_NOTIFY 0x0103 |
No reply; corr_len MUST be 0 (NPAMP-BRIDGE §8). |
The message_kind field MUST agree with the frame type (NPAMP-BRIDGE §4). A per-protocol
mapping document MUST specify, for each performative in the carried protocol's
vocabulary, which class of the table above it falls into, because that classification is
protocol-defined and cannot be inferred from the performative label alone. Where the
carried protocol's own parameters determine the reply discipline of an individual
message (for example, the presence or absence of a reply-with token), an implementation
MUST classify that message by those parameters in preference to a default for the
performative.
A failure reply MUST use BRIDGE_ERROR with message_kind 0x04 only when it reports a
foreign-protocol-level failure carried as the protocol's own error or failure message
(for example a failure performative); a failure below the foreign protocol (the
message did not reach the foreign endpoint) is reported as an N-PAMP transport error per
NPAMP-BRIDGE §6 and §4.6 of this document.
4.3 content_type¶
The content_type field of the BridgeEnvelope carries the encoding of the foreign
message as a whole (for example application/json for a JSON-encoded message), drawn
from the values NPAMP-BRIDGE defines. The content-language and ontology of the message
content are message parameters carried inside the verbatim body (§5.4); they are NOT the
BridgeEnvelope content_type and MUST NOT be projected onto it.
4.4 method (the performative)¶
The BridgeEnvelope method field carries the message's performative label as a
UTF-8 string (for example inform, request, query-ref). The value MUST be the
performative exactly as it appears in the foreign message, with no case folding,
abbreviation, or translation. A receiver MUST NOT rely on the projected method value as
the authoritative performative for protocol semantics; it is an index into the
authoritative performative carried in the foreign message (§3.1). A receiver that does
not carry the indicated performative reports MethodUnsupported per NPAMP-BRIDGE §6.
A message whose protocol carries no performative concept is outside the scope of this class and SHOULD be carried under a different carriage class.
5. Conversation, correlation, and message parameters¶
5.1 Correlation identifier versus conversation identifier¶
NPAMP-BRIDGE correlation (§5) and a message-passing protocol's conversation identifier are distinct, and this class keeps them distinct:
- The NPAMP-BRIDGE correlation identifier correlates exactly one reply to exactly one request, within one direction on the Bridge channel. It is consumed by the N-PAMP layer to match a BRIDGE_RESPONSE/BRIDGE_ERROR to its BRIDGE_REQUEST.
- The protocol's conversation identifier groups an arbitrary number of messages — across many request/reply exchanges and in both directions — into one logical dialogue. It is a protocol-level concept consumed by the carried protocol's agents.
An implementation MUST NOT overload one onto the other. The conversation identifier MUST remain inside the verbatim foreign message and MUST NOT be substituted for the correlation identifier, and the correlation identifier MUST NOT be assumed to equal the conversation identifier.
5.2 Deriving the correlation identifier¶
For a message carried as BRIDGE_REQUEST (§4.2), the BridgeEnvelope correlation_id MUST
be a non-empty token, unique among the originating peer's outstanding requests on the
channel in that direction (NPAMP-BRIDGE §5). The originating peer MUST derive it as
follows, in order of preference:
- If the message carries a reply-with token (the protocol's own per-message token
that the responder is asked to echo as an in-reply-to), the originating peer SHOULD use
that token as the
correlation_id, provided it satisfies the uniqueness requirement above. - Otherwise, the originating peer MUST generate a fresh
correlation_idthat satisfies the uniqueness requirement.
A reply message (BRIDGE_RESPONSE or BRIDGE_ERROR) MUST echo the originating request's
correlation_id verbatim (NPAMP-BRIDGE §5), regardless of how that identifier was
derived. Echoing the correlation identifier at the N-PAMP layer does not relieve the
responding agent of carrying the protocol's own in-reply-to token inside the foreign
message when the protocol requires it; the two are carried independently.
5.3 Receivers and addressing¶
The message's receiver parameter (or receiver set) is carried inside the verbatim foreign message and is NOT projected onto the envelope. Carriage over a point-to-point N-PAMP association delivers the message to the single peer at the other end of the Bridge channel; the foreign message's receiver parameter remains authoritative for the carried protocol's addressing semantics. A message naming more than one receiver is carried with its full receiver set intact; this class does not fan the message out to multiple associations (§1.3, item 5).
5.4 Ontology and content-language¶
The ontology and content-language parameters are carried inside the verbatim foreign message and MUST NOT be projected onto the BridgeEnvelope. This class does not require either parameter to be present, does not supply a default for an absent parameter, and does not validate content against an ontology or a content-language. Their presence, absence, and values are preserved exactly as emitted.
6. Sender identity¶
6.1 Sender is self-asserted by default¶
The sender parameter of a carried message is an identifier that the originating agent asserts about itself. In the general case it is self-asserted: the message-passing protocols in scope carry a sender parameter that the sending agent populates and that the protocol itself does not authenticate, sign, or bind to any external identity. A receiver MUST NOT treat a self-asserted sender as an authenticated identity, and MUST NOT grant an authorization decision on the basis of a self-asserted sender alone.
This class carries the self-asserted sender verbatim inside the foreign message (§3.2). It neither strengthens nor weakens the assertion: it does not add authentication the protocol lacks, and it does not strip the parameter.
6.2 Binding to an N-PAMP identity¶
An N-PAMP association authenticates both peers during the handshake (core specification, Protocol Overview and Security Considerations). A deployment MAY treat the handshake-authenticated identity of the peer that originates a carried message as a verified binding for that message's sender, under a locally configured policy that maps the carried protocol's sender identifier to the N-PAMP peer identity. When such a binding is in force:
- A receiver MAY rely on the bound, handshake-authenticated identity for an authorization decision in place of the self-asserted sender.
- A receiver MUST reject (or, per local policy, downgrade to self-asserted) a message whose self-asserted sender does not match the binding the policy requires for the originating peer, because a sender that disagrees with the authenticated origin is an identity-spoofing indicator.
- The binding applies only to the originating peer's own sender assertion. A message that asserts a sender other than the originating peer (for example a relayed or forwarded message) MUST NOT be treated as verified by this binding.
In the absence of such a configured binding, the sender remains self-asserted (§6.1) and this class makes no identity claim about it.
6.3 No new identity machinery¶
This class defines no TLV, frame, or handshake element for sender identity. The verified binding of §6.2 is an application of the N-PAMP handshake identity that the core specification already establishes, governed by local policy; it is not a new wire mechanism, and it introduces no code point.
7. Side effects and safety¶
A performative does not by itself reveal whether acting on a message mutates state: a
request may ask for a read-only computation or for a destructive action, and the
distinction is in the content, not the performative. Therefore:
- When a carried message, if acted upon by the receiving agent, can cause a side effect, the sender MUST attach a SafetyLabel TLV (NPAMP-BRIDGE §7) describing the effect, exactly as NPAMP-BRIDGE requires for any state-mutating request. An intermediary MUST carry the SafetyLabel unchanged.
- A receiver MUST NOT infer
read_onlyfrom the performative label. In particular, a receiver MUST NOT treat arequest,propose, orqueryperformative as read-only on the basis of the label. - Consistent with NPAMP-BRIDGE §7, the absence of a SafetyLabel on a message that can
mutate state MUST be treated as
destructive(fail-safe), not asread_only.
The SafetyLabel describes intent and does not replace authorization (NPAMP-BRIDGE §7); a verified sender binding (§6.2) and a SafetyLabel are complementary inputs to a receiver's authorization decision, not substitutes for it.
8. Envelope/message disagreement¶
Because the performative and the dialogue-threading token appear both as projected envelope fields (§4.4, §5.2) and inside the authoritative foreign message (§3.1), the two can disagree if a sender projects incorrectly or an intermediary tampers with the envelope. A receiver MUST detect and handle such a disagreement:
- The foreign message's parameters are authoritative for protocol semantics (§3.1). A receiver MUST act on the performative and parameters carried in the foreign message, not on the projected envelope values, when it parses the message.
- A receiver that detects a disagreement between the projected
methodand the message's own performative, or between the derivedcorrelation_idand a reply-with token the message carries, MUST treat the frame as malformed and reportEnvelopeMalformed(NPAMP-BRIDGE §6), because the index does not match the indexed message and routing or correlation performed on the projection would be unsound. - A receiver MUST NOT silently "repair" a disagreement by overwriting either side; it rejects the frame so the originator can re-send a consistent one.
9. Errors¶
This class adds no error codes. Failures are reported exactly as NPAMP-BRIDGE §6 defines:
- A foreign-protocol-level failure (for example a
failureorrefuseperformative, or the protocol's own error message) is carried as BRIDGE_ERROR whose foreign message is the protocol's own failure message, verbatim (NPAMP-BRIDGE §4.2 / §6). An implementation MUST NOT reduce such a failure to free text. - A failure below the foreign protocol — a malformed envelope, an unsupported
protocol, an unsupported performative, a message that could not be delivered to the
foreign endpoint, or a local safety refusal — is reported with the corresponding
NPAMP-BRIDGE transport error code (
EnvelopeMalformed,ProtocolUnsupported,MethodUnsupported,NotDelivered,SafetyPolicy). An unsupported performative is reported asMethodUnsupported(§4.4); an envelope/message disagreement is reported asEnvelopeMalformed(§8).
10. Conformance¶
An implementation conforms to NPAMP-CC-MSG if and only if, on the Bridge channel and in addition to conforming to NPAMP-BRIDGE, it:
- Carries each performative message octet-for-octet as the foreign message, with every message parameter — performative, sender, receiver(s), conversation identifier, ontology, content-language, and content — preserved exactly as emitted (§3, §5.3, §5.4);
- Projects the performative onto the BridgeEnvelope
methodfield unchanged, and the message kind and frame type from the performative's reply discipline as classified by the per-protocol mapping, withmessage_kindagreeing with the frame type (§4); - Keeps the NPAMP-BRIDGE correlation identifier distinct from the protocol's conversation identifier, never overloading one onto the other, and derives the correlation identifier per §5.2;
- Treats the sender as self-asserted unless a configured policy binds it to the handshake-authenticated identity of the originating peer, and never treats a self-asserted sender as authenticated (§6);
- Attaches and honors the SafetyLabel for any message that can mutate state, never
inferring
read_onlyfrom a performative and fail-safing on an absent label (§7); - Detects an envelope/message disagreement and rejects the frame rather than repairing it (§8); and
- Reports foreign-protocol failures as preserved foreign error messages and below-protocol failures as the corresponding NPAMP-BRIDGE transport error codes, adding no error codes of its own (§9).
A conformance test suite SHOULD assert each clause above with recorded exchanges that include: a request-bearing performative correlated to its reply; a one-way (no-reply) performative; a message carrying an ontology and a content-language; a state-mutating message with and without a SafetyLabel; a self-asserted sender and a sender under a configured identity binding; and an envelope whose projected performative disagrees with the carried message.
11. Security considerations¶
This document inherits the security considerations of the core specification and of NPAMP-BRIDGE and adds the following.
Self-asserted sender. The sender parameter of a carried message is self-asserted and unauthenticated by default (§6.1). Treating it as an authenticated identity is an authorization vulnerability: any peer can assert any sender. An implementation MUST require either a verified sender binding (§6.2) or an independent authorization input before acting on a sender's asserted identity. The N-PAMP handshake authenticates the peer at the other end of the association; binding that authenticated identity to a message's sender is the only sender authentication this class offers, and it covers only the originating peer's own assertion, not relayed senders.
Performative is not a safety signal. A performative declares communicative intent, not side-effect class. Deriving a read-only/destructive judgement from the performative would let a destructive action ride a benign-looking label; §7 forbids it and requires fail-safe handling of an absent SafetyLabel.
Projection integrity. The projected envelope fields (§4, §5.2) are an index over the authoritative foreign message. A tampered projection could mis-route or mis-correlate a message whose body is intact. The whole frame, including the BridgeEnvelope TLV, is covered by the N-PAMP AEAD protection of the core specification, so an off-path attacker cannot alter the projection undetected; §8 additionally requires a receiver to reject any frame whose projection disagrees with its carried message, closing the gap against a mis-projecting originator.
Conversation-identifier confusion. Overloading the protocol's conversation identifier onto the NPAMP-BRIDGE correlation identifier (§5.1) could let one conversation's messages be correlated as replies to another's, enabling response confusion. Keeping the two identifiers distinct, as §5.1 requires, prevents this.
No content processing. This class does not parse message content, ontologies, or content-languages (§1.3). It therefore introduces no content-parsing attack surface of its own; the security of content interpretation is the responsibility of the receiving agent and the carried protocol's specification.
12. Relationship to other companion specifications¶
NPAMP-CC-MSG is one carriage class of the N-PAMP companion set. It inherits NPAMP-BRIDGE
in full (§1.2). A per-protocol mapping document for a specific message-passing protocol
selects this class, assigns the protocol's protocol_id, and pins the protocol's
performative vocabulary and parameter names; that mapping does the protocol-specific work,
while this class does the structural work common to the family. Until a per-protocol
mapping is published, a message-passing protocol remains carriable through the opaque
carriage class, with the metadata-projection benefits of this class becoming available
once its mapping is registered.
Appendix A. Open questions for the maintainer¶
These items require a maintainer decision and are recorded here, outside the normative text, so that the normative text consumes no code point that the core specification or NPAMP-BRIDGE has not already reserved.
OPEN QUESTION 1 — No protocol_id is assigned to any message-passing protocol. The
BridgeEnvelope protocol_id value space (NPAMP-BRIDGE §4: 0x01–0x04 assigned,
0x10–0x7F experimental, 0x80–0xFF private use) assigns no value to a message-passing
protocol, and the protocol-identifier registry (NPAMP-REG) is not yet published. This
document therefore directs deployments to the experimental range with out-of-band
agreement (§4.1). A maintainer decision is needed on whether to assign a stable
protocol_id for the first message-passing protocol (for example the FIPA-ACL family) in
NPAMP-REG, and which value.
OPEN QUESTION 2 — A dedicated MessageEnvelope TLV is intentionally NOT defined. Sender,
receiver, conversation identifier, ontology, and content-language are carried inside the
verbatim foreign message (§5), not in a dedicated TLV, because routing/correlation/safety
need only the performative (projected to method) and a correlation token, and because no
carriage-class TLV code point is available to define one: the core specification reserves
TLV tags 0x0010, 0x0013, and 0x0014 for companion specifications, NPAMP-BRIDGE has
consumed 0x0010 (BridgeEnvelope) and 0x0013 (SafetyLabel), and the only remaining
reserved companion tag, 0x0014, is reserved as handshake-only and fixed
32-octet in the core TLV registry — unsuitable for a variable-length, per-message
metadata TLV. If a future need arises to project message metadata into a typed TLV (for
example to let an intermediary route on conversation identifier without parsing the body),
the core specification would have to reserve an additional, variable-length,
per-frame-eligible companion TLV tag for it. A maintainer decision is needed on whether to
request that reservation; absent it, the verbatim-body carriage of this document is the
complete and code-point-clean design.
OPEN QUESTION 3 — Sender-binding policy is deployment-local. The verified sender binding (§6.2) is governed by local policy mapping a carried protocol's sender identifier to an N-PAMP peer identity. Whether the companion set should standardize a binding descriptor (so two peers can agree on the mapping in band rather than out of band) is a maintainer decision; standardizing one would require its own representation and, if carried on the wire, a reserved code point not available today (see OPEN QUESTION 2).