This is the full developer documentation for Syderial # What the record is > Governed continuity for people and agents: where each claim came from, on whose authority, and what the record does not know. Syderial is the system of record for intelligence. For every person and agent that uses it, Syderial does four jobs. 1. **It decides what a model is given.** A model receives only what the person or agent is cleared to see, cited and signed. We call that the context of record. 2. **It limits what an agent can do to what that ground supports.** An action the record doesn’t support doesn’t run, or waits for a person. 3. **It records what the agent knew, was allowed to see and did,** with a signed receipt for each call. 4. **It admits what it doesn’t know.** When the record has nothing on a question, the door says so. The record doesn’t claim to know what is true. It shows what is in it, where each part came from and on whose authority. Memory tools recall. Syderial keeps the record. ## What you get as a developer [Section titled “What you get as a developer”](#what-you-get-as-a-developer) * **The request formats you already use.** Syderial doors accept OpenAI chat completions, Anthropic messages and OpenAI responses requests and return the matching responses. Your client changes its base URL and its credential. See the [Quickstart](/quickstart/). * **Answers from the record.** Before a call reaches a model, Syderial compiles the context of record the caller is cleared to see and grounds the call in it. The answer comes back with the evidence it rests on. * **Separation you don’t write yourself.** Every line in the record has a label, and every request has a clearance. A line reaches a reader only when the clearance dominates the label on every axis, so your application code filters nothing. See [Labels and information flow](/concepts/labels/). * **A receipt for every call.** Syderial signs a receipt for each answer, each abstention and each tool decision, and a reviewer can replay them. See [Receipts and verification](/concepts/receipts/). * **Tools under the same rule.** A tool or MCP call is proposed, checked against authority and recorded under the same labels as a read. See the [MCP door](/api/mcp/). Available to design partners as it ships. ## The record in one paragraph [Section titled “The record in one paragraph”](#the-record-in-one-paragraph) The record is a **journal** of signed entries. Each entry is posted once and chained to the entry before it. An entry contains **lines**, and each line cites its **evidence**, either a quote from a retained source or a pointer to an entry already posted. A correction is a new entry that cites the entry it corrects. Every entry keeps **two clocks**: when a claim applied according to its source, and when the record learned it. The chain of entries is the ledger, and Syderial rebuilds every graph and index from it. ## How a call moves through Syderial [Section titled “How a call moves through Syderial”](#how-a-call-moves-through-syderial) Every write and every read passes through six stations. 1. 01CaptureEvery turn, with its author. 2. 02BoundLabels on every line, the lattice on every read. 3. 03EntailEvidence must support the claim. 4. 04CompileA hashed packet of cleared context. 5. 05GatePolicy before any tool call runs. 6. 06ReceiptSigned, hash-chained, replayable. **Figure 1.** The six stations. Every write and every read passes through them in order. 1. **Capture** keeps every turn with its author. 2. **Bound** labels every line when it’s written and checks the reader’s clearance on every read. 3. **Entail** commits a line to the record only when its cited evidence supports it. 4. **Compile** builds the context of record for a call as a hashed packet, drawn only from lines the reader is cleared to see. 5. **Gate** checks policy before any tool call runs. 6. **Receipt** signs and chains what happened so a reviewer can replay it. The [six stations](/concepts/stations/) page covers each one. ## Where Syderial fits [Section titled “Where Syderial fits”](#where-syderial-fits) Syderial doesn’t chat. The applications and agents that chat call it. Vector stores, retrieval libraries, orchestration frameworks and observability tools can all run on top of a record, and Syderial is the record they read from. A model can’t reason over what it isn’t given. With Syderial, an agent can’t act beyond it. ## Where to go next [Section titled “Where to go next”](#where-to-go-next) * New here: read [The journal](/concepts/journal/), then run the [Quickstart](/quickstart/). * Wiring an agent: see [Coding harnesses](/guides/coding-harnesses/) and the [MCP door](/api/mcp/). * Evaluating the design: read the [research](/research/). Access Syderial issues door addresses and credentials to design partners. [Request a briefing](https://syderial.ai/early-access) to apply. # Quickstart > Send a call through a Syderial door with the OpenAI or Anthropic SDK you already use. You change the base URL and add your credential. A Syderial door accepts the same requests as the API your client was written for. This guide sends one call through the chat completions door, then repeats it through the messages and responses doors. Before you start Syderial issues each design partner a **door address** and a **credential**. If you don’t have them yet, [request a briefing](https://syderial.ai/early-access). The examples use placeholders for both. 1. **Save your credential.** Your credential arrives as request headers, one `Name: value` pair per line. Save them to a file named `syderial-headers.txt` and keep that file out of source control. syderial-headers.txt ```text
:
: ``` The door identifies you from these headers, never from the request body. Your organization and identity come from the credential, so a request can’t claim to be someone else. 2. **Set your door address.** ```sh export SYDERIAL_DOOR_URL="https://YOUR-DOOR-ADDRESS" ``` 3. **Install the SDK you already use.** * Python ```sh pip install openai anthropic ``` * TypeScript ```sh npm install openai @anthropic-ai/sdk ``` * curl curl 7.55 or later reads headers from a file with `-H @file`. Nothing to install. 4. **Load the credential in your client.** Both SDKs accept extra headers on every request. A small helper reads the file from step 1. * Python syderial\_headers.py ```python from pathlib import Path def load_headers(path="syderial-headers.txt"): """Read the issued credential headers, one 'Name: value' per line.""" headers = {} for line in Path(path).read_text().splitlines(): if ":" in line: name, value = line.split(":", 1) headers[name.strip()] = value.strip() return headers ``` * TypeScript syderial-headers.ts ```ts import { readFileSync } from "node:fs"; // Read the issued credential headers, one "Name: value" per line. export function loadHeaders(path = "syderial-headers.txt"): Record { const headers: Record = {}; for (const line of readFileSync(path, "utf8").split("\n")) { const i = line.indexOf(":"); if (i > 0) headers[line.slice(0, i).trim()] = line.slice(i + 1).trim(); } return headers; } ``` * curl curl reads the file directly with `-H @syderial-headers.txt`. 5. **Find a model alias.** The `model` field takes an alias configured for your organization. List them with the standard models call. * Python ```python import os from openai import OpenAI from syderial_headers import load_headers client = OpenAI( base_url=os.environ["SYDERIAL_DOOR_URL"] + "/v1", api_key="unused", # the door reads the credential headers, not this field default_headers=load_headers(), ) for model in client.models.list(): print(model.id) ``` * TypeScript ```ts import OpenAI from "openai"; import { loadHeaders } from "./syderial-headers"; const client = new OpenAI({ baseURL: `${process.env.SYDERIAL_DOOR_URL}/v1`, apiKey: "unused", // the door reads the credential headers, not this field defaultHeaders: loadHeaders(), }); for await (const model of client.models.list()) { console.log(model.id); } ``` * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/models" \ -H @syderial-headers.txt ``` Set the alias you want to use: ```sh export SYDERIAL_MODEL="" ``` 6. **Send a call.** * Python call.py ```python import os from openai import OpenAI from syderial_headers import load_headers client = OpenAI( base_url=os.environ["SYDERIAL_DOOR_URL"] + "/v1", api_key="unused", default_headers=load_headers(), ) completion = client.chat.completions.create( model=os.environ["SYDERIAL_MODEL"], messages=[ {"role": "user", "content": "When did V-204 fail, and how do we know?"}, ], ) print(completion.choices[0].message.content) ``` * TypeScript call.ts ```ts import OpenAI from "openai"; import { loadHeaders } from "./syderial-headers"; const client = new OpenAI({ baseURL: `${process.env.SYDERIAL_DOOR_URL}/v1`, apiKey: "unused", defaultHeaders: loadHeaders(), }); const completion = await client.chat.completions.create({ model: process.env.SYDERIAL_MODEL!, messages: [ { role: "user", content: "When did V-204 fail, and how do we know?" }, ], }); console.log(completion.choices[0].message.content); ``` * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/chat/completions" \ -H @syderial-headers.txt \ -H "content-type: application/json" \ -d '{ "model": "'"$SYDERIAL_MODEL"'", "messages": [ {"role": "user", "content": "When did V-204 fail, and how do we know?"} ] }' ``` Syderial answers from the entries you’re cleared to see. If the record has nothing on the question, the door says so. If the answer is behind a boundary you aren’t cleared for, you get a refusal that names no one and reveals nothing about the withheld entries. ## The same call through the other doors [Section titled “The same call through the other doors”](#the-same-call-through-the-other-doors) ### Anthropic messages [Section titled “Anthropic messages”](#anthropic-messages) The Anthropic SDK adds `/v1/messages` to its base URL, so pass the door address without `/v1`. * Python ```python import os import anthropic from syderial_headers import load_headers client = anthropic.Anthropic( base_url=os.environ["SYDERIAL_DOOR_URL"], api_key="unused", default_headers=load_headers(), ) message = client.messages.create( model=os.environ["SYDERIAL_MODEL"], max_tokens=1024, messages=[ {"role": "user", "content": "When did V-204 fail, and how do we know?"}, ], ) print(message.content[0].text) ``` * TypeScript ```ts import Anthropic from "@anthropic-ai/sdk"; import { loadHeaders } from "./syderial-headers"; const client = new Anthropic({ baseURL: process.env.SYDERIAL_DOOR_URL, apiKey: "unused", defaultHeaders: loadHeaders(), }); const message = await client.messages.create({ model: process.env.SYDERIAL_MODEL!, max_tokens: 1024, messages: [ { role: "user", content: "When did V-204 fail, and how do we know?" }, ], }); const first = message.content[0]; if (first.type === "text") console.log(first.text); ``` * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/messages" \ -H @syderial-headers.txt \ -H "content-type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "'"$SYDERIAL_MODEL"'", "max_tokens": 1024, "messages": [ {"role": "user", "content": "When did V-204 fail, and how do we know?"} ] }' ``` ### OpenAI responses [Section titled “OpenAI responses”](#openai-responses) * Python ```python response = client.responses.create( model=os.environ["SYDERIAL_MODEL"], input="When did V-204 fail, and how do we know?", ) print(response.output_text) ``` Here `client` is the OpenAI client from step 6. * TypeScript ```ts const response = await client.responses.create({ model: process.env.SYDERIAL_MODEL!, input: "When did V-204 fail, and how do we know?", }); console.log(response.output_text); ``` Here `client` is the OpenAI client from step 6. * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/responses" \ -H @syderial-headers.txt \ -H "content-type: application/json" \ -d '{ "model": "'"$SYDERIAL_MODEL"'", "input": "When did V-204 fail, and how do we know?" }' ``` ## Streaming [Section titled “Streaming”](#streaming) All three doors stream server-sent events when you set `stream`, in the event format each API defines. * Python ```python stream = client.chat.completions.create( model=os.environ["SYDERIAL_MODEL"], messages=[{"role": "user", "content": "Summarise the V-204 record."}], stream=True, ) for chunk in stream: if chunk.choices and chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="", flush=True) ``` * TypeScript ```ts const stream = await client.chat.completions.create({ model: process.env.SYDERIAL_MODEL!, messages: [{ role: "user", content: "Summarise the V-204 record." }], stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); } ``` * curl ```sh curl -N "$SYDERIAL_DOOR_URL/v1/chat/completions" \ -H @syderial-headers.txt \ -H "content-type: application/json" \ -d '{ "model": "'"$SYDERIAL_MODEL"'", "stream": true, "messages": [{"role": "user", "content": "Summarise the V-204 record."}] }' ``` ## Next [Section titled “Next”](#next) * Read [The journal](/concepts/journal/) to see what the answer was drawn from. * Connect an agent through the [MCP door](/api/mcp/) or a [coding harness](/guides/coding-harnesses/). * See the fields each door reads in the [API reference](/api/). # Four graphs > Syderial rebuilds four graphs from the journal, one for each question a read must answer. All four come from the journal and nothing else. Syderial computes its graphs from the journal and can discard and rebuild them at any time. There are four, one for each question a read must answer. Permissionswho may see what person · team · boundary · grant Entitieswhat the entries are about asset · person · organization · document Ontologypolicies and decisions policy · decision · applies to · supersedes Capability and provenancewhat may act, and what it did tool reach · agent · ingested · performed rebuilt from The recordthe journal of signed entries entry · line · evidence · receipt **Figure 1.** Four graphs, rebuilt from the record. They connect only through the shared keys tenant, boundary and entity. A read crosses them in order, starting with permissions. Available to design partners as it ships. ## Permissions [Section titled “Permissions”](#permissions) **Who may see what.** People, teams and roles, the boundaries they belong to and the grants between them. Syderial computes a reader’s clearance here, and reads this graph before the others on every request. ## Entities [Section titled “Entities”](#entities) **What the entries are about.** Assets, people, organizations, places, documents and concepts, and the mentions that tie lines to them. Each relationship records how well the evidence supports it, and each entity belongs to a boundary. ## Ontology [Section titled “Ontology”](#ontology) **Policies and decisions.** Which decision a policy came from, where it applies and what it supersedes or adjusts. Syderial uses it to explain an outcome, such as why a reader can see a line. It never grants access. ## Capability and provenance [Section titled “Capability and provenance”](#capability-and-provenance) **What may act, and what it did.** The capability half lists tools, agents and connectors and the reach of each. Syderial reads it before an action, and it can only narrow what the action may touch. The provenance half records what was ingested, extracted, invoked and performed. Syderial writes it after each action and uses it to explain. ## How a read crosses them [Section titled “How a read crosses them”](#how-a-read-crosses-them) A read crosses the graphs in order: who may see, what the question is about, which policy applies and what may act. The graphs connect only through the shared keys tenant, boundary and entity, so information can’t pass between them any other way. ## When a graph and the journal disagree [Section titled “When a graph and the journal disagree”](#when-a-graph-and-the-journal-disagree) The journal wins. Syderial rebuilds the graph from the journal, which corrects it. # The journal > Syderial keeps the record as a journal of entries, each dated, signed and posted once. Each line cites its evidence, a correction is a new entry, and the chain of entries is the ledger. 7Q4N-0190Observation V-204 in service quote · shift log, 2 Feb, line 14 * valid from 2026-02-02 06:00Z * recorded at 2026-02-03 08:10Z * posting lane import · receipt * signed ed25519 · prev 41ab…c3e0 prev hash 7Q4N-0193Observation V-204 status failed quote · sensor log, start 1482, end 1611 * valid from 2026-03-11 09:14Z * recorded at 2026-03-11 11:02Z * posting lane reader · receipt * signed ed25519 · prev 9f1c…a204 prev hash 7Q4N-0201Adjustment V-204 failed from 22:40 pointer · entry 7Q4N-0193, valid from * valid from 2026-03-10 22:40Z * recorded at 2026-03-14 08:30Z * posting lane principal · receipt * signed ed25519 · prev 7d02…19e8 **Figure 1.** Three entries in the journal, in posting order. The adjustment moves the failure earlier in the world and later in the record. Both clocks stay visible. ## Entries [Section titled “Entries”](#entries) An **entry** is one dated, signed statement of what happened, posted once. Nobody edits it after posting. Every entry has these parts. | Part | Contents | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | `kind` | The type of entry, such as a fact, a decision, a task, a commitment, a request or an observation. | | `when` | The two clocks: when the content applied according to its source, and when the record learned it. See [Two clocks](/concepts/two-clocks/). | | `actors` | Who took part, each with a role. | | `lines` | The assertions the entry makes, each with its evidence. | | `relations` | Links to other entries, such as the entry this one corrects, supersedes, closes, blocks or waits on. | | `labels` | Who may read the entry. See [Labels and information flow](/concepts/labels/). | | `posting` | The lane, the poster and the receipt. | | `statement` | A short readable summary. | ## Lines [Section titled “Lines”](#lines) A **line** is one typed, atomic assertion inside an entry. It has a subject, a predicate and an object, the way a sentence has a subject, a verb and an object. Each line has one of three classes: * **statement** for something asserted. * **observation** for something witnessed. * **action** for something done. ## Evidence [Section titled “Evidence”](#evidence) Every line cites its evidence in one of two forms. * A **quote** is a verbatim excerpt from a retained source. Its start and end locate it, and a hash of the exact text fixes it. * A **pointer** refers to something already in the record, such as an entry or a document, together with its hash. If a line’s evidence doesn’t support it, Syderial doesn’t commit the line to the record. The [Entail station](/concepts/stations/#entail) runs that check. ## Posting lanes [Section titled “Posting lanes”](#posting-lanes) Entries arrive through one of three lanes, and every posting has a receipt. * **reader** for lines Syderial extracted from what it read. They’re admitted only when their evidence supports them. * **principal** for statements by a person with the authority to make them. * **import** for entries brought in from an existing journal, log or set of notes. The author decides the lane. A person’s own words and a model’s summary of them take different lanes. ## Corrections [Section titled “Corrections”](#corrections) Syderial never rewrites an entry. A correction is a new entry that cites the entry it corrects. * `corrects` fixes an error in an earlier entry. * `supersedes` replaces an earlier entry in full. The earlier entry stays in the record, so you can ask what the record said at any point in its history. In Figure 1, adjustment `7Q4N-0201` moves the failure of V-204 earlier in the world and posts it later in the record, and entry `7Q4N-0193` is unchanged. ## The chain [Section titled “The chain”](#the-chain) Each entry is signed and includes the hash of the entry before it. Changing or removing any entry breaks every link after it. A verifier checks those links. See [Receipts and verification](/concepts/receipts/). # Labels and information flow > Every line and every request has a label. A line reaches a reader only when the reader's clearance dominates its label on every axis, and the same rule governs tool calls. Syderial checks clearance before a question reaches the record. A model never sees a line the caller isn’t cleared for, so there’s nothing to filter out of an answer afterwards. ## Labels [Section titled “Labels”](#labels) Every line in the record has a **label**, and every request has a **clearance** with the same five axes. | Axis | Meaning | Rule | | ------------ | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------- | | boundary | The part of the organization the line belongs to, from a tree your organization manages. | The reader’s boundary must contain the line’s. | | sensitivity | How widely the line may travel, as a ladder of ranks your organization names. | The reader’s rank must be at or above the line’s. | | compartments | Need-to-know groups within a boundary. | The reader must belong to every compartment the line is in. | | integrity | How well the evidence supports the line, from unverified to proven. | The line must meet the floor the request sets. | | purpose | The uses the line is permitted for. | The request’s purpose must be one the line allows. | ## Dominance [Section titled “Dominance”](#dominance) A line reaches a reader only when the reader’s clearance **dominates** the line’s label on every axis. Dominance is a partial order. One clearance can dominate many labels, and two labels can be incomparable. axisline labelreader clearancecheck boundaryoperations / plant-2operationswithin: yes sensitivityrank 2rank 3at or above: yes compartmentsmaintenancemaintenance, safetycontains: yes integrityattestedfloor: inferredmeets floor: yes purposeoperationsauditcontains: no ResultThe line doesn't reach this reader. Four axes pass and purpose fails, and one failed axis is enough. **Figure 1.** Syderial checks dominance on every axis. A line reaches a reader only when the reader's clearance dominates its label on all five. Three rules follow from dominance. * Anything built from several lines gets the strictest of their labels. * No operation lowers a label. * A request can narrow its clearance and can’t widen it. Clearance comes from the credential and the permissions it maps to. ## Refusal and absence [Section titled “Refusal and absence”](#refusal-and-absence) A question can end in four ways, and Syderial answers each one differently. | Case | What you get | | ----------------------------------------- | ------------------------------------------------------------------------- | | The record has it and you’re cleared. | The answer with its evidence. | | The record has it and you aren’t cleared. | A refusal that names no one and reveals nothing about the withheld lines. | | The record doesn’t have it. | An honest absence. The door says the record has nothing on the question. | | A service failed. | An error. The door doesn’t answer from partial context. | ## Tool calls [Section titled “Tool calls”](#tool-calls) A tool call has a label too. Before a tool runs, the caller’s clearance and the tool’s own reach must both dominate the request. A tool with no declared reach doesn’t run. The [Gate station](/concepts/stations/#gate) applies this rule. Available to design partners as it ships. ## Further reading [Section titled “Further reading”](#further-reading) [Boundary-First Information Governance](https://syderial.ai/research/boundary-first-governance) is the architecture note behind this model. # Receipts and verification > Every answer, abstention, posting and tool decision gets a signed receipt on an append-only chain. Anyone with the verification key can check the chain without trusting the database that serves queries. A receipt is the record’s account of one event. You, or a reviewer who isn’t you, use receipts to check that the record says what it says and that nobody changed it afterwards. ## Events with receipts [Section titled “Events with receipts”](#events-with-receipts) | Event | The receipt records | | --------------- | -------------------------------------------------------------------------------------------- | | A posting | Which entry was posted, through which lane, by whom. | | An answer | The hash of the context packet, the lines it cited and the model lane that answered. | | An abstention | Whether the record was silent or the reader wasn’t cleared, and the scope Syderial searched. | | A tool decision | The tool, a hash of its arguments, the decision and the reason. | Receipts store hashes of content, never the content. A tool receipt stores the hash of the arguments. A reviewer can confirm the sequence of events is intact without clearance to read what those events contained. ## How the chain is built [Section titled “How the chain is built”](#how-the-chain-is-built) * Syderial serializes each receipt and each entry to a canonical form and hashes it with **SHA-256**. * Each one includes the hash of the one before it, which forms an append-only **hash chain**. * Syderial signs each hash with **Ed25519**. The chain doesn’t depend on the database that serves queries, so you can check it on its own. ## Verifying [Section titled “Verifying”](#verifying) Verification checks three properties in order. 1. **The hash.** Recompute the SHA-256 of the canonical form and compare it with the recorded hash. 2. **The signature.** Check the Ed25519 signature over that hash against the verification key issued with your deployment. 3. **The link.** Check that the recorded previous hash matches the hash of the receipt before it. A failed check marks the exact receipt where the record and its receipts disagree. Reference verifier We intend to publish the receipt format and a reference verifier as open source, so anyone can check a chain without depending on the service that wrote it. See [Open source](/open-source/). ## Where you’ll see receipts [Section titled “Where you’ll see receipts”](#where-youll-see-receipts) * The model doors return a receipt reference with each answer, next to the standard response fields. * The MCP door records a receipt for each proposal, commit and tool decision. * Design partners evaluating Syderial verify the receipts themselves before any commitment. # The six stations > Capture, Bound, Entail, Compile, Gate and Receipt. Every write and every read passes through the stations in order. 1. 01CaptureEvery turn, with its author. 2. 02BoundLabels on every line, the lattice on every read. 3. 03EntailEvidence must support the claim. 4. 04CompileA hashed packet of cleared context. 5. 05GatePolicy before any tool call runs. 6. 06ReceiptSigned, hash-chained, replayable. **Figure 1.** The six stations. Every write and every read passes through them in order. Writes pass through Capture, Bound and Entail. Reads pass through Bound, Compile and Gate. Both end with a Receipt. ## Capture [Section titled “Capture”](#capture) Every turn, with its author. Syderial retains what was said and who said it, whether a person, an agent acting for a person or a system. Evidence can quote only what Syderial captured. ## Bound [Section titled “Bound”](#bound) Labels on every line, the lattice on every read. Syderial labels each line when it’s written and checks each read against the reader’s clearance before a model sees anything. See [Labels and information flow](/concepts/labels/). ## Entail [Section titled “Entail”](#entail) Evidence must support the claim. Syderial judges each line against its cited span and a bounded window around it, and assigns one of four outcomes. | Outcome | Meaning | | ---------- | --------------------------------------------------------------------------------- | | commit | The evidence supports the line. Syderial commits it to the record. | | propose | The evidence partly supports the line. Syderial serves it only as a labeled lead. | | quarantine | The evidence doesn’t support the line. Syderial withholds it. | | degraded | The check couldn’t run. Syderial marks the line and doesn’t commit it. | Syderial never entails a claim that something is absent. It answers with the scope it searched. ## Compile [Section titled “Compile”](#compile) A hashed packet of cleared context. For each call, Syderial compiles the context of record the reader is cleared to see into a packet and hashes it. The same question asked of the same record at the same coordinates produces the same packet. The hash goes into the receipt, so a reviewer can identify the context behind any answer. ## Gate [Section titled “Gate”](#gate) Policy before any tool call runs. Syderial checks each proposed tool call against the caller’s clearance and the tool’s reach before it executes. A tool with no declared reach doesn’t run, and Syderial records each denial. Available to design partners as it ships. ## Receipt [Section titled “Receipt”](#receipt) Signed, hash-chained, replayable. Every answer, abstention, posting and tool decision gets a receipt, signed and chained to the one before. A reviewer can replay the sequence from the receipts without reading the content. See [Receipts and verification](/concepts/receipts/). # Two clocks > Every entry keeps two times. Valid time is when a claim applied according to its source. Recorded time is when the record learned it. With both, you can ask what the sources said applied at a time, or what the record knew at a time, without rewriting the past. A record with one clock has to rewrite its past whenever it learns something late. Syderial keeps two clocks for every entry. | Clock | Field | Meaning | Set by | | ------------- | ------------------------ | ------------------------------------------------ | ----------------------------- | | Valid time | `valid_from`, `valid_to` | When the claim applied, according to its source. | The entry, from its evidence. | | Recorded time | `recorded_at` | When the record learned it. | Syderial, at posting. | The research literature calls recorded time *transaction time*. **Figure 1.** The failure of V-204 on both clocks. The adjustment moves it earlier in the world, to 22:40 on 10 March, and posts it later in the record, on 14 March. The earlier entry is unchanged. ## Two questions, two answers [Section titled “Two questions, two answers”](#two-questions-two-answers) * **What applied on 11 March, according to the sources?** Read by valid time. After the adjustment, the record says V-204 was failed from 22:40 on 10 March, on the authority of the principal who posted the adjustment. * **What did we know on 12 March?** Read by recorded time as of 12 March. The record had entry `7Q4N-0193` only, a failure observed on the morning of 11 March. Syderial posted the adjustment two days later. Audits ask the second question: what did the agent know when it acted? A record with one clock can answer it only by keeping a separate history. ## What this means for your application [Section titled “What this means for your application”](#what-this-means-for-your-application) * You never update an entry in place. You post a new entry, and both clocks of the old entry stay as they were. * Syderial sets `recorded_at`. A client can’t backdate what the record knew. * An entry can be valid from long before it was recorded, as when a person states a decision made last month. ## Further reading [Section titled “Further reading”](#further-reading) [Bitemporal Claims: Separating Validity from Knowledge](https://syderial.ai/research/bitemporal-claims) shows why two clocks are enough, why one isn’t, and what auditability requires of a claim store. # Doors and credentials > Syderial has four doors. Three accept the request formats of the model APIs your clients already call, and the fourth is an MCP server. All four answer from the same record under the same labels. A **door** is an endpoint that speaks a protocol your client already knows. Syderial identifies every call through a door, limits it to the caller’s clearance, grounds it in the record and signs a receipt for it. | Door | Method and path | Request format | | ------------------------------------------ | --------------------------- | --------------------------------------- | | [Chat completions](/api/chat-completions/) | `POST /v1/chat/completions` | OpenAI chat completions | | [Messages](/api/messages/) | `POST /v1/messages` | Anthropic messages | | [Responses](/api/responses/) | `POST /v1/responses` | OpenAI responses | | [Models](/api/models/) | `GET /v1/models` | OpenAI models list | | [MCP door](/api/mcp/) | `POST /mcp` | Model Context Protocol, streamable HTTP | ## Addresses [Section titled “Addresses”](#addresses) Syderial issues door addresses to design partners. These pages write them as `https://YOUR-DOOR-ADDRESS` for the model doors and `https://YOUR-MCP-DOOR-ADDRESS` for the MCP door. ## Credentials [Section titled “Credentials”](#credentials) Syderial issues each credential as a set of request headers. Send them on every call. The [Quickstart](/quickstart/) shows how to load them into the OpenAI and Anthropic SDKs and into curl. * **Identity comes from the credential.** A request body can’t name its own organization or principal, and the door rejects requests that try. * **The door ignores the SDK key field.** The OpenAI and Anthropic SDKs require an API key value, so pass any placeholder. * **Scopes limit each credential.** A credential may call the model doors, capture turns, or both. The door refuses calls outside its scopes. * **Your organization’s provider keys.** Syderial calls model providers with keys your organization controls. The MCP door also accepts standard MCP authorization with browser sign-in. See [MCP door](/api/mcp/). ## Model aliases [Section titled “Model aliases”](#model-aliases) The `model` field takes an alias configured for your organization. [List your aliases](/api/models/) to see which ones you can use. The door doesn’t serve a call with an unknown alias. ## What Syderial adds to a response [Section titled “What Syderial adds to a response”](#what-syderial-adds-to-a-response) Responses follow each API’s standard format, so standard clients parse them unchanged. Syderial adds the evidence behind the answer and a receipt reference in extra response fields and headers, which standard clients ignore. The design partner reference documents the field names. ## Streaming [Section titled “Streaming”](#streaming) All three model doors stream server-sent events when the request sets `stream` to `true`, in the event format each API defines. ## Errors [Section titled “Errors”](#errors) Errors return an HTTP status and a JSON body with a machine-readable error code. | Status | Meaning | | ------ | -------------------------------------------------------------------------------------- | | `400` | The request body isn’t valid for the door, or exceeds the limit on messages or tools. | | `401` | The credential is missing, incomplete or not recognized. | | `403` | The credential lacks the scope for this door. | | `429` | Your organization has too many concurrent requests or streams. | | `503` | A service the call needs is unavailable. The door doesn’t answer from partial context. | # Chat completions > POST /v1/chat/completions. The OpenAI chat completions format, answered from the record within the caller's clearance. ```http POST https://YOUR-DOOR-ADDRESS/v1/chat/completions ``` Requests and responses follow the OpenAI chat completions API. Use the OpenAI SDK with `base_url` set to your door address plus `/v1`, and your credential headers as default headers. See [Doors and credentials](/api/). ## Request fields the door reads [Section titled “Request fields the door reads”](#request-fields-the-door-reads) | Field | Type | Notes | | ----------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------- | | `model` | string, required | A model alias configured for your organization. See [Models](/api/models/). | | `messages` | array, required | Non-empty. Roles `system`, `developer`, `user`, `assistant` and `tool`. A `developer` message is treated as `system`. | | `max_completion_tokens` | integer | Upper bound on generated tokens. `max_tokens` is accepted as well. | | `temperature` | number | As in the standard API. | | `tools` | array | Function tools, as in the standard API. | | `tool_choice` | string or object | As in the standard API. | | `metadata` | object | As in the standard API. | | `stream` | boolean | `true` streams server-sent events in the standard chunk format. | A request body can’t include organization or principal identity. The door limits the number of messages and tools per request. ## Example [Section titled “Example”](#example) * Python ```python import os from openai import OpenAI from syderial_headers import load_headers # helper from the Quickstart client = OpenAI( base_url=os.environ["SYDERIAL_DOOR_URL"] + "/v1", api_key="unused", default_headers=load_headers(), ) completion = client.chat.completions.create( model=os.environ["SYDERIAL_MODEL"], messages=[ {"role": "system", "content": "Answer from the record. Say when the record is silent."}, {"role": "user", "content": "Which decisions changed the V-204 maintenance plan?"}, ], max_completion_tokens=800, ) print(completion.choices[0].message.content) ``` * TypeScript ```ts import OpenAI from "openai"; import { loadHeaders } from "./syderial-headers"; // helper from the Quickstart const client = new OpenAI({ baseURL: `${process.env.SYDERIAL_DOOR_URL}/v1`, apiKey: "unused", defaultHeaders: loadHeaders(), }); const completion = await client.chat.completions.create({ model: process.env.SYDERIAL_MODEL!, messages: [ { role: "system", content: "Answer from the record. Say when the record is silent." }, { role: "user", content: "Which decisions changed the V-204 maintenance plan?" }, ], max_completion_tokens: 800, }); console.log(completion.choices[0].message.content); ``` * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/chat/completions" \ -H @syderial-headers.txt \ -H "content-type: application/json" \ -d '{ "model": "'"$SYDERIAL_MODEL"'", "max_completion_tokens": 800, "messages": [ {"role": "system", "content": "Answer from the record. Say when the record is silent."}, {"role": "user", "content": "Which decisions changed the V-204 maintenance plan?"} ] }' ``` ## Response [Section titled “Response”](#response) A standard chat completion object, or a stream of standard chunks when `stream` is `true`. Syderial adds the evidence and a receipt reference alongside the standard fields. See [What Syderial adds to a response](/api/#what-syderial-adds-to-a-response). # MCP door > The record as Model Context Protocol tools. Agents read the context of record, propose entries and check authority before acting, under the same labels as every other read. ```http POST https://YOUR-MCP-DOOR-ADDRESS/mcp ``` The MCP door is a Model Context Protocol server over streamable HTTP. Any MCP client that supports remote servers can connect. ## Authorization [Section titled “Authorization”](#authorization) The MCP door follows the MCP authorization specification. * The door publishes protected resource metadata at `/.well-known/oauth-protected-resource`. Your client reads it, finds the authorization server and signs you in through the browser. * A request without valid authorization gets a `401` with a `WWW-Authenticate` challenge that points to that metadata, and no tool list. * Your sign-in maps to a Syderial principal and a set of scopes. Roles and groups in your identity provider don’t grant Syderial authority on their own. * Clients that can’t sign in through a browser can send a header credential, as for the model doors. ## Sessions [Section titled “Sessions”](#sessions) `initialize` opens a session and returns an `Mcp-Session-Id` header. Later requests in the session send that header and must authenticate as the same identity. Sessions end on `DELETE`, when the transport closes, or after a period of inactivity. ## Tools [Section titled “Tools”](#tools) `tools/list` returns the tools your scopes allow. They fall into these families. | Family | What the tools do | | ---------- | -------------------------------------------------------------------------------------------------------- | | Record | Propose an entry without committing it, commit an authorized proposal and read the history of a subject. | | Context | Retrieve the context of record for a question as a packet, limited to your clearance. | | Evidence | Expand one piece of cited evidence into its signed source window. | | Artifacts | Register an artifact and its source, and read what you are cleared to see of it. | | Case files | Open, update, review and close a bounded working matter, with a receipt on closing. | | Authority | Simulate whether an action would be allowed before attempting it. | | Briefs | Read the daily and weekly briefs and the items that have drifted, within your boundary. | | Execution | Propose an action without side effects, turn an approved proposal into a ticket and read its status. | Syderial checks every tool call against authority and records it. Writes pass through the same [stations](/concepts/stations/) as every other write, so Syderial commits a proposal only when its evidence supports it. ## Connect a client [Section titled “Connect a client”](#connect-a-client) * Claude Code ```sh claude mcp add --transport http syderial https://YOUR-MCP-DOOR-ADDRESS/mcp ``` Then run `/mcp` in a session and sign in. * Codex \~/.codex/config.toml ```toml [mcp_servers.syderial] url = "https://YOUR-MCP-DOOR-ADDRESS/mcp" ``` Then run `codex mcp login syderial`. See [Coding harnesses](/guides/coding-harnesses/) for the full setup. # Messages > POST /v1/messages. The Anthropic messages format, answered from the record within the caller's clearance. ```http POST https://YOUR-DOOR-ADDRESS/v1/messages ``` Requests and responses follow the Anthropic messages API. Use the Anthropic SDK with `base_url` set to your door address (without `/v1`, which the SDK adds) and your credential headers as default headers. See [Doors and credentials](/api/). ## Request fields the door reads [Section titled “Request fields the door reads”](#request-fields-the-door-reads) | Field | Type | Notes | | ------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `model` | string, required | A model alias configured for your organization. See [Models](/api/models/). | | `max_tokens` | integer, required | Upper bound on generated tokens. | | `messages` | array, required | Non-empty. Roles `user` and `assistant`. Content is a string or an array of `text`, `image`, `tool_use` and `tool_result` blocks. | | `system` | string or array | A string or an array of text blocks. | | `tools` | array | Client tools, as in the standard API. | | `tool_choice` | object | As in the standard API. | | `metadata` | object | As in the standard API. | | `stream` | boolean | `true` streams server-sent events in the standard event format. | A request body can’t include organization or principal identity. The door limits the number of messages and tools per request. ## Example [Section titled “Example”](#example) * Python ```python import os import anthropic from syderial_headers import load_headers # helper from the Quickstart client = anthropic.Anthropic( base_url=os.environ["SYDERIAL_DOOR_URL"], api_key="unused", default_headers=load_headers(), ) message = client.messages.create( model=os.environ["SYDERIAL_MODEL"], max_tokens=800, system="Answer from the record. Say when the record is silent.", messages=[ {"role": "user", "content": "Which decisions changed the V-204 maintenance plan?"}, ], ) print(message.content[0].text) ``` * TypeScript ```ts import Anthropic from "@anthropic-ai/sdk"; import { loadHeaders } from "./syderial-headers"; // helper from the Quickstart const client = new Anthropic({ baseURL: process.env.SYDERIAL_DOOR_URL, apiKey: "unused", defaultHeaders: loadHeaders(), }); const message = await client.messages.create({ model: process.env.SYDERIAL_MODEL!, max_tokens: 800, system: "Answer from the record. Say when the record is silent.", messages: [ { role: "user", content: "Which decisions changed the V-204 maintenance plan?" }, ], }); for (const block of message.content) { if (block.type === "text") console.log(block.text); } ``` * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/messages" \ -H @syderial-headers.txt \ -H "content-type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "'"$SYDERIAL_MODEL"'", "max_tokens": 800, "system": "Answer from the record. Say when the record is silent.", "messages": [ {"role": "user", "content": "Which decisions changed the V-204 maintenance plan?"} ] }' ``` ## Streaming [Section titled “Streaming”](#streaming) ```python with client.messages.stream( model=os.environ["SYDERIAL_MODEL"], max_tokens=800, messages=[{"role": "user", "content": "Summarise the V-204 record."}], ) as stream: for text in stream.text_stream: print(text, end="", flush=True) ``` ## Response [Section titled “Response”](#response) A standard message object, or a standard event stream when `stream` is `true`. Syderial adds the evidence and a receipt reference alongside the standard fields. See [What Syderial adds to a response](/api/#what-syderial-adds-to-a-response). # Models > GET /v1/models. Lists the model aliases configured for your organization, in the OpenAI models list format. ```http GET https://YOUR-DOOR-ADDRESS/v1/models ``` The `model` field on every door takes an **alias** configured for your organization. Each alias names the model that answers and the provider key used to call it. This call lists your aliases. ## Example [Section titled “Example”](#example) * Python ```python for model in client.models.list(): print(model.id) ``` * TypeScript ```ts for await (const model of client.models.list()) { console.log(model.id); } ``` * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/models" -H @syderial-headers.txt ``` ## Response [Section titled “Response”](#response) ```json { "object": "list", "data": [ { "id": "", "object": "model", "owned_by": "syderial", "endpoint_family": "" } ] } ``` `endpoint_family` says which door an alias is meant for. Use `id` as the `model` value in your calls. # Responses > POST /v1/responses. The OpenAI responses format, answered from the record within the caller's clearance. ```http POST https://YOUR-DOOR-ADDRESS/v1/responses ``` Requests and responses follow the OpenAI responses API. Use the OpenAI SDK with `base_url` set to your door address plus `/v1`, and your credential headers as default headers. See [Doors and credentials](/api/). ## Request fields the door reads [Section titled “Request fields the door reads”](#request-fields-the-door-reads) | Field | Type | Notes | | ------------------- | ------------------------- | --------------------------------------------------------------------------- | | `model` | string, required | A model alias configured for your organization. See [Models](/api/models/). | | `input` | string or array, required | A string, or a non-empty array of input items. | | `instructions` | string | System instructions, as in the standard API. | | `max_output_tokens` | integer | Upper bound on generated tokens. | | `temperature` | number | As in the standard API. | | `tools` | array | Function tools, as in the standard API. | | `tool_choice` | string or object | As in the standard API. | | `metadata` | object | As in the standard API. | | `stream` | boolean | `true` streams server-sent events in the standard event format. | A request body can’t include organization or principal identity. The door limits the number of messages and tools per request. ## Example [Section titled “Example”](#example) * Python ```python import os from openai import OpenAI from syderial_headers import load_headers # helper from the Quickstart client = OpenAI( base_url=os.environ["SYDERIAL_DOOR_URL"] + "/v1", api_key="unused", default_headers=load_headers(), ) response = client.responses.create( model=os.environ["SYDERIAL_MODEL"], instructions="Answer from the record. Say when the record is silent.", input="Which decisions changed the V-204 maintenance plan?", max_output_tokens=800, ) print(response.output_text) ``` * TypeScript ```ts import OpenAI from "openai"; import { loadHeaders } from "./syderial-headers"; // helper from the Quickstart const client = new OpenAI({ baseURL: `${process.env.SYDERIAL_DOOR_URL}/v1`, apiKey: "unused", defaultHeaders: loadHeaders(), }); const response = await client.responses.create({ model: process.env.SYDERIAL_MODEL!, instructions: "Answer from the record. Say when the record is silent.", input: "Which decisions changed the V-204 maintenance plan?", max_output_tokens: 800, }); console.log(response.output_text); ``` * curl ```sh curl "$SYDERIAL_DOOR_URL/v1/responses" \ -H @syderial-headers.txt \ -H "content-type: application/json" \ -d '{ "model": "'"$SYDERIAL_MODEL"'", "instructions": "Answer from the record. Say when the record is silent.", "input": "Which decisions changed the V-204 maintenance plan?", "max_output_tokens": 800 }' ``` ## Response [Section titled “Response”](#response) A standard response object, or a standard event stream when `stream` is `true`. Syderial adds the evidence and a receipt reference alongside the standard fields. See [What Syderial adds to a response](/api/#what-syderial-adds-to-a-response). # Coding harnesses > Connect Claude Code or Codex to Syderial. Give the agent the record as MCP tools, send its model calls through a door, or both. A coding agent can reach the record in two ways. | Path | What the agent gets | What you configure | | -------------- | ---------------------------------------------------------------------------- | ----------------------------------- | | **MCP door** | Tools to read the record, propose entries and check authority before acting. | One MCP server entry. | | **Model door** | Every model call the harness makes is grounded in the record and receipted. | The harness’s base URL and headers. | Start with the MCP door if the agent needs the record as a tool. Add the model door when every call should answer from the record. Available to design partners as it ships. Access Syderial issues the MCP door address, the model door address and the credential to design partners. The examples use placeholders. ## Connect the MCP door [Section titled “Connect the MCP door”](#connect-the-mcp-door) The MCP door speaks the Model Context Protocol over streamable HTTP and follows standard MCP authorization. Your harness reads the door’s protected resource metadata, finds the authorization server and signs you in through your browser. * Claude Code ```sh claude mcp add --transport http syderial https://YOUR-MCP-DOOR-ADDRESS/mcp ``` Start Claude Code, run `/mcp`, choose `syderial` and sign in. The session then lists the tools your credential allows. * Codex \~/.codex/config.toml ```toml [mcp_servers.syderial] url = "https://YOUR-MCP-DOOR-ADDRESS/mcp" ``` Then sign in: ```sh codex mcp login syderial ``` A client that hasn’t signed in sees no tools. The [MCP door](/api/mcp/) reference lists the tool families. ## Send model calls through a door [Section titled “Send model calls through a door”](#send-model-calls-through-a-door) Both harnesses can send model calls to another base URL with extra headers. Use the door address and credential headers from the [Quickstart](/quickstart/). * Claude Code Claude Code calls the Anthropic messages API, so it uses the messages door. ```sh export ANTHROPIC_BASE_URL="https://YOUR-DOOR-ADDRESS" export ANTHROPIC_CUSTOM_HEADERS="$(cat syderial-headers.txt)" export ANTHROPIC_AUTH_TOKEN="unused" # the door reads the credential headers export ANTHROPIC_MODEL="" export ANTHROPIC_DEFAULT_HAIKU_MODEL="" # used for background calls claude ``` `ANTHROPIC_CUSTOM_HEADERS` takes one `Name: value` pair per line, the same format as `syderial-headers.txt`. Setting `ANTHROPIC_AUTH_TOKEN` stops Claude Code from sending any other credential on your machine to the door. * Codex Codex calls the OpenAI responses API, so it uses the responses door. Put each issued header value in an environment variable and map it in a provider entry. \~/.codex/config.toml ```toml model = "" model_provider = "syderial" [model_providers.syderial] name = "Syderial" base_url = "https://YOUR-DOOR-ADDRESS/v1" wire_api = "responses" [model_providers.syderial.env_http_headers] "" = "SYDERIAL_CREDENTIAL_1" "" = "SYDERIAL_CREDENTIAL_2" ``` ```sh export SYDERIAL_CREDENTIAL_1="" export SYDERIAL_CREDENTIAL_2="" codex ``` Request fields Each door’s contract covers the fields listed in the [API reference](/api/) for its protocol. Other request fields aren’t part of it. If your harness depends on one, call the model directly and connect the MCP door alone. ## Capture hooks [Section titled “Capture hooks”](#capture-hooks) Design partners also receive a hooks kit for Claude Code, Codex and OpenCode. It records each prompt and each final turn in the journal with its author, and runs an advisory check before each tool call. The kit includes its own setup notes. # Build on the record > Governed continuity for people and agents: where each claim came from, on whose authority, and what the record does not know. Syderial doors accept the request formats your code already sends: OpenAI chat completions, Anthropic messages, OpenAI responses and the Model Context Protocol. Change the base URL and add your credential. Syderial answers each call from the record, within the caller’s clearance, and signs a receipt for it. The change in your client ```python client = OpenAI( base_url=os.environ["SYDERIAL_DOOR_URL"] + "/v1", # a Syderial door api_key="unused", # the door ignores this field default_headers=load_headers(), # your issued credential ) ``` [Overview](/overview/)What the record keeps, and what changes when your agents answer from it. [Quickstart](/quickstart/)Send a call through a door in Python, TypeScript or curl. [Concepts](/concepts/journal/)The journal, two clocks, labels, the six stations, receipts and the four graphs. [API reference](/api/)The three model doors, the models list and the MCP door. [Coding harnesses](/guides/coding-harnesses/)Connect Claude Code or Codex to the record. [Research](/research/)Papers on bitemporal claims, boundaries and why intelligence needs a record. ## Access [Section titled “Access”](#access) Syderial issues door addresses and credentials to design partners. We work with a small number of organizations whose decisions deserve a verifiable past. [Request a briefing](https://syderial.ai/early-access) to apply. ## For agents reading this site [Section titled “For agents reading this site”](#for-agents-reading-this-site) [/llms.txt](/llms.txt) lists every page with a one-line summary. [/llms-full.txt](/llms-full.txt) has the full text. # Research > Syderial is a research company, and we publish what we find. These papers set out the ideas behind the record. [Bitemporal Claims: Separating Validity from Knowledge](https://syderial.ai/research/bitemporal-claims)Paper. A record that keeps one clock must rewrite its past to stay current. Why two clocks are enough, why one isn't, and what auditability requires of a claim store. [Boundary-First Information Governance](https://syderial.ai/research/boundary-first-governance)Architecture note. Access control filters answers after the fact. Boundaries limit the question before it reaches the record. [Why Intelligence Needs a System of Record](https://syderial.ai/research/intelligence-system-of-record)Essay. Money, operations, relationships and identity each got a system of record when they began to matter. Intelligence still runs without one. ## How these map to the docs [Section titled “How these map to the docs”](#how-these-map-to-the-docs) | Paper | Where it shows up here | | ----------------------------------------- | ---------------------------------------------------------------------------------- | | Bitemporal Claims | [Two clocks](/concepts/two-clocks/), [The journal](/concepts/journal/) | | Boundary-First Information Governance | [Labels and information flow](/concepts/labels/), [Four graphs](/concepts/graphs/) | | Why Intelligence Needs a System of Record | [Overview](/overview/) | The papers use the word *claim* for a line with its evidence and labels, and they describe the record as the context of record. ## The specification [Section titled “The specification”](#the-specification) We distribute the context-of-record specification to early-access organizations and reviewers. We welcome serious technical correspondence, and disagreement most of all. [Request a copy](https://syderial.ai/early-access). # Open source > What we intend to open, and in what order. The parts that let anyone check the record without trusting Syderial lead the list. A stranger should be able to check the record without our help. The parts we intend to open earliest make that possible. None is published yet, and this page lists them in the order we intend to release them. ## Coming [Section titled “Coming”](#coming) ### Receipt format and reference verifier [Section titled “Receipt format and reference verifier”](#receipt-format-and-reference-verifier) A precise written description of the canonical form, hashing, chain links and Ed25519 signatures behind every [receipt](/concepts/receipts/), detailed enough for an independent implementation. It comes with a reference verifier that checks a chain end to end. ### Record schema [Section titled “Record schema”](#record-schema) A versioned schema for an entry, its lines, its evidence and its two clocks. Importers, exporters and verifiers can then work against the definition Syderial uses. ### Label model [Section titled “Label model”](#label-model) A small library with the five label axes and the dominance rule. It answers whether a line may reach a reader, using the rule the record uses. ### Formal specification of the record [Section titled “Formal specification of the record”](#formal-specification-of-the-record) Machine-checkable specifications of the record’s core rules. The record admits only supported lines, corrections never rewrite an entry, labels only get stricter, and every consequential step leaves a receipt. ### Client kits [Section titled “Client kits”](#client-kits) The configuration fragments and capture hooks for coding harnesses, and examples for connecting MCP clients, so you can read the integration code you run. ## What stays closed [Section titled “What stays closed”](#what-stays-closed) The context compiler, the extraction and entailment pipeline and the service that runs the doors stay proprietary. We’re opening the parts you need to check the record and keeping closed the parts that produce it. ## Follow along [Section titled “Follow along”](#follow-along) We’ll announce each release on [syderial.ai](https://syderial.ai/), [X](https://x.com/SyderialAI) and [GitHub](https://github.com/SyderialAI). To review a part before it opens, [get in touch](https://syderial.ai/early-access).