# DECS — setup and use, for AI agents You are probably reading this because a human pasted you the link. This document is self-contained: it tells you how to find out whether DECS is already working in the repository in front of you, how to get it working if it isn't, and what to do with it once it is. No prior knowledge assumed. It deliberately contains no project ids, no credentials and no example identifiers. It is the same document for every reader. Everything specific to the repository you are in comes from that repository, not from here. ## What DECS is, and what it is not DECS is persistent collaboration memory and an asynchronous coordination surface. It records, organizes, resurfaces and explains evolving truth: the decisions a project has made and why, the questions still open, and the answers its humans give while you keep working. The point is that a *different* session reads what this one recorded — a teammate's agent tomorrow, a human in the web app, you after a context compaction. That is the difference between DECS and a machine-local notes file: DECS is structured, server-shared and visible to the whole project. What DECS is not: - **It is not a gate.** Nothing here blocks the work in front of you. If DECS is absent, misconfigured, unreachable, or the human declines to set it up, do the work anyway and say so plainly once. Never stall on DECS. - **It is not something you install unasked.** Offer; never auto-install, never write a credential anywhere without saying where it went. - **A Decision is not the place for running commentary.** Running commentary now has a home: an **AI Session Note**, filed with `add.decs.session_note`. A Decision is a settled judgement a future session would otherwise re-derive or re-litigate: a technology or architecture choice, a constraint discovered, a prior decision reversed. Everything else worth keeping — progress made, a finding, a dead end, context a later session would have to rediscover — is a Session Note; filing it as a Decision buries the real decisions among the rest. ## Do you already have DECS here? Three checks. All three pass, or you are not set up — there is no partial "working." 1. **A project identity.** A `.decs.json` file at the repository root (and often inside each app directory of a monorepo) whose `v2.projectScopeId` is present and NOT null. 2. **A credential.** A project-scoped credential reachable by the tools you run, conventionally in the environment variable `RELENTLESS_DECS_API_KEY`. 3. **A live catalog fetch.** `GET {host}/api/semantic-definitions` with that credential returns 200. Only the third check proves anything. The first two are necessary conditions you can verify by reading; the fetch is the only evidence the credential is alive, belongs to this project, and reaches a deployment that has DECS turned on. The partial states each mean something specific, so read them rather than retrying: - `.decs.json` exists but `v2.projectScopeId` is `null` — this directory declares a v2 identity but was never linked to a concrete project. That is a documented, non-error state. A human links it in the app. - No `.decs.json` anywhere — this repository does not record to DECS at all. - Credential missing — nothing will authenticate; go to *Getting a credential* below. - Everything present, fetch returns 401 or 403 — the credential is expired, revoked, or belongs to a different project than the one in `.decs.json`. ## Project identity comes from `.decs.json`, never from this document `.decs.json` is committed to the repository and is the machine-readable marker for which DECS project that code records to. Read it. Do not carry an id between repositories, do not infer one from a project's name, and do not expect to find one here — this document deliberately carries none, so it cannot drift from the file that is authoritative. Its shape: ```json { "v2": { "projectScopeId": "", "host": "" } } ``` `v2.host` is the origin every URL in this document's `{host}` placeholder refers to. In a monorepo it is the same origin in every app directory — identity varies per directory, the backend does not. A file may also carry older v1 keys alongside `v2`; leave them alone, they are read by a separate legacy path. ## Getting a credential You cannot mint one. A human does it in the Relentless web app, and it is worth telling them the exact path rather than describing it vaguely: > Open the project in Relentless, scroll to the **DECS** section on the > project, find **Credentials**, and click **+ New**. Copy the credential it > shows you — that is the only time it is displayed in full. Any live member of the project can do this; it is not owner-only. What the credential is: a Bearer token bound to exactly one project scope, sent as `Authorization: Bearer `. Its validity is derived from live project membership on every single call — if that person is removed from the project, the credential stops working on its very next request, not on a delay. It also carries a 365-day expiry as a backstop, which is not how it gets revoked. One consequence worth stating: a credential is *per project*. An agent working across several DECS-recording repositories needs several. ## Where the credential goes **Canonical: the repository's own `.claude/settings.local.json`**, in its `env` block, as `RELENTLESS_DECS_API_KEY`. That file is gitignored by convention and is per-repository, which is what the per-project credential model actually requires — a single global environment slot silently breaks the moment a second project is involved, and the failure looks like "DECS answers about the wrong project," which is much worse than not working. ```json { "env": { "RELENTLESS_DECS_API_KEY": "" } } ``` A shell profile export works too, and is a reasonable shortcut for someone who only ever works in one DECS project. Say that tradeoff out loud rather than picking silently for them. Never put it in a tracked file. Never commit it. Before you write it anywhere, confirm the file you are writing to is ignored by git, and after you write it, tell the human exactly which file now holds their credential. ## Verifying — the only definition of success ```bash curl -s -o /dev/null -w '%{http_code}\n' \ -H "Authorization: Bearer $RELENTLESS_DECS_API_KEY" \ {host}/api/semantic-definitions ``` 200 means DECS is set up. Anything else means it is not: - **401** — no credential presented, or the credential is expired or revoked. - **403** — authenticated, but not permitted for this project scope. - **404** — this deployment does not have DECS v2 enabled. - **429** — rate limited; wait, do not retry in a loop. A successful fetch is the *only* thing that establishes setup succeeded. Having written the files is not evidence. Do not report success on the strength of having done the steps — run the fetch, and report what it returned. ## The core actions The full vocabulary is 24 actions; these are the ones worth knowing by name. Descriptions and postures below are read live from the registry, not restated by hand: - `start.decs.session` — Starts a DECS session for one conversation — or re-attaches to an existing one when its server-issued id is presented — and returns the bootstrap context that conversation needs to start working, including this project's key decisions and its most recent ordinary ones in full. (callable with a project-scoped credential) - `add.decs.decision` — Files a new Decision in a Project's Decisions module: what was decided, optionally why, what it serves and what constrained it, stamped with the provenance of whoever recorded it. (callable with a project-scoped credential) - `add.decs.session_note` — Files an AI Session Note in a Project's AI Session Notes module: what a working session produced, found, tried or abandoned, stamped with the session it came from and the model that wrote it. (callable with a project-scoped credential) - `list.decs.decision` — Reads the Decisions filed in a project — what was decided, why, what it serves and what constrained it, plus each decision's current version and what it relates to. (callable with a project-scoped credential) - `list.decs.plan` — Reads the Plans filed in a project — master plans, implementation plans and how they group — with each plan's status, current version, and the wrap-up it was completed with. (callable with a project-scoped credential) - `list.decs.project` — Reads a project's DECS state: whether DECS is enabled, which modules exist, how many decisions, plans, questions and session notes are filed, who is a member of the project scope, and which other conversations are working in it. (callable with a project-scoped credential) - `add.decs.question` — Asks a project's humans an asynchronous question — a prompt, optional stable options and one shared canonical answer stream any project editor may fill — filed in the Questions module and addressed back to the DECS session that asked, which keeps working while it waits. (callable with a project-scoped credential) - `update.decs.question` — Corrects or withdraws a question a project already asked — reword the prompt, replace the options, or retire it so it leaves the human's queue without destroying the answers already on it. (callable with a project-scoped credential) - `answer.decs.question` — Answers a question a project asked — selected option ids and/or free text, with optional notes — as a new revision that never overwrites an earlier one, and delivers the answer back to the DECS session that asked. (callable with a project-scoped credential) - `list.decs.question` — Reads a project's questions with their full answer history — prompt, stable options, who it was addressed to, which answer streams are still waiting, every revision on every stream oldest first, and what each question is about (the plans or decisions it relates to). (callable with a project-scoped credential) - `list.decs.communication` — Reads a DECS session's addressed delivery queue in keyset order, oldest first, with the session's current acknowledgement cursor and — for your own session — unread counts per event type. (callable with a project-scoped credential) - `acknowledge.decs.communication` — Advances a DECS session's acknowledgement cursor to a communication it has handled, so that delivery and everything before it is never delivered to that session again. (callable with a project-scoped credential) Every action is a POST to `{host}/api/semantic-actions/` with an envelope carrying `target` (the project scope, exactly one of `scopeId` or `projectNodeId`), `input` (the action's own schema), and optionally `decsSessionId` and `provenance`. The catalog below publishes the exact shapes; do not guess them from these one-liners. ## Reading what is already recorded The point of recording decisions is that a later session reads them, so start here rather than with the write actions. `start.decs.session` returns a bootstrap context carrying this project's key decisions and its ten most recent ordinary ones **in full** — what was decided, why, what it serves, what constrained it — each with a node id. For an ordinary session that is all the reading you need, and it is also how the context comes back after a compaction: re-attaching your session IS the re-injection, there is no second mechanism. Three actions read past what the bootstrap sampled: - `list.decs.decision` reads decisions — wider than the sample, filtered to key decisions, or one by id. - `list.decs.plan` reads master and implementation plans, and how they group. - `list.decs.project` reads the project itself: modules, counts, member ids. Two things about them are worth knowing before you need them: - **They are where node ids and versions come from.** `update.decs.decision` and `update.decs.question` each require a `nodeId` and an `expectedVersion`, and the matching read returns both; `revise.decs.plan` and `complete.decs.plan` require a plan's `nodeId`; `relate.decs.artifact` requires two. A create call returns its own id, but once that conversation ends the read actions are the only way back to it. - **Reading acknowledges nothing.** A read never moves a delivery cursor. Only `acknowledge.decs.communication` does, and only for the delivery it names. If your context window is small, pass `condensed: true` to `start.decs.session`: the bootstrap comes back with decision ids and titles instead of prose, and you read the ones that matter through `list.decs.decision`. Nothing becomes unreachable — the ids are always there. ## The full catalog `GET {host}/api/semantic-definitions` returns every action's input and output schema, authorization posture, preconditions, effects, error codes and worked examples, plus the request envelope schema and the closed error-code table. A credential is required — this endpoint is what you verified setup against above. Read it once per session rather than working from memory of this page. It is the contract; this page is an orientation. ## Setting yourself up: Claude Code Requires Claude Code 2.1.214 or newer. Below that version, `SessionStart`'s `source` field cannot distinguish a forked conversation from a resumed one, and two windows would silently share one DECS session. Check with `claude --version` first. ``` claude plugin marketplace add RelentlessToph/relentless-decs claude plugin install relentless-decs@relentless-decs-marketplace ``` Run both. Being listed under `enabledPlugins` in a settings file does not by itself complete an installation on current Claude Code — a repository can declare the marketplace and the plugin, and the plugin still will not be installed until the explicit install command runs — current Claude Code shows no install prompt for it. If you are troubleshooting a plugin that "should" be active because settings mention it, that is the first thing to check. The plugin gives you a DECS session that spans the whole conversation, real awareness delivered on every semantic-action response rather than keyword guessing, and an MCP server. It reads the same `RELENTLESS_DECS_API_KEY` and the same `.decs.json` described above. At session start it injects this project's decisions in full. To get ids and titles instead — condensed start hooks — set `RELENTLESS_DECS_CONDENSED_START` to `1` in the same place the credential lives. The Codex plugin reads the same variable, and is where it most often earns its keep. ## Setting yourself up: other agents - **Codex CLI** — a Codex plugin that mirrors the Claude Code one behavior for behavior (session bootstrap, awareness, decision hygiene, provenance), installed through `codex plugin marketplace add` and `codex plugin add`. - **MCP, any client** — a Streamable HTTP MCP server at `{host}/api/mcp`. Bearer credential only: no browser session, no other key class. Tool names are action keys with dots replaced by underscores (`add.decs.decision` becomes `add_decs_decision`), and arguments are the same envelope shape as the REST surface. A manual `curl` against it must send `Accept: application/json, text/event-stream` — BOTH types, or the transport rejects the request with a 406 before any DECS code runs. - **Plain REST** — POST the semantic actions directly. Nothing is lost; the plugins and the MCP server are conveniences over this same surface. Same credential, same vocabulary, same catalog in every case. Pick whichever your runtime actually supports. ## Not the generic CRUD API — and why these are two documents Relentless publishes a second agent-facing document at `{host}/docs/agent`: the generic node/edge CRUD API for an agent's own buildspace. The two are not two views of one API. They are two credentials that cannot reach each other's surface, which is why they are two documents and why merging them would teach you an access model neither credential has. | | This document | `/docs/agent` | | -------------- | -------------------------- | --------------------------------- | | Credential | project-scoped credential | buildspace-scoped agent key | | What it covers | one DECS project | one whole buildspace, every kind | | Vocabulary | the semantic actions above | `/api/nodes`, `/api/edges` | | Refused on | `/api/nodes` | semantic actions, `/api/mcp` | "Refused" is literal, not advisory. Present a project-scoped credential to `/api/nodes` and the answer is *"This endpoint is not accessible with project-scoped credentials."* Present a buildspace agent key to `/api/mcp` and it is refused just as hard. If you hold one and need the other, a human mints it; there is no upgrade path between them. Three more differences, each of which has bitten somebody reading both pages in one sitting: - **Status codes mean different things.** Here, a wrong project scope is `403` and `404` means "this deployment does not have DECS v2 enabled". On the CRUD API, a wrong buildspace is `401` and `404` is an ordinary missing resource. - **Expiry differs**: a buildspace agent key lasts 90 days and is revoked by a timestamp; a project-scoped credential lasts 365 days as a backstop and is really revoked by the membership it derives from. - **A `decision` node kind exists on the CRUD API.** It is a real node kind with its own content shape, and it is *not* how you record a decision. That last one is the trap this section exists for. Writing a decision, a question, a plan or a session note through the CRUD API stores unvalidated content that DECS never sees: it will not be recalled into any session's bootstrap, will not reach a human's question queue, and will not appear in any project's decision record. It is also shaped differently — the CRUD `decision` kind wants all four of what/why/purpose/constraints, while `add.decs.decision` requires only `what`. Decisions, questions, plans and session notes go through the semantic actions above, always. ## When it goes quiet Silence with no error is the designed failure mode — DECS never blocks your work, which means a broken DECS looks exactly like a DECS that has nothing to say. Diagnose it rather than assuming it is fine: - **401 or 403 on any DECS call** — the credential is dead, revoked with the membership it derived from, or scoped to a different project than this repository's `.decs.json`. Ask the human to mint a fresh one. - **`v2.projectScopeId` is null** — the repository declares a v2 identity but was never linked to a project. Nothing will record until a human links it. - **No `.decs.json` found** — this repository was never set up. Offer; do not assume. - **Nothing at all, no errors** — check the catalog fetch. If it returns 200 and DECS still seems absent, the credential and the project are fine and the integration layer (plugin, MCP entry, hooks) is what is missing. Whatever you find, say it once, plainly, and carry on with the actual work. That is the whole contract: DECS is an offer, never a requirement. Generated from catalog 4570900c643912209803cfe4ac6c1693352da815850619b7d3b9ca51b1ab44b6.