OCP is a JSON format for the record of one agent orchestration run: the units of work, each attempt at them, what each cost in tokens, and whether the result was accepted, with the evidence for it. A producer writes it after the fact, from its own records, logs or telemetry. It is not a runtime protocol: it never starts, schedules or coordinates agents, and nothing goes over a wire. OpenTelemetry spans describe calls as they happen; an OCP document describes the finished run, and can be built from spans. See Introduction.
Five top-level fields: ocp ("0.3"), producer with a name, privacy with a profile, run with an id, and nodes, which may be empty. Each node needs an id and a kind. Edges, attempts, cost and everything 0.3 added are optional. The checker warns (W180) until you declare producer.capabilities. See Quickstart.
Yes. Write what you know and leave the rest out: an absent cost means unknown, not zero. Declare producer.capabilities so a reader can tell an element you cannot record from one that did not happen; a capability declared false must not appear in the document (E180). Give what you inferred an evidence tier.
A node is a unit of work in the run, such as implement or review. An attempt is one try at a node, with one model, one cost record and one outcome; a retry is a new attempt, with a cause that says why. A workflow piece belongs to the configuration, the plan of what runs: vertex links a node or attempt to its piece, round counts repair rounds, and a piece’s width runs parallel copies. See Run graph and Configuration.
Keep the tool’s own label in model.raw, exactly as written, and add a canonical model.id when you know it. Put effort in effort. Do not build a fused label such as fable·xhigh yourself, but keep one the source already wrote. See Model and effort.
Per attempt, with uncached input, cache reads, cache writes and output kept apart. Many tools count cache reads inside input, so subtract them before writing input_tokens. Output includes reasoning tokens; reasoning_tokens is only a breakdown, so add reasoning into output_tokens if your source reports it apart. Say how the counts were attributed: basis: measured for usage records that belong to this attempt, allocated when you split a larger total, such as a day’s usage or a session several attempts shared. If you cannot attribute usage at all, leave cost out. See Cost.
verified: mechanically checked. reported: a report taken at face value. heuristic: inferred by a rule. asserted: a bare claim. Edges and inferred labels use the first three; signals, preferences and task labels can also be asserted, and an outcome without evidence counts as asserted. A producer never raises a tier without new mechanical evidence. An attempt’s done is that attempt’s result, not the run’s: from 0.3, the run’s acceptance rule decides from its signals. See Evidence.
Not automatically. metadata_only forbids prompt, completion and transcript text anywhere in the document, extensions included, but it still holds short labels, paths and repository names, which can be sensitive. The schema caps the designated label fields at 500 characters; it cannot tell a label from pasted text, so the profile is the producer’s promise. Reduce documents before they leave the machine: loopmath’s share --preview prints exactly what would go. See Privacy.
cfg_ plus 12 hex digits of a SHA-256 over the canonical form of the declared workflow and the baseline setting of each piece: harness, model, effort, context policy and options. Every tool that implements the algorithm gets the same id for the same configuration. The id does not cover per-attempt overrides, so check attempt setting fields before pooling runs by id. Configuration id gives the algorithm and a calculator.
The observation: the task, the configuration that ran, signals and the acceptance rule, slates of runs compared on one task and the preferences between them, provenance, rescue and a receipt. All of it is optional. Add it when you want runs to be comparable across configurations. See the changelog.
Yes. A reader accepts 0.1, 0.2 and 0.3, each by the rules of its own version. To upgrade, run loopmath ocp migrate FILE, which writes the 0.3 form and never changes its input. A 0.2 file usually needs only its version changed; a 0.1 file also needs a tier on every edge, which the migration adds. See Versioning.
Install loopmath (pipx install loopmath, Python 3.11 or newer) and run loopmath ocp validate FILE.... It exits 0 when no file has an error, 1 when one does and 2 when a file is missing; --json gives every finding. A pass means the schema and every numbered rule hold. It does not prove the privacy promise, the evidence tiers or every requirement in the field descriptions; see what the checker does not test.
No. Implement the schema and the numbered rules in your own tool. loopmath is the reference implementation of the checker, the migration and the configuration id. A few parts are loopmath’s own and say so: the dev.loopmath. namespace, run.receipt (W196 when another producer writes one) and the log extractor’s cost rule, E171. The loopmath project maintains OCP under the MIT license, and changes go through public proposals. See Governance.
Put it in ext on the entity it describes, under a reverse-domain namespace you control, such as com.example.queue_wait_ms. Readers ignore namespaces they do not know. When several tools write the same kind of data, propose it as a field. See Extensions.

Privacy