Protocol Implementor Guide
The protocol is only real if another implementation can prove it. This page is for runner authors, adapter authors, and compatibility-layer maintainers who want to implement AgentXchain and verify that claim against the repo's published fixture corpus.
If you want the constitutional model, start with Protocol v7. If you want the current normative boundary, read Protocol Reference v7. If you want the executable adoption contract, start here.
What protocol conformance means
AgentXchain ships a repo-native conformance corpus under .agentxchain-conformance/fixtures/. The verifier runs those fixtures against your implementation through a thin adapter boundary. You are not proving that your CLI looks like the reference CLI. You are proving that your implementation behaves the same way at the protocol surface.
The current corpus is split into three tiers:
| Tier | Focus | Current surfaces | Current fixture count |
|---|---|---|---|
1 | Core constitutional behavior | state_machine, turn_result_validation, gate_semantics, decision_ledger, history, config_schema, delegation, decision_carryover, parallel_turns, event_lifecycle | 77 |
2 | Trust-hardening behavior | dispatch_manifest, hook_audit | 23 |
3 | Multi-repo coordination | coordinator | 8 |
The verifier selects every fixture up to the requested tier. --tier 2 runs Tier 1 plus Tier 2. --tier 3 runs the entire corpus.
What You Do Not Need For v7 Conformance
Do not let the reference CLI's product surface blur the protocol boundary.
A non-reference runner can still claim protocol v7 without implementing these reference-runner workflow surfaces:
- mission hierarchy and mission plans under
.agentxchain/missions/ - dashboard APIs, ports, view names, and browser UX
- export, report, and release operator surfaces
Those surfaces matter for the reference runner, but they are not part of the current fixture-backed protocol-v7 requirement set.
A future protocol-v8 cut needs promoted conformance or a new normative artifact/state contract. Shipping more reference-runner workflow features is not enough by itself.
Required repo contract
Your implementation target can expose either a repo-local conformance directory or a remote HTTP conformance endpoint.
Local mode:
.agentxchain-conformance/
capabilities.json
your-adapter.js
capabilities.json tells the verifier what implementation it is testing and how to invoke your adapter.
Remote mode:
GET /conform/capabilitiesPOST /conform/executeadapter.protocol: "http-fixture-v1"
The verifier still owns the canonical local fixture corpus in remote mode. The remote endpoint receives one full fixture JSON document per POST and returns the same {status, message, actual} payload that a local stdio adapter would have emitted. For the full HTTP request/response contract, see Remote Protocol Verification.
Writing capabilities.json
This is the reference CLI's current file:
{
"implementation": "agentxchain-cli",
"version": "2.155.72",
"protocol_version": "v7",
"adapter": {
"protocol": "stdio-fixture-v1",
"command": ["node", ".agentxchain-conformance/reference-adapter.js"]
},
"tiers": [1, 2, 3],
"surfaces": {
"state_machine": true,
"turn_result_validation": true,
"gate_semantics": true,
"decision_ledger": true,
"history": true,
"config_schema": true,
"dispatch_manifest": true,
"hook_audit": true,
"coordinator": true,
"delegation": true,
"decision_carryover": true,
"parallel_turns": true,
"event_lifecycle": true
},
"metadata": {
"name": "AgentXchain Reference CLI",
"url": "https://github.com/shivamtiwari93/agentXchain.dev"
}
}
Because this example is the shipped reference CLI file, the surfaces map above must stay exhaustive for the surfaces the implementation actually claims. Leaving out a shipped surface is not harmless sample drift; it tells operators the implementation does not explicitly claim that surface.
Fields that matter today:
| Field | Required | Notes |
|---|---|---|
implementation | Yes | Non-empty string used in the report |
protocol_version | No | Informational but useful for humans and release evidence |
adapter.protocol | Yes | Must be exactly stdio-fixture-v1 |
adapter.command | Yes | Non-empty command array passed to spawnSync() |
tiers | Yes | Non-empty array containing only 1, 2, or 3 |
For remote HTTP verification, the capabilities document is fetched from GET /conform/capabilities and adapter.protocol must instead be http-fixture-v1. In that mode there is no adapter.command; the verifier posts fixtures to POST /conform/execute.
Fields that affect verifier behavior when present:
| Field | Role |
|---|---|
surfaces | When present, the verifier enforces surface claims: --surface X will fail fast if surfaces.X is not declared. When absent, surface filtering works without enforcement for backward compatibility. |
Fields that are informative only:
| Field | Role |
|---|---|
version | Human-readable implementation version |
metadata | Display metadata only |
Surface enforcement rule: If your capabilities.json includes a surfaces map, any --surface request for an undeclared surface exits with code 2 and a clear error naming the unclaimed surface plus listing claimed ones. If you omit the surfaces map entirely, surface filtering still works but without claim enforcement — this preserves backward compatibility for implementations that predate surface declarations.
Writing a stdio-fixture-v1 adapter
The adapter contract is intentionally narrow:
- Read one fixture JSON object from stdin.
- Materialize the fixture setup in your implementation's test workspace.
- Execute the fixture's
input.operationagainst your implementation. - Compare the result against
expected. - Emit exactly one JSON result on stdout.
- Exit with the status code that matches the JSON result.
Adapter result shape:
{
"status": "pass",
"message": "optional human-readable note",
"actual": null
}
Valid adapter statuses:
| Adapter status | Meaning | Required process exit code |
|---|---|---|
pass | Fixture behavior matched expectation | 0 |
fail | Fixture executed but the behavior was wrong | 1 |
error | Adapter or implementation could not evaluate the fixture correctly | 2 |
not_implemented | Fixture surface is intentionally unsupported for now | 3 |
Minimal adapter skeleton:
#!/usr/bin/env node
import { stdin, stdout, stderr, exit } from 'node:process';
let input = '';
stdin.setEncoding('utf8');
stdin.on('data', (chunk) => {
input += chunk;
});
stdin.on('end', async () => {
try {
const fixture = JSON.parse(input);
const result = await runFixtureAgainstYourImplementation(fixture);
stdout.write(`${JSON.stringify(result)}\n`);
const code =
result.status === 'pass' ? 0 :
result.status === 'fail' ? 1 :
result.status === 'not_implemented' ? 3 :
2;
exit(code);
} catch (error) {
stderr.write(`${error.message}\n`);
stdout.write(`${JSON.stringify({
status: 'error',
message: error.message,
actual: null,
})}\n`);
exit(2);
}
});
Progressive conformance
not_implemented exists so third-party implementations can adopt the protocol incrementally without faking success or collapsing into generic adapter errors. That status is valid adapter output.
Be precise about the semantics:
not_implementedis counted separately from pass, fail, and error.- A tier can still be reported as overall
passwhen every selected fixture is eitherpassornot_implemented. not_implementedis not a loophole for broken behavior. If the surface exists and behaves incorrectly, returnfail.
Running protocol conformance
Typical usage:
# Run Tier 1 against the current directory
agentxchain conformance check --tier 1 --target .
# Run up to Tier 2 and isolate one surface
agentxchain conformance check --tier 2 --surface dispatch_manifest --target .
# Emit JSON for CI or a reporting pipeline
agentxchain conformance check --tier 3 --target . --format json
# Verify a remote implementation over HTTP
agentxchain conformance check --tier 1 --remote https://example.com/agentxchain --format json
agentxchain verify protocol remains supported as a compatibility alias over the same verifier.
Command options:
| Flag | Meaning |
|---|---|
| `--tier <1 | 2 |
--surface <name> | Restrict execution to one surface |
--target <path> | Root containing .agentxchain-conformance/capabilities.json |
--remote <url> | Remote HTTP conformance endpoint base URL |
--token <token> | Bearer token for remote verification |
--timeout <ms> | Per-fixture remote HTTP timeout in milliseconds |
| `--format <text | json>` |
Do not confuse verifier exit codes with adapter exit codes
The adapter speaks per-fixture status. The verifier speaks overall run status.
| Surface | Exit codes |
|---|---|
| Adapter process | 0=pass, 1=fail, 2=error, 3=not_implemented |
agentxchain verify protocol | 0=overall pass, 1=one or more fixture failures, 2=verifier or adapter error |
The verifier never exits 3. not_implemented is adapter-level truth that gets folded into the final report.
Report interpretation
The JSON report includes:
implementationprotocol_versiontier_requestedtarget_rootresults.tier_Noverall
Each tier summary tracks:
fixtures_runfixtures_passedfixtures_failedfixtures_erroredfixtures_not_implementedsurfacesfailures[]errors[]not_implemented[]
That shape lets you distinguish "we have not built this yet" from "we built it and got it wrong." If your CI collapses those cases together, your adoption signal is garbage.
Fixture anatomy
Every fixture is a single JSON file under .agentxchain-conformance/fixtures/<tier>/<surface>/.
Real Tier 1 example:
{
"fixture_id": "SM-001",
"tier": 1,
"surface": "state_machine",
"description": "Completed state rejects assignment",
"type": "reject",
"setup": {
"state": {
"status": "completed",
"phase": "qa",
"run_id": "run_001",
"active_turns": {},
"pending_phase_transition": null,
"pending_run_completion": null,
"blocked_on": null
},
"config": {
"roles": {
"dev": {
"runtime": "manual"
}
}
}
},
"input": {
"operation": "assign_turn",
"args": {
"role_id": "dev"
}
},
"expected": {
"result": "error",
"error_type": "invalid_state_transition",
"state_unchanged": true
}
}
The important fields are:
| Field | Meaning |
|---|---|
fixture_id | Stable identifier used in reports and CI failures |
tier | Which conformance tier the fixture belongs to |
surface | Protocol subsystem under test |
description | Human-readable contract summary |
type | Fixture intent such as validate, reject, or transition |
setup | Files, state, config, dispatch bundles, or coordinator state to materialize |
input | Abstract operation plus arguments your adapter must map onto your implementation |
expected | Minimal assertion object the adapter must satisfy |
The input.operation verbs are fixture abstractions, not CLI command names. Your adapter is responsible for mapping those verbs onto your implementation.
Surface reference
state_machine
Core run lifecycle rules. Tier 1 currently proves:
- initialization moves
idletoactiveonly with valid governed config - human gates move
activetopaused, and approvals resume toactiveor finish tocompleted - escalations move
activetoblocked, and explicit resolution movesblockedback toactive - terminal
completedruns reject new assignment and approval attempts - illegal transitions such as
idle -> pausedare rejected run_idis immutable after initialization
If your state machine is loose here, every higher surface becomes untrustworthy.
turn_result_validation
Validation pipeline for staged turn results. Tier 1 currently proves:
- required fields such as
summaryare enforced at schema validation time - staged results must match the assigned
run_idandturn_id - reserved paths in
files_changedare rejected before acceptance review_onlyturns must include at least one objection- decision IDs must match the
DEC-NNNcontract phase_transitionandrun_completioncannot both be requested in one staged resultneeds_humanstatus is valid when accompanied by the required reason
These checks exist to reject malformed or incomplete artifacts before they enter history.
gate_semantics
Human approval boundaries for phase transitions and run completion. This surface proves both structural gate predicates and workflow-file semantic evaluators. The conformance corpus currently covers:
.planning/PM_SIGNOFF.mdmust containApproved: YESbefore planning can exit.planning/ship-verdict.mdmust contain an affirmative## Verdict:before run completion.planning/SYSTEM_SPEC.mdmust define required contract sections (e.g.## Acceptance Tests) before planning can exit.planning/IMPLEMENTATION_NOTES.mdmust replace scaffold placeholders with real content before implementation can exit.planning/acceptance-matrix.mdmust contain a real passing requirement table before run completion.planning/RELEASE_NOTES.mdmust replace scaffold placeholders with real QA content before run completion
These are not documentation preferences. They are runtime-enforced semantic checks: the gate evaluator reads the file content, parses it, and rejects phase advancement or run completion when the content is structurally insufficient. This is where AgentXchain stops pretending a model can unilaterally ship.
decision_ledger
Append-only constitutional record for decisions, objections, approvals, and rejections. Tier 1 currently proves:
- well-formed decision entries include the required fields
- empty decision statements are rejected
- invalid categories are rejected
- duplicate decision IDs within one run are rejected
If this surface is wrong, your audit trail is fiction.
history
Accepted turn-result history and its integrity constraints. Tier 1 currently proves:
- accepting a turn appends exactly one history entry atomically with the state update
- re-accepting the same turn is idempotent and does not duplicate history
- accepting a non-active turn fails before history can change
This surface proves what actually happened across the run, not what a status screen claims happened.
config_schema
Validation of governed config shape, roles, runtimes, and baseline project contract. Tier 1 currently proves:
- a minimal governed config is accepted
entry_rolemust refer to a declared role- roles cannot reference undeclared runtimes
- routing cannot reference undeclared gates
- invalid
schema_versionvalues are rejected
Broken config validation pushes protocol drift downstream where it is harder to debug.
delegation
Hierarchical authority delegation from one role to another. Tier 1 currently proves:
- a valid delegation with all required fields (
to_role,charter,scope) passes validation - delegation with missing
charteris rejected - delegation with an invalid
to_rolepattern is rejected - self-delegation (delegating to your own role) is rejected
- more than 5 delegations in a single turn result are rejected
- delegation cannot coexist with a
run_completion_requestin the same turn result - delegation with
required_decision_idspasses validation when the IDs are well-formed - delegation with duplicate
required_decision_idsis rejected
Delegation is not a convenience feature. It is how governed authority flows through a role hierarchy without collapsing the audit trail.
decision_carryover
Cross-run decision durability and override semantics. Tier 1 currently proves:
- a decision with
durability: "repo"passes turn result validation and promotes into repo-level continuity - a decision with an invalid
durabilityvalue (not"run"or"repo") is rejected - a decision with a valid
overridesfield pointing at an existing repo decision passes validation - a decision with
overridespointing at itself (self-override) is rejected - a decision with default
durability(omitted, meaning"run") passes validation
If your implementation does not enforce durability scoping and override validity, continuation runs will inherit stale or contradictory decisions.
parallel_turns
Concurrent turn dispatch configuration. Tier 1 currently proves:
- config with
max_concurrent_turns: 2passes validation - config with
max_concurrent_turns: 4passes validation (maximum allowed) - config with
max_concurrent_turns: 1passes validation (sequential mode, the default) - config with
max_concurrent_turns: 0fails validation (must be >= 1) - config with
max_concurrent_turns: 5fails validation (maximum is 4) - config with a non-integer
max_concurrent_turnsfails validation
The range is intentionally narrow. Unbounded parallelism in governed delivery is not a scaling feature; it is a governance collapse risk.
event_lifecycle
Structural and ordering validation for run lifecycle events in .agentxchain/events.jsonl. Tier 1 currently proves:
- a valid run event with all required fields (
event_type,timestamp,run_id) passes validation - an event with an invalid
event_typeis rejected - a valid event sequence with
run_startedfirst andrun_completedlast passes ordering validation turn_acceptedwithout a precedingturn_dispatchedfor the same turn fails ordering validationrun_completednot being the last event fails ordering validation- backwards timestamps (timestamp regression) fail ordering validation
- a
turn_dispatchedevent missingturn.turn_idfails event validation - a timeline not starting with
run_startedfails ordering validation
This surface proves that your event log is a trustworthy timeline, not just an append-only dump. Ordering and completeness constraints make the event log useful for recovery, audit, and dashboard rendering.
dispatch_manifest
Dispatch-bundle finalization and integrity verification. This is the hardening layer that proves agents received the expected assignment files and that post-finalization tampering is detectable. Tier 2 currently proves:
- a finalized manifest with valid SHA-256 digests verifies successfully
- an unexpected file injected after finalization fails verification
- content tampering that changes a file's digest fails verification
- a deleted file after finalization fails verification
MANIFEST.jsonis excluded from its own file entries- a size mismatch after content replacement with different-length data fails verification
- multiple simultaneous integrity violations produce accumulated errors, not just the first
- a missing manifest after deletion fails with a
missing_manifesterror - malformed
MANIFEST.json(invalid JSON) fails withinvalid_manifest - a manifest missing required fields fails with
invalid_manifest
These are not smoke tests. They prove that the dispatch bundle is a tamper-evident envelope, not just a file list.
hook_audit
Execution and audit recording for lifecycle hooks. The important contract is not just "hooks run" but "their effects are observable and attributable." Tier 2 currently proves:
- a process hook audit entry contains all required fields (
hook_id,orchestrator_action,verdict,exit_code,duration_ms) - an HTTP hook records
transport: "http"even on connection failure - an advisory hook returning
verdict: "block"is downgraded to a warning (downgraded_block_to_warn) - a blocking hook process failure records
blocked_failureand halts the phase - protected-file tamper detection records
aborted_tamperand halts the phase withhook_ok: false, blocked: false - a blocking hook explicit block verdict records
blockedand stops the phase - a blocking hook short-circuits later hooks; remaining entries are recorded as
skipped - a blocking hook with invalid JSON output records
blocked_invalid_outputand halts the phase - an advisory hook with invalid JSON output records
warned_invalid_outputwithout blocking - a blocking hook timeout records
blocked_timeoutand halts the phase - an advisory hook timeout records
warned_timeoutwithout blocking - an advisory hook process failure records
warned_failurewithout blocking - an advisory hook
verdict: "warn"recordswarnedwithout blocking
Your adapter's run_hooks operation must return this shape:
{
"result": "success",
"hook_ok": boolean,
"blocked": boolean,
"audit_entry": { ... } | null,
"audit_entries": [ ... ]
}
hook_ok means "can the governed pipeline proceed past this hook phase?" — not "did the hook succeed." Advisory hooks that fail, time out, or produce garbage still return hook_ok: true because advisory failures degrade to warnings without halting the pipeline. hook_ok: false means a blocking condition was encountered: either a blocking hook blocked or a protected file was tampered with.
blocked is true only when a blocking hook returned a block verdict (explicit, fail-closed, timeout, or invalid output). Tamper detection sets hook_ok: false but blocked: false — it is a different halt mechanism.
audit_entries is the ordered list of all hook execution results. Each entry includes orchestrator_action, the precise 13-value enum describing what happened:
orchestrator_action | hook_ok | blocked | Meaning |
|---|---|---|---|
continued | true | false | Hook returned verdict: "allow" |
warned | true | false | Hook returned verdict: "warn" |
downgraded_block_to_warn | true | false | Advisory hook returned block, downgraded to warn |
warned_failure | true | false | Advisory hook exited non-zero |
warned_timeout | true | false | Advisory hook exceeded timeout_ms |
warned_invalid_output | true | false | Advisory hook produced unparseable stdout |
blocked | false | true | Blocking hook returned verdict: "block" |
blocked_failure | false | true | Blocking hook exited non-zero (fail-closed) |
blocked_timeout | false | true | Blocking hook exceeded timeout_ms (fail-closed) |
blocked_invalid_output | false | true | Blocking hook produced unparseable stdout (fail-closed) |
aborted_tamper | false | false | Hook modified a SHA-256 protected file |
skipped | N/A | N/A | Prior blocking hook blocked; remaining hooks were not executed |
skipped entries appear in audit_entries (not as the primary audit_entry) with verdict: null, exit_code: null, duration_ms: 0, and no transport field.
The disambiguation signal for operators and dashboards is orchestrator_action, not hook_ok. Use hook_ok for flow control (proceed or halt). Use orchestrator_action for precise diagnosis.
coordinator
Multi-repo coordination: coordinator config validation, acceptance projection, workstream state, and barrier semantics. Tier 3 starts here because cross-repo governance is where weak protocol claims usually collapse. Tier 3 currently proves:
- a valid coordinator config with repos and workstreams validates successfully
- cyclic workstream dependencies are rejected at config validation time
- the first repo acceptance transitions a barrier from
pendingtopartially_satisfied - all required repos accepting transitions a barrier from
partially_satisfiedtosatisfied - cross-repo write isolation is enforced: file write violations are rejected during acceptance projection
ordered_repo_sequencestays unsatisfied when a downstream repo accepts before the entry reposhared_human_gateremainspendingeven after every required repo has accepted — it requires explicit human approvalinterface_alignmentrequires each repo to have accepted its declaredDEC-NNNdecision IDs (viadecision_ids_by_repo) before the barrier is satisfiednamed_decisionsrequires each repo to have accepted its declaredDEC-NNNdecision IDs (vianamed_decisions.decision_ids_by_repo) before the barrier is satisfied
interface_alignment and named_decisions are not heuristic placeholders. The coordinator resolves them by checking accepted decision ledger entries per repo against declared requirements.
Fixture setup helpers you need to support
Depending on the surface, fixtures may ask your adapter to materialize:
- Common repo-local setup:
setup.config,setup.state,setup.turn_result,setup.history,setup.ledger,setup.filesystem - Dispatch-manifest setup:
setup.dispatch_bundle,setup.post_finalize_inject,setup.post_finalize_tamper,setup.post_finalize_delete,setup.post_finalize_corrupt_manifest,setup.post_finalize_delete_manifest - Coordinator setup:
setup.coordinator_config,setup.repos,setup.coordinator_state,setup.barriers,setup.coordinator_history
Those keys are part of the adapter contract, not implementation detail. If your adapter silently ignores one, you are not "partially compatible" with that fixture; you are evaluating the wrong setup state.
The authoritative helper list lives in .agentxchain-conformance/fixtures/README.md. Do not fork the contract in your own docs and hope it stays aligned.
Recommended adoption sequence
- Implement Tier 1 first and return
not_implementedfor higher tiers. - Add Tier 2 once your dispatch-manifest and hook-audit surfaces are real, not mocked.
- Add Tier 3 only when your coordinator model is actually multi-repo and barrier-aware.
- Run
agentxchain verify protocol --format jsonin CI and publish the report with your release evidence.
Protocol claims without conformance evidence are marketing. AgentXchain only becomes an open protocol if independent implementations can fail publicly and fix themselves against the same corpus.