cxp package
Reviewed against commit 8a2cb42ad on 2026-10-23.
Reference: package page (37 modules, 9,628 lines, plus the proto subpackage) · key modules: servicer, transport, direct_transport, direct_cxp_adapter, endpoint_config, router, dispatcher, prolog_bridge. The packet type itself now lives in core.packet. Where CXP sits among the layers and how a request travels over it is explained in the overview.
The story
Orchestrata is a multi-agent system whose Volks — the specialized agents (Concierge, Analyst, PM, Architect, QA, and the rest) — constantly hand work to one another. Left unstructured, that traffic would be a soup of ad-hoc payloads with no identity, ordering, or accountability. orchestrata_ultimate.cxp exists to prevent that: it implements the Cross-agent eXchange Protocol (Spec 004), the single wire format and lifecycle model for every agent-to-agent message in the system. Everything a Volk says to another Volk travels as a CXPPacket — a flat, typed record (message id, from_agent/to_agent volk aliases, thread id, subject, priority, delivery and work status, protocol version, plus payload and routing metadata) — so the rest of the platform can route, govern, track, and replay conversations uniformly.
A packet's life starts in the packet model. Until the packet vocabulary moved down a layer, this lived in _packet_impl.py, _packet_enums.py and packet.py inside this package; those modules are gone. CXPPacket is now defined in core/packet/ (layer 0, so that every package can use it without importing cxp), and the constructor accepts either the modern flat field API or a legacy PacketHeader (kept in the deprecated core.packet.compat), then self-validates. Two small state machines live inside the packet itself: mark_delivered/mark_failed/mark_acknowledged walk the delivery status through the legal transitions defined in core/packet/enums.py, and start_work/resolve_work/archive_work/requeue_work walk the work status; an illegal jump raises StateTransitionError. A packet can validate itself into a ValidationResult, mint an acknowledgement with create_ack, or turn itself into an error reply with create_error. To leave the process it is serialized — JSONSerializer (via the CXPEncoder) for readable JSON, BinarySerializer for a compact msgpack-backed encoding, both behind the ISerializer protocol — and carried over one of two transports. Until 2026-08 the primary transport was gRPC (grpc_client.py/grpc_server.py, backed by the generated proto/ stubs); grpcio was retired on 2026-08-07 and those two modules were removed. Its replacement is the cxpt direct transport: direct_transport.py is an async wrapper over the free-threaded cxpt package (DirectServer, AsyncDirectClient), direct_cxp_adapter.py adapts it to the CXP server and client shapes (DirectCXPServer, DirectCXPClient) over the shared, transport-neutral servicer.py (CXPServicer, CXPServerConfig), transport.py builds the server or client through the CXPServerLike/CXPClientLike protocols, proto_codec.py converts packets to and from the protobuf messages (CXPPacketCodec, CXPClientConfig), and reply_router.py routes replies per consumer (SPEC-001 US-002). The second transport, WebSocket (ws_client.py/ws_server.py), is unchanged. Endpoints are never hardcoded: endpoint_config.py is the single source of truth and reads host/port from the environment at call time (CXP_GRPC_PORT, CXP_GRPC_ENDPOINT, CXP_GRPC_HOST — the names keep the old GRPC wording), raising CXPConfigError when unset. deterministic_ids.py adds reproducible UUID v5 packet ids for the Postman sync router.
On arrival, CXPRouter decides where the packet goes — and crucially, whether it is allowed to go there. It keeps a routing table (seeded with defaults: every Volk may talk to Postman and the Orchestrator; those two may reach any registered Volk) and, when a PrologBridge is wired in, consults governance before returning a RoutingResult. The bridge asserts each packet as a cxp_packet/12 fact into the real janus-swi Prolog engine (converting volk aliases to escaped atoms) so policy rules such as can_send_to/2 and validate_packet/2 can approve or deny the route; with no Prolog backend installed it degrades gracefully. Approved packets flow to CXPDispatcher, which combines routing with delivery, retries up to a bound, and records every outcome as a DeliveryResult. Two dedicated trackers keep the lifecycle honest and queryable outside the packet: DeliveryTracker (delivery_status) records status history, failure reasons, and retry counts, while WorkTracker (work_status) times each work item from start to resolution. CXPValidator and SchemaRegistry provide rule- and JSON-Schema-based validation, and version.py/version_compat.py let differently-versioned peers negotiate compatibility. (handler.py is the legacy single-object predecessor of the router+dispatcher pair and is kept for compatibility.)
Multi-turn exchanges are grouped into conversation threads by ThreadManager on top of an in-memory ThreadStore, tracking participants and activity in a ThreadMetadata record and auto-archiving stale threads. The package is deliberately a leaf that neighbors plug into rather than the other way around: postman_adapter.py bridges CXP packets into the Postman message broker's per-recipient priority queues (enqueue/dequeue/peek/acknowledge/reject), session_adapter.py scopes traffic to a session, and the agents, gateway, and kernel packages all speak CXP when they exchange work. Its only outward dependencies are the shared core (tracing/traceability, paths, the Prolog adapter) — which is what makes CXP the stable contract the rest of the pipeline is built around.
Key responsibilities
- Define the canonical
CXPPacketwire format and its self-contained delivery/work state machines. - Serialize packets to JSON (
JSONSerializer) or compact binary (BinarySerializer) behind theISerializerprotocol. - Carry packets over the cxpt direct transport (
servicer,transport,direct_transport,direct_cxp_adapter,proto_codec; it replaced gRPC on 2026-08-07) and WebSocket (ws_client/ws_server), with endpoints resolved from the environment. - Route packets with a governed routing table (
CXPRouter) and enforce governance via the real Prolog engine (PrologBridge). - Dispatch, retry, and record deliveries (
CXPDispatcher,DeliveryResult), tracking delivery and work lifecycle (DeliveryTracker,WorkTracker). - Validate packets against rules and JSON Schema (
CXPValidator,SchemaRegistry,ValidationResult). - Group multi-turn exchanges into conversation threads (
ThreadManager,ThreadStore,ThreadMetadata). - Bridge CXP into the Postman broker and into sessions (
PostmanAdapter,SessionAdapter), and negotiate protocol versions across peers.
Class diagram
The packet and its companions
The heart of the package is CXPPacket — a flat record carrying identity, routing, payload, and two status fields — together with the small result dataclasses it produces and the enums that define its legal states (render-verified):
Routing, dispatch, and governance
CXPRouter decides where a packet goes and whether governance permits it; CXPDispatcher combines routing with delivery, retries, and history. DeliveryTracker and WorkTracker hold the out-of-band lifecycle state, and PrologBridge connects routing to the real Prolog policy engine (render-verified):
Serialization, validation, threads, and the Postman bridge
Packets are encoded by JSONSerializer/BinarySerializer, validated by CXPValidator, grouped into conversations by ThreadManager over ThreadStore, and handed to the Postman broker by PostmanAdapter (render-verified):
Inheritance hierarchy
The exception hierarchy rooted at CXPError, the protocol interfaces, and the status/priority enums (render-verified, generated from the AST):
Module dependency diagram
Internal module imports within orchestrata_ultimate.cxp (render-verified). The public __init__ re-exports the whole surface; dispatcher builds on router, router on prolog_bridge, threads on thread_store, and the packet model (then split into _packet_enums/_packet_results leaf clusters inside this package) has since moved to core.packet:
Module inventory
Thirty-seven modules at commit 8a2cb42ad (the proto subpackage holds the generated cxp_pb2 and its init). Each is on the package page.
| Group | Modules |
|---|---|
| Transport | servicer (transport-neutral service core), transport (server/client construction), direct_transport (async wrapper over cxpt), direct_cxp_adapter (DirectCXPServer, DirectCXPClient), proto_codec (packet to protobuf codec and client config), reply_router (per-consumer reply routing), endpoint_config, ws_client, ws_server, proto/ |
| Wire format | binary_serializer, json_serializer, serializer, schema, headers, payload, types, constants, deterministic_ids, version, version_compat |
| Routing and governance | router, dispatcher, prolog_bridge, validator, priority, handler (legacy), interfaces, exceptions |
| Lifecycle and threads | delivery_status, work_status, threads, thread_store, postman_adapter, session_adapter |
Notes
- Spec reference: Spec 004 (CXP). Packet fields, delivery/work state machines, priority levels, and threading all trace to
@traces(spec="004", ...)markers in the source. handler.pyis the legacy single-object predecessor of theCXPRouter+CXPDispatcherpair, kept for backward compatibility.- Governance is enforced through the real janus-swi Prolog engine via
PrologBridge; with no Prolog backend installed the bridge operates in degraded mode (queries return empty, mutations raisePrologBridgeError). - Transport history: gRPC until 2026-08; the cxpt direct transport since grpcio was retired on 2026-08-07.
- Transport endpoints are resolved from the environment at call time by
endpoint_config.py— no hardcoded host/port; missing config raisesCXPConfigError.
Class map (generated)
Generated from the live source AST by scripts/gen-module-class-diagrams.py — do not hand-edit. Abstract classes have a green border; members listed are those defined on the class itself (inherited members excluded). Solid empty-triangle arrows = in-package inheritance; dashed arrows into dashed boxes = external/stdlib/cross-package bases; filled diamond = composition (constructed in __init__); open diamond = aggregation (annotated/injected reference); diamond edge labels name the owning attribute.