Portal Community

The protocolVersion Field

Every ANCP envelope carries a protocolVersion string in the header. This field tells the receiving router and handler which version of the ANCP specification this message conforms to. Routers use it to select the correct deserializer and to decide whether a compatibility shim is needed.

{
  "id":              "msg-uuid",
  "type":            "Command",
  "protocolVersion": "1.0",   // ← always present, always a string
  // ... other fields ...
}

Version Format

ANCP uses a MAJOR.MINOR versioning scheme:

ComponentWhen it incrementsBackward compatible?
MAJOR A breaking change is introduced — required fields added, field semantics changed, or a type is removed. No — consumers must be updated before accepting new MAJOR messages.
MINOR A non-breaking addition — new optional fields, new optional message types, or additive changes to the payload convention. Yes — consumers that read only the fields they know about continue to work correctly.
Current Version: 1.0

All messages in the current BizFirstGO platform use "protocolVersion": "1.0". ANCP 1.1 (adding optional message signing) is planned. ANCP 2.0 would be a major version with advance deprecation notice of at least 6 months.

Version History

VersionReleasedStatusChanges
1.02026-01CurrentInitial release. Core envelope, four message types, addressing scheme, tenant isolation.
1.1Planned Q3 2026PlannedOptional Ed25519 message signing (signature field). Backward compatible — unsigned messages remain valid.
2.0TBDFutureBreaking changes TBD. Will carry 6-month deprecation window for 1.x.

Router Behaviour for Received Messages

Known Version (exact match)

The router deserializes and processes the message using the matching specification.

Known MAJOR, Higher MINOR

The router applies forward compatibility: it reads the fields it knows about and ignores unknown fields. This is safe for MINOR version increments because they only add optional fields.

// Router logic (pseudocode)
if (message.protocolVersion.major === SUPPORTED_MAJOR) {
  // Safe to process — ignore unknown fields
  processWithKnownFields(message);
} else {
  // Unknown major version — reject with explanation
  rejectWithVersion(message, SUPPORTED_MAJOR);
}

Unknown MAJOR

If the MAJOR version is not supported by the router, the message is rejected with a PROTOCOL_VERSION_UNSUPPORTED error returned to the sender (if the sender is reachable via a Response). The sender must downgrade or the router must be updated.

Sender Responsibility

Message producers must always set protocolVersion to the version they are targeting. Do not omit it, do not default it dynamically at runtime — set it explicitly in the message construction code so upgrades are intentional and visible in code review.

// TypeScript — building an ANCP envelope
const envelope: AncpEnvelope = {
  id:              generateUuid(),
  type:            'Command',
  source:          AncpAddress.node({ tenantId, flowId, nodeId }),
  destination:     AncpAddress.node({ tenantId, flowId, nextNodeId }),
  tenantId:        tenantId,
  timestamp:       new Date().toISOString(),
  protocolVersion: '1.0',    // ← explicit, never computed
  payload:         { action: 'proceed', data: outputData }
};

Migration Strategy for Breaking Changes

When ANCP 2.0 (or any future MAJOR version) is released, the platform runs both versions in parallel during a transition window. The router is updated first to accept both MAJOR versions. Nodes and agents are then updated incrementally. Only after all producers and consumers have migrated is support for the old MAJOR version removed.

1

Announce + Release New MAJOR

6-month deprecation notice. Release 1.x compatibility window alongside 2.0.

2

Update Router

Router accepts both old and new MAJOR. Applies compatibility shims for old messages if needed.

3

Update Producers

All message-sending nodes and agents upgraded to emit new MAJOR. Old consumers still work via shim.

4

Update Consumers

All message-receiving nodes and agents upgraded to accept new MAJOR natively.

5

Remove Old MAJOR Support

After all producers and consumers are on the new MAJOR, the router stops accepting old MAJOR messages.

Detecting Version in Handlers

Handler code that needs to branch on version should read protocolVersion from the envelope and handle explicitly:

// C# — version-aware handler
public async Task HandleAsync(AncpEnvelope envelope)
{
    var version = Version.Parse(envelope.ProtocolVersion);

    if (version.Major == 1)
    {
        await HandleV1Async(envelope);
    }
    else
    {
        _logger.LogWarning("Unsupported ANCP major version {Version}", version.Major);
        // Return a Response with error status rather than throwing
        await SendErrorResponseAsync(envelope, "UNSUPPORTED_VERSION");
    }
}
Do Not Hard-Code Version Strings in Routing Logic

Read the version from a configuration or constant — never scatter "1.0" literals through routing and handler code. When the platform version changes, you want a single place to update, not a grep-and-replace across dozens of files.