Technology · Protocol

JSON Schema

Every work-order contract, tool definition and generated function surface in my estate is a JSON Schema, and schemas compile into dispatch at build time.

AgentOS · Agent Swarm · FAFO CoreContracts at every handoff
AgentOSevery handoff
API platformfields from real calls
Agent Swarmfirst step of every call
Valid
Malformed
  • 33schema contracts governing AgentOS handoffs
  • 12semantic rules checking each API reference
  • ≈2,000lines of Rust in the harness validator

Contracts at every handoff

Long agent runs drift when the handoffs between agents are prose, because each agent reinterprets what the last one meant. In AgentOS I made every handoff a contract and chose JSON Schema as the contract language. The *.schema.json contracts cover work-order sources, authoring plans, work packages and the structured output of model checkers.

Every seam is checked on both sides, so a malformed artefact cannot pass through a component that trusts its upstream. The PostgreSQL work graph and its schemas are the truth; Markdown views are generated from them, and edits to those views are discarded.

Valid artefact
Malformed at build
the producer names the schema that failed
Changed in transit
the consumer refuses, naming the schema
producer checkthe seamconsumer check

Diagnostics that name the fix

Work-order authoring starts from an operator-only source document. When it fails validation, the diagnostic names the exact field and the fix, such as a missing deliverable class or a team larger than the ceiling of twelve, which keeps authoring from turning into trial and error.

The schema for a model checker's verdict is flat and closed and matches the vendors' structured-output modes, so a verdict comes back as data. Nested and open schemas are where model output drifts. On the Rust side, contracts are checked with the jsonschema crate and hashed in canonical form. Why the handoffs had to become contracts is the subject of Why long agent runs fail.

Open and nested
verdict
field
nested object
nested object
field
extra property, allowed
Flat and closed
verdict
field
field
field
additionalProperties: false
Field names are illustrative.

Fields only from real calls

Connecting an API for agents usually starts with someone reading documentation and guessing which fields are real. In the sibling platform for third-party APIs in FAFO Core and Function Forge, I decided a field counts only once a real call has returned it. A two-pass normaliser does the work, starting from an OpenAPI 3.x document or a hand-written seed.

Pass one · every field the document claimsPass two · only fields a successful real call returned
returned by a real call
documented, never seen
Illustrative counts. Tools appear only once the validation harness passes.

A semantic validator checks the canonical API reference, and the platform exposes no tools for an API until its validation harness passes, so the schema describes the API as it behaves. That platform's build is the story in Closed by evidence.

Validation in the harness

If every tool validates its own input, a fleet with hundreds of tools ends up with hundreds of slightly different validators. In Agent Swarm I put validation in the harness, as the first step of the frozen pipeline every tool call passes through. The validator applies draft-07 validation and the OpenAI strict-mode rules, plus structural pre-checks such as the depth of a peer-call chain, before parameters are normalised and authorised.

One tool call
first, for every tool
the only part a new tool writes
Proportions are illustrative.

See Tools are the platform. I use schemas to take ambiguity out of systems where many agents hand work to one another. The validators are the standard Rust and Python libraries; the contracts, the seam discipline and the evidence rule for API fields are mine.

I put the checks where a bad artefact would otherwise pass unnoticed.