Skip to main content
38 routes. Every example runs with LITMUS_URL, LITMUS_TOKEN and LITMUS_ORG (your org tag) set in your shell (see Authentication). A $NAME in a path is an id you read from the listing route on this page; a <field> in a body is a value you supply, and every field the handler reads is shown, so send only the ones you need. Fields are what the handler’s source reads and writes, listed mechanically; they are not a schema.

GET /v0/orgs/{orgtag}/agents

This org’s agents: the connected rows, then the built-in harnesses. Path parameters: orgtag Query parameters the handler or its helper reads: retired Response fields written in the helper the handler answers through: as_of, behind (added to a stored record whose own keys are not in the source)

POST /v0/orgs/{orgtag}/agents

Connect an agent: {kind, name, version?, command | url | repo fields, token_env?, env?, model?, notes?}. Path parameters: orgtag Body fields the handler or its helper reads: adapter, command, egress, env, kind, model, name, notes, run, token_env, url, version Response fields written in the handler: job This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/first

The org’s first agent, written if it has none. Path parameters: orgtag Response fields written in the handler: agent, agents, created, org This call changes state in the org.

GET /v0/orgs/{orgtag}/agents/{aid}

One agent: its versions, the groups it ran, and where its traces are. Path parameters: orgtag, aid Response fields written in the handler: agent, groups, langfuse

PATCH /v0/orgs/{orgtag}/agents/{aid}

Change an agent, or pin a new version of it. Path parameters: orgtag, aid Body fields the handler or its helper reads: adapter, command, egress, env, model, name, notes, ref, run, setup, token_env, url, version Response: JSON: a stored record or a helper’s result, answered as it is, so its keys are not written in the source and none are listed. This call changes state in the org.

DELETE /v0/orgs/{orgtag}/agents/{aid}

Disconnect an agent. Path parameters: orgtag, aid Response fields written in the handler: deleted, kept This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/retire

Retire an agent, or restore one: POST …/agents/{aid}/retire, body {retired: bool, by?}. Path parameters: orgtag, aid Body fields the handler or its helper reads: by, retired Response fields written in the handler: agent, kept This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/probe

Ask the agent one fixture question, and store the shape of its answer. Path parameters: orgtag, aid Body fields the handler or its helper reads: version Response fields written in the handler: agent, job, note, poll, probe, stages This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/smoke

One trial of the agent on the fixture household: the connect step’s smoke. Path parameters: orgtag, aid Body fields the handler or its helper reads: version Response fields written in the handler: accepted_ms, agent, job, note, poll, stages This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/onboard

POST /v0/orgs/{org}/agents/{aid}/onboard — {version?, against?, surface?, tasks?, allow_cannot?, environments?}, and for a surface agent the change to its surface: {description_overrides?, added_tools?, removed_tools?, redeclared_tools?, origin?, by?} — an added tool is {name, description, input_schema, behaviour}, compiled deterministically from its declared behaviour; a redeclared tool is {name, behaviour, description?}, an EXISTING tool whose function is replaced by its declared one (e.g. rows_by_match: rows the world holds, by a fixed query), stamped tools_redeclared and named in the surface diff; origin is {kind: operator_edit|declared|branch, ref?, repo?, sha?}, stored as a field on B’s stamp and the version’s ready row. One job from a connected version to “ready: run it vs the last version on n shared tasks”. Path parameters: orgtag, aid Body fields the handler or its helper reads: added_tools, against, allow_cannot, by, description_overrides, environments, origin, redeclared_tools, removed_tools, surface, tasks, version Response fields written in the helper the handler answers through: against, agent, job, note, poll, stages, version This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/discover

Ask a connected agent version a few tasks against a surface this org serves, and store which operations it used and who answered each. Path parameters: orgtag, aid Body fields the handler or its helper reads: surface, tasks, version Response fields written in the handler: agent, job, note, poll, stages, surface, tasks This call changes state in the org.

GET /v0/orgs/{orgtag}/agents/{aid}/touched-coverage

GET /v0/orgs/{org}/agents/{aid}/touched-coverage?version=&tools=&set=&group= — before any B run: which tools a surface change touches, how many of the set’s tasks call each, which production calls (when the Datadog grammar holds them), and the tasks to generate for the gap, priced. A read: nothing runs and nothing is written; the gap plan’s confirm is POST …/environments/{id}/tasks {count, tool}, once per row. Path parameters: orgtag, aid Response: JSON: a stored record or a helper’s result, answered as it is, so its keys are not written in the source and none are listed.

GET /v0/orgs/{orgtag}/agents/{aid}/discoveries

This agent’s discover runs, newest first. Path parameters: orgtag, aid Response fields written in the handler: agent, discoveries

POST /v0/orgs/{orgtag}/agents/{aid}/primary

Make this agent the org’s primary: POST /v0/orgs/{org}/agents/{aid}/primary, body {by?}. The Agents page’s one “Make primary” control; a sandbox’s Run and the Runner default to it. A built-in harness is not an agent this org connected, so it cannot be made primary. Path parameters: orgtag, aid Body fields the handler or its helper reads: by Response fields written in the handler: primary_agent This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/detect

Read the repository again and probe what it proposes. Path parameters: orgtag, aid Response fields written in the handler: agent, job, poll This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/scan

Scan for new versions of this agent now: POST /v0/orgs/{org}/agents/{aid}/scan, body {paths?, cadence?}. Path parameters: orgtag, aid Body fields the handler or its helper reads: cadence, paths Response fields written in the handler: agent, job, poll, stages This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/server-repo

POST /v0/orgs/{org}/agents/{aid}/server-repo — {url, ref?, paths?, listing?, run?, setup?, upstream_env?}. A surface agent names the repository its MCP server lives in: ref is the base branch (what the served surface A stands for, default main), paths the tool definitions a commit must touch to count, listing a static tools/list file. Read through the org’s Litmus GitHub App installation for the owner (contents: read) — derived here from the org in the path. The base is resolved to a commit once, now; nothing is built or run. Path parameters: orgtag, aid Body fields the handler or its helper reads: listing, paths, ref, run, setup, upstream_env, url Response fields written in the handler: agent This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/server-refs

POST /v0/orgs/{org}/agents/{aid}/server-refs — {ref, behaviours?, by?, supersedes?}. The ref of the server repository — a branch, tag, commit or pull request (refs/pull/<n>/head, pull/<n>) — becomes a surface version: its tool listing is read (serverref.read_change: the served build, else a static listing file, else the tool definitions in its source, else one model call over the diff, tier llm-derived), stored by commit with the fork point’s, the head’s ancestry to the base recorded as merge, diffed from where the branch forked from the base to its head, and applied to A — changed descriptions as overrides, added tools from their declared behaviour, removed tools dropped — through the surface onboard, origin: {kind: branch, ref, repo, sha}. An added tool with no behaviour (the listing’s, or behaviours: {tool: line}) stores the version needs_behaviour and compiles nothing. A head the base already reaches is merged and compiles nothing. supersedes names a declared version this branch replaces: it stays listed, reads “declared from the customer’s description, superseded”, and is no longer makeable main. 202 with the onboard’s job; 200 when there is nothing to ready yet. Path parameters: orgtag, aid Body fields the handler or its helper reads: behaviours, by, ref, supersedes Response fields written in the helper the handler answers through: agent, job, poll, same, surface_version (added to a stored record whose own keys are not in the source) This call changes state in the org.

GET /v0/orgs/{orgtag}/agents/{aid}/server-tools/{sha}

GET /v0/orgs/{org}/agents/{aid}/server-tools/{sha} — the tool definitions read from the server repository at one commit (main for main’s): {sha, reader, count, tools: [{name, description, input_schema, data_source?}]}, as a deterministic reader read them. 404 for a commit no reader read. Path parameters: orgtag, aid, sha Response: JSON: a stored record or a helper’s result, answered as it is, so its keys are not written in the source and none are listed.

POST /v0/orgs/{orgtag}/agents/{aid}/main

POST /v0/orgs/{org}/agents/{aid}/main — {version, by?}. Make a declared version of a surface agent’s tools its MAIN version: the one the next change is applied to and the one the page says is live. version is the agent version the declared row was readied on, or the row’s surface id; base (or the connected tools’ surface id) makes the tools it was connected on main again. The main it replaces stays listed, “was main until ‹date›”. Nothing is re-served and no model is called: the declared version’s tools are already ready. Path parameters: orgtag, aid Body fields the handler or its helper reads: by, version Response fields written in the handler: agent, main, same This call changes state in the org.

GET /v0/orgs/{orgtag}/agents/{aid}/write-path

The agent’s write path by tool: GET /v0/orgs/{org}/agents/{aid}/write-path. The last count’s lines, their coverage (“over B of T batches”), the threshold, the proposals, and the count running now if one is. Reads one small record; never a trace. Path parameters: orgtag, aid Query parameters the handler or its helper reads: audience Response fields written in the helper the handler answers through: accepted, agent, counted, counted_at, job, org, running, threshold, tier (added to a stored record whose own keys are not in the source)

POST /v0/orgs/{orgtag}/agents/{aid}/write-path

Count the agent’s write path by tool now: POST /v0/orgs/{org}/agents/{aid}/write-path. A job (write_path) reads every stored trace batch of the org one at a time and stores the lines the page reads. No model call. 202 with the job to follow; 409 while one is running. Path parameters: orgtag, aid Response fields written in the handler: job, model_calls, poll, stages This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/write-path/accept

Record one proposal as a known failure mode: POST /v0/orgs/{org}/agents/{aid}/write-path/accept, {tool, by}. The mode the last count proposed for tool, stored through the failure-modes route’s own checks (failuremodes.body_of, feedback.prepare) in the name of who confirmed it. No model call. A tool the count did not propose is refused by name; a second accept is a duplicate, not a second mode. The task in the bucket is the next step, and it is the one that calls a model (next). Path parameters: orgtag, aid Body fields the handler or its helper reads: author_member, by, tool, visibility Response fields written in the handler: agent, duplicate, mode, model_calls, next, org, stored, tool This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/versions

Add a version of a repository agent from a ref: POST …/agents/{aid}/versions, body {ref, by?} — or of an http agent by its label: {version, url?, by?}, the endpoint only when it changed. Path parameters: orgtag, aid Body fields the handler or its helper reads: by Response fields written in the handler: agent, version This call changes state in the org.

PATCH /v0/orgs/{orgtag}/agents/{aid}/versions/{version}

Retire a version, or restore one: PATCH …/agents/{aid}/versions/{version}, body {retired: bool, by?}. Path parameters: orgtag, aid, version Body fields the handler or its helper reads: by, retired Response: JSON: a stored record or a helper’s result, answered as it is, so its keys are not written in the source and none are listed. This call changes state in the org.

GET /v0/orgs/{orgtag}/agents/{aid}/versions/{version:path}/changes

GET /v0/orgs/{org}/agents/{aid}/versions/{version}/changes — what a tracked version of the server repository changes, by file, as it was read once and kept on the version record: {version, changes?: {base, head, files, names, areas: {tools, handlers, skills, registration, other}, by_area, statuses, additions, deletions, reader, tier, line}}. version is the version’s name (“tools v3”), its ref or its commit. A version no repository ref made — a declared one, or main — answers with no changes and its line, never an error; a tracked one not read yet says so the same way. File names and counts only: no file’s contents. Path parameters: orgtag, aid, version Response fields written in the helper the handler answers through: changes, version (added to a stored record whose own keys are not in the source)

POST /v0/orgs/{orgtag}/agents/{aid}/versions/{version:path}/changes

POST /v0/orgs/{org}/agents/{aid}/versions/{version}/changes — read the changed-file list between a tracked version’s fork point and its head through the org’s installed GitHub App (GET /repos/{o}/{r}/compare/ {base}...{head}, a token minted for that one repository with contents: read, never returned or logged) and keep it on the version record. Read ONCE: a version already read answers what is kept with same: true. Areas are the declared path table in versionchanges.AREAS; no model call, $0. A repository the installation does not cover is a 409 not_covered; a version no repository ref made answers with no changes and its line, and nothing is written. Path parameters: orgtag, aid, version Response fields written in the helper the handler answers through: changes, version (added to a stored record whose own keys are not in the source) This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/versions/{version:path}/skills

POST /v0/orgs/{org}/agents/{aid}/versions/{version}/skills — {ref, paths?}: register “main’s tools + this version’s skills”. Each listed skill file is read at the commit the version names, through the org’s installed GitHub App (GET /repos/{o}/{r}/contents/{path}?ref= {sha}, a token minted for that one repository with contents: read, never returned or logged), kept as one of the org’s documents, and pinned by sha on a new agent version whose tools are main’s. paths defaults to the skill files the version’s kept changed-file list names. Refused: a path outside a skills/ directory (422 outside_skills), a ref the version does not name (409 ref_not_named), a repository the installation does not cover (409 not_covered); the read answers GET only, so it never writes to git. The same files at the same commit on the same tools answer the arm already kept with same: true. Answers {arm, row} — names, refs, shas and counts; never a file’s text. No model call, $0. Path parameters: orgtag, aid, version Body fields the handler or its helper reads: paths, ref Response fields written in the handler: arm, row, same This call changes state in the org.

POST /v0/orgs/{orgtag}/agents/{aid}/versions/{version:path}/tool-texts

POST /v0/orgs/{org}/agents/{aid}/versions/{version}/tool-texts — {by, dry_run?}: carry a tracked version’s MCP tool texts onto the served API tools their data source names, as a STAND-IN beside a control. From main’s stored source definitions and the version’s (server-tools/{sha}), each MCP tool’s data_source routes are matched to the routes the run’s door recorded for its tools (contract.json); the set is every served tool an MCP tool whose description differs between main and the ref reaches, and each one’s description is the texts of every MCP tool that calls it, sorted by name and prefixed by it — main’s texts for the control, the ref’s for the arm (tooltexts.plan). Unless dry_run, both are compiled through the onboard’s compile (description_overrides, origin {kind: declared, ref, sha}) and re-served on main’s standing environments in one job; each is then a version a re-run moves to (runs/start {group, agent_version: sfv-…}), labelled “main’s tool texts on the run’s tools (stand-in)” and “‹ref›‘s tool texts on the run’s tools (stand-in)”. The same commit pair answers the kept pair with same: true. Refused: a version with no stored source definitions (no_source), a ref that changes no description (no_description_change), texts that reach no served tool (nothing_reached, no_routes). Answers counts and tool NAMES only — {reached, carried, not_carried: {schema, data_source, no_served_route, added, removed}, control, arm} — never a description. No model call, $0. Path parameters: orgtag, aid, version Body fields the handler or its helper reads: by, dry_run Response fields written in the handler: code, error This call changes state in the org.

GET /v0/orgs/{orgtag}/agent-env

The names this org has set, who set each and when — never a value. Path parameters: orgtag Response fields written in the handler: env, org, prefix, tier

PUT /v0/orgs/{orgtag}/agent-env/{name}

Set one value, {value}. Answers the name and who set it, not the value. Path parameters: orgtag, name Body fields the handler or its helper reads: by, value Response fields written in the handler: org, set This call changes state in the org.

DELETE /v0/orgs/{orgtag}/agent-env/{name}

Remove one value. 404 for a name the org never set. Path parameters: orgtag, name Response fields written in the handler: deleted, org This call changes state in the org.

POST /v0/orgs/{orgtag}/github/installations

Record a Litmus GitHub App installation on this org: {installation_id, account_login?}. Path parameters: orgtag Body fields the handler or its helper reads: account_login, by, installation_id, setup_action Response fields written in the handler: github_app This call changes state in the org.

GET /v0/orgs/{orgtag}/github/installation

The installations this org references: {org, installations: [{installation_id, account, account_type}]}. Path parameters: orgtag Response fields written in the handler: installations, org, tier

POST /v0/orgs/{orgtag}/github/installation

Reference, from this org, an installation an org the caller acts for already holds: {installation_id, from_org?}. Path parameters: orgtag Body fields the handler or its helper reads: by, from_org, installation_id Response fields written in the handler: github_app This call changes state in the org.

GET /v0/orgs/{orgtag}/github/repositories

The repositories this org’s Litmus GitHub App installations cover: {org, installations: [{account, installation_id, repositories: [{full_name, clone_url, default_branch, private, pushed_at}], refusal}]}. Path parameters: orgtag Response fields written in the handler: installations, org, tier

GET /v0/orgs/{orgtag}/github/refs

One covered repository’s branches and open pull requests: GET /v0/orgs/{org}/github/refs?repo=owner/name → {org, repo, account, installation_id, branches: [{name, sha}], pulls: [{number, title, head_ref, head_sha, base_ref}], pulls_refusal, refusal}. Path parameters: orgtag Query parameters the handler or its helper reads: repo Response fields written in the handler: org, tier

GET /v0/orgs/{orgtag}/github/unrecorded

Installations of the Litmus GitHub App that GitHub holds and no org has recorded, on the account ?owner= names: {org, owner, unrecorded: [{installation_id, account}]}. Path parameters: orgtag Query parameters the handler or its helper reads: owner Response fields written in the handler: org, owner, refusal, tier, unrecorded