CxRP is a contract-only protocol for defining and executing structured work — describing AI/workflow request lifecycles across planning, lane selection, execution requests, and execution results.
CxRP defines the shared language exchanged between:
- OperatorConsole (entrypoint)
- SwitchBoard (lane selection boundary)
- OperationsCenter (planning boundary, execution boundary, policy enforcement, and adapter dispatch)
CxRP defines what systems say to each other, not how they run.
- Versioned contract models.
- Canonical vocabulary enums.
- JSON Schemas for validation.
- Example payloads for interoperable integration.
CxRP excludes implementation logic, including:
- execution logic
- routing logic
- scheduling/watchers
- subprocess execution
- model/provider integrations
- adapters
- queue systems
- transport machinery (gRPC, FastAPI, Temporal, etc.)
Install via pip from the repo root:
pip install -e .Use the contract models in your own code:
from cxrp.contracts import TaskProposal, LaneDecision, ExecutionRequest, ExecutionResultJSON Schemas live under cxrp/schemas/ for non-Python consumers.
CxRP is a contract layer — four versioned Pydantic models plus their canonical vocabulary enums and JSON Schemas. The Repository Layout section below maps which directory holds each surface (cxrp/contracts/, cxrp/schemas/, cxrp/examples/). Consumers (OperatorConsole, SwitchBoard, OperationsCenter) import the models verbatim and never mutate them — version bumps follow the Contract Evolution Policy later in this file.
Current revision: v0.2 (active). Frozen prior revision: v0.1 (retained on disk for historical interop).
TaskProposal— expresses requested work intent.LaneDecision— records chosen lane/executor/backend by SwitchBoard.ExecutionRequest— defines bounded work unit for execution; carries lane-specificinput_payloadvalidated against a named payload schema.ExecutionResult— reports normalized outcome (ok,status, optionalartifacts, optionaldiagnostics).
lane is an abstract category (coding_agent, review_agent, ...). executor (e.g. claude_cli) and backend (e.g. kodo) are open strings at the envelope level — consuming systems layer their own typed constraints internally.
cxrp/contracts/: Python contract models.cxrp/vocabulary/: canonical enums (status,lane,artifact).cxrp/validation/: schema loading and validation helper.cxrp/schemas/v0.2/: JSON Schemas for the four canonical contracts (shipped inside the installable package).task_proposal.schema.jsonlane_decision.schema.jsonexecution_request.schema.jsonexecution_result.schema.jsonpayloads/: per-lane payload schemas (e.g.coding_agent_input.schema.json).
cxrp/schemas/v0.1/: frozen prior revision, retained for historical interop.examples/v0.2/: minimal interoperable examples.docs/spec/v0.2.md: versioned normative summary.
- OperatorConsole emits or captures
TaskProposalandExecutionResult-shaped data viaoperator_console.cxrp_capture. - SwitchBoard consumes
TaskProposaland emitsLaneDecisiononly; the wire shape is produced byswitchboard.adapters.cxrp_mapper. - OperationsCenter consumes
TaskProposal+LaneDecision, buildsExecutionRequest, and consumesExecutionResult. OC has its own internal Pydantic subtype with stricter narrowing —operations_center.contracts.cxrp_mappertranslates between OC's subtype and the CxRP envelope at the boundary.
CxRP defines the envelope: identities, abstract lane: LaneType category, open-string executor/backend, free-form input_payload keyed by a lane-specific payload schema. Consumer repos (notably OC) layer their own typed Literal/Pydantic constraints internally without changing the wire contract. Cross-repo communication uses CxRP shape; intra-repo code is free to use richer types as long as it maps to/from CxRP at the wire.
All contracts include schema_version = "0.2" and contract_kind as canonical discriminators. v0.1 is frozen; breaking changes land under a new cxrp/schemas/vX.Y/.
Contract kinds and schema filenames are stable across versions:
task_proposal lane_decision execution_request execution_result
CxRP contracts evolve under the following rules:
- Additive fields are non-breaking. Adding a new optional field within a schema version (e.g.
0.2 → 0.2.1) does not require aschema_versionbump. - Renames and removals require a
schema_versionbump. They land under a newcxrp/schemas/vX.Y/directory; the previous version is frozen on disk for historical interop. - Capability removals require a deprecation cycle. A capability removed from
CapabilitySetmust first be marked deprecated for one release/version window, then removed in the next. - Producers may add fields only when the schema permits them. Top-level contracts use
additionalProperties: falseand reject unknown fields; the designated extension slot isevidence.extensions(opendict[str, Any]). - Consumers must reject unknown fields unless the schema explicitly allows extension. This keeps drift detectable rather than silent.
evidence.extensions is the single sanctioned escape valve for backend-specific evidence that does not fit the normalized fields. Anything else outside the schema is a contract violation.
Apache License 2.0 (Apache-2.0) — see LICENSE.