Docs

Amdahl Platform API

v1.0.0

REST API for Amdahl customer intelligence. Two surfaces: **Search** — the synchronous fast-search lane over your customer conversations — and **Agents** — the async automation surface (multi-turn Chat, a reusable agent library, and cron-driven Routines).

Base URL https://app.amdahl.ai. All paths below include the full /api/platform/v1 prefix. Every operation has a Try it runner that calls the live API from your browser.

Need a key? Create one in the console: open console.amdahl.ai, then your workspace then Settings then Developer then Create key. Paste it into any Try it panel below (it is saved in this browser only, never sent anywhere but the API).

Workflows

Workflow orchestration endpoints.

post/api/platform/v1/agents/{session_id}/resume
API keyorBearer JWT

Resume Agent Session

Resume an agent run that is paused on pending user input. Use when replying to an outline approval prompt, a clarification question, or a continue/finish decision. The input payload must match the run's `pending_input_schema`. After a successful resume the run transitions back to running and proceeds from where it paused.

Parameters

session_idpathstring <uuid>required

Request body

application/jsonrequired

inputobjectrequired

The user's resume payload. Must match the run's persisted pending_input_schema.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/agents/{session_id}/cancel
API keyorBearer JWT

Cancel Agent Session

Cancel an in-flight agent run. Use when the user wants to stop a running agent before it finishes, or abandon a run that has gone sideways. Cascades to any sub-agents spawned from this run via agents.start — every live descendant is cancelled atomically. The runner bails at the next iteration boundary after observing the status change. Already-completed runs cannot be canceled. Pass a reason to record WHY the run was aborted in the audit trail.

Parameters

session_idpathstring <uuid>required

Request body

application/json

reasonstringoptional

Optional operator note describing why the run was canceled.

max length 500

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/agents
API keyorBearer JWT

List Workspace Agents

List the workspace agent roster - Amdahl-shipped library agents merged with tenant-authored ones - as lean rows of slug, name, description, and provenance. Read when choosing which named agent should handle a task or rendering the agent directory. Library entries are code-defined and locked; tenant rows carry their creation time.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/agents
API keyorBearer JWT

Create Workspace Agent

Save a new tenant-authored agent: a named, reusable prompt the workspace can dispatch later by its stable kebab-case slug. Use when a user wants to capture a custom instruction set as a workspace agent. Rejects a slug that shadows an Amdahl library agent (those ship in code and cannot be replaced) and surfaces tenant slug collisions as a typed conflict.

Request body

application/jsonrequired

slugstringoptional

Optional stable kebab-case dispatch key (lowercase letters, digits, single dashes). Omitted: derived from the name and uniquified automatically.

min length 2max length 64
namestringrequired

Display name.

min length 1max length 120
descriptionstringoptional

Optional one-line blurb for the agent directory.

max length 2000
tool_blocklistarray of stringoptional

Operation ids to subtract from this agent tool kit at run time (all kit tools are on by default; empty list = no restriction). Runner-inline tools are refused.

promptstringrequired

The prompt the agent runs with.

min length 1

Responses

201Created
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/agents/{id}
API keyorBearer JWT

Get Agent By Id Or Slug

Fetch one named agent by slug or id, including the full prompt text it runs with. Resolves the Amdahl code library first, then falls back to the tenant row. Read when inspecting exactly what instructions an agent carries before dispatching, editing, or duplicating it. Returns null for another tenant or a missing id.

Parameters

idpathstringrequired

UUID or slug of the agent to read.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
patch/api/platform/v1/agents/{id}
API keyorBearer JWT

Update Workspace Agent

Revise a tenant-authored agent's name, description, or prompt in place, keeping its slug stable. Call when refining how a saved agent behaves after seeing its output. Amdahl library agents are code-defined and immutable, so edits targeting one are refused with a locked error rather than silently ignored.

Parameters

idpathstringrequired

UUID or slug of the agent to patch.

Request body

application/json

namestringoptional

New display name.

min length 1max length 120
descriptionstringoptional

New directory blurb.

max length 2000
promptstringoptional

New prompt body.

min length 1
tool_blocklistarray of stringoptional

Operation ids to subtract from this agent tool kit at run time (all kit tools are on by default; empty list = no restriction). Runner-inline tools are refused.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
delete/api/platform/v1/agents/{id}
API keyorBearer JWT

Archive Workspace Agent

Retire a tenant-authored agent by soft-archiving it out of the roster; the row is retained and nothing is destroyed. Use when the workspace no longer dispatches a saved agent. Archived agents disappear from listings immediately, while Amdahl library agents cannot be archived at all - they are code-defined and always available.

Parameters

idpathstringrequired

UUID or slug of the agent to archive.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/agents/usage
API keyorBearer JWT

Get Build Usage

Workspace rollups of recent agent and routine activity over a fixed 30-day window: per-agent and per-routine run counts (7d / 30d), last run pointers, schedule counts, and workspace totals. Read when rendering the Agents & Routines page so operators can see which specialists and schedules are doing anything without inspecting each chat.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/routines
API keyorBearer JWT

List Routines

List the workspace Routines, newest first: each entry carries the prompt, cadence (cron + timezone), agent pin, per-fire config, and last/next fire bookkeeping. Read when rendering the Routines page, checking what refreshes on a schedule, or picking one to update or fire now. Filter by enabled; paginate via limit + offset.

Parameters

enabledquerybooleanoptional

Filter by enabled state. As a query param, accepts ONLY the exact strings "true" or "false"; any other value (or omitted) applies no filter.

limitqueryintegeroptional
offsetqueryintegeroptional

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/routines
API keyorBearer JWT

Create Routine

Create a Routine: a cron that fires a Chat each occurrence, running one Master agent turn in a fresh named Chat. Use when the user asks for a standing refresh or a recurring investigation. Provide name, prompt, and cron (plus optional timezone and per-fire config like write_outputs or an agents roster); the fire never pauses on a human and each occurrence opens a new Chat.

Request body

application/jsonrequired

namestringrequired

Human label. Each fired Chat is named "{name} — {date}".

promptstringrequired

The Chat input every fire starts the Master turn with.

cronstringrequired

Cron expression (e.g. "0 9 * * 1"). Validated before the row is stored.

timezonestringoptional

IANA timezone the cron evaluates in. Defaults to UTC.

agentstringoptional

LEGACY single-agent pin the Master turn runs as (library slug/uuid or workspace agent id/slug). Prefer config.agents; passing both rejects.

configobjectoptional

Per-fire Chat config. on_question is always none (headless); write_outputs defaults true for routines; agents picks the roster ("all", one pin, or a delegate allowlist).

depthstringoptional
quickstandarddeep
agentsanyoptional

Agents the routine employs: "all" for unrestricted delegation, one ref to run AS that agent (pin), or several refs to restrict delegation to that roster.

actions_allowedarray of stringoptional

Outbound actions each fired run may invoke. Absent = ALL cataloged actions (default ON); pass a list to narrow, [] to disable.

write_outputsbooleanoptional

Allow living-doc commits from fired runs. Default true for routines.

write_memorybooleanoptional

Allow long-term memory commits from fired runs. Default false.

external_searchbooleanoptional

Allow market fan-outs (external_search.execute in the kit). Default false.

include_divergencebooleanoptional

Fuse the divergence map on external_search.execute (else evidence-only). Default false.

enabledbooleanoptional

Whether the routine fires. Defaults to true.

Responses

201Created
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/routines/{id}
API keyorBearer JWT

Get Routine

Fetch one Routine in full: prompt, cadence, agent roster, per-fire config, enabled state, and the last fire pointers (Chat + run ids). Read when opening a routine detail view or before patching one. Unknown and cross-workspace ids return null.

Parameters

idpathstringrequired

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
patch/api/platform/v1/routines/{id}
API keyorBearer JWT

Update Routine

Patch an existing Routine: rename it, change its prompt or cadence, re-pin the agent, adjust per-fire config, or enable/disable it. Use when tuning a standing scheduled ask without recreating it. Only the supplied fields change; a cadence change is re-validated first and takes effect on the next scheduler tick.

Parameters

idpathstringrequired

The routine id.

Request body

application/json

namestringoptional

New human label.

promptstringoptional

New Chat input for future fires.

cronstringoptional

New cron expression (validated before storing).

timezonestringoptional

New IANA timezone.

agentstring | nulloptional

LEGACY single-agent pin, or null to clear back to the plain Master. Prefer config.agents; passing both rejects.

configobjectoptional

Replacement per-fire config (replaces the whole object, including the agents roster).

depthstringoptional
quickstandarddeep
agentsanyoptional

Agents the routine employs: "all" for unrestricted delegation, one ref to run AS that agent (pin), or several refs to restrict delegation to that roster.

actions_allowedarray of stringoptional

Outbound actions each fired run may invoke. Absent = ALL cataloged actions (default ON); pass a list to narrow, [] to disable.

write_outputsbooleanoptional

Allow living-doc commits from fired runs. Default true for routines.

write_memorybooleanoptional

Allow long-term memory commits from fired runs. Default false.

external_searchbooleanoptional

Allow market fan-outs (external_search.execute in the kit). Default false.

include_divergencebooleanoptional

Fuse the divergence map on external_search.execute (else evidence-only). Default false.

enabledbooleanoptional

Enable or disable firing.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
delete/api/platform/v1/routines/{id}
API keyorBearer JWT

Delete Routine

Permanently remove a Routine so its cadence stops firing. Use when the user no longer wants the standing scheduled ask. Deletion affects only future fires - Chats and documents earlier fires produced are untouched. Prefer disabling (routines.update enabled=false) when the user may want it back.

Parameters

idpathstringrequired

The routine id to delete.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/routines/{id}/run-now
API keyorBearer JWT

Run Routine Now

Fire one Routine immediately, off-cadence: opens a fresh Chat and starts the Master turn exactly as the cron would. Use when the user wants the standing refresh right now instead of waiting for the next occurrence. Returns the Chat and run handles (stream/read/resume URLs) so the fire can be watched like any Chat.

Parameters

idpathstringrequired

The routine id to fire.

Request body

application/json

object

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional

Conversations

post/api/platform/v1/chat
API keyorBearer JWT

Chat

Ask the workspace anything: opens or continues a named Chat and enqueues one Master agent turn. Use when starting an investigation over company data, memory, and connected sources. Always returns handles immediately (chat_id, run_id, stream/read/resume URLs) - subscribe to stream_url or poll read_url with wait_ms for the answer; never blocks.

Request body

application/jsonrequired

inputstringrequired

The ask, in plain language. Becomes the Master turn user message.

min length 1max length 32000
chat_idstring <uuid>optional

Continue an existing Chat. Omit to open a new one.

namestringoptional

Name for a NEW Chat. Omitted: auto-titled from the input.

min length 1max length 120
agentstringoptional

Optional agent pin: an Amdahl library slug/uuid or workspace agent id/slug the Master turn runs as (Master privileges; the agent prompt is the specialization).

max length 200
configobjectoptional

The only knobs. No model, temperature, or stream fields exist.

depthstringoptional
quickstandarddeep
actions_allowedarray of stringoptional

Outbound actions this run may invoke. Absent = ALL cataloged actions (default ON); pass a list to narrow, [] to disable.

write_outputsbooleanoptional

Allow living-doc commits. Default false.

write_memorybooleanoptional

Allow long-term memory commits. Default false on API keys.

on_questionstringoptional

ask_a_human behavior: pause (interactive), auto (default), none (headless).

pauseautonone
external_searchbooleanoptional

Allow market fan-outs (external_search.execute stays in the kit). Default false; deep depth forces true.

include_divergencebooleanoptional

Fuse the divergence map on external_search.execute (else mode:evidence). Default false; deep depth forces true.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/chats
API keyorBearer JWT

List Chats

List Chats for this workspace, newest activity first. Read when picking a Chat to continue, rendering a recents rail, or reviewing what one agent or routine has been doing. Each entry is a lean snapshot (name, status, turn count, last activity, and how it was triggered); scope by agent_ref or routine_id, filter by status, page via limit and offset.

Parameters

statusquerystringoptional
agent_refquerystringoptional

Keep only Chats this agent drove (slug or uuid — both forms of the same agent match).

routine_idquerystringoptional

Keep only Chats this routine fired.

limitqueryintegeroptional
offsetqueryintegeroptional

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/chats/{id}
API keyorBearer JWT

Get Chat

Fetch one Chat snapshot: name, status, its runs (with read handles), which runs are still in flight, and any pending human asks with their resume URLs. Read when rendering a Chat view, deciding whether to continue it, or surfacing an awaiting question to the human. Returns null for unknown or cross-workspace ids.

Parameters

idpathstringrequired

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
patch/api/platform/v1/chats/{id}
API keyorBearer JWT

Rename Chat

Rename one Chat so the thread is findable later. Use when a chat was auto-titled from its first ask and deserves a human name, or when its focus shifted. Renames the underlying conversation title in place; runs, substrate, and handles are untouched. Returns the updated chat snapshot.

Parameters

idpathstring <uuid>required

Chat UUID.

Request body

application/jsonrequired

namestringrequired

The new chat name.

min length 1max length 120

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/chats/{id}/runs/{run_id}
API keyorBearer JWT

Get Chat Run

Read one Chat run snapshot: status, pause payload when awaiting input, the answer envelope (answer_text plus the ordered content_blocks with query and snapshot data), answered asks, and usage. Read when polling a started Chat for its result; pass wait_ms (max 30000) to long-poll until the run settles instead of tight-looping. Pass include=events to also get the persisted activity trace for transcript replay.

Parameters

idpathstringrequired

Chat (conversation) UUID.

run_idpathstringrequired

Run (turn) UUID from the START response.

wait_msqueryintegeroptional

Optional long-poll budget in ms; hard-capped at 30000.

includequerystringoptional

Optional: 'events' includes the persisted activity trace (parent + sub-agent tool calls, capped) so a reloaded transcript can replay what the run did.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/chat/preferences
API keyorBearer JWT

Get Chat Preferences

Fetch the calling user's saved Chat settings for this workspace: their default run-config knobs (depth, on_question, write_outputs/memory, external_search, include_divergence, actions_allowed) and their agent block list. Read when opening the Chat settings surface to seed its controls. Returns defaults when nothing is saved yet.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
patch/api/platform/v1/chat/preferences
API keyorBearer JWT

Update Chat Preferences

Save the calling user's Chat settings for this workspace: their default run-config knobs and/or their agent block list (the agents the Master may not delegate to). Use when the user changes a control in the Chat settings surface. A top-level PATCH — only the keys you send change; the block list applies to new Chat turns server-side.

Request body

application/json

run_configobjectoptional

Default Chat run knobs. Replaces the stored run_config wholesale when sent.

depthstringoptional
quickstandarddeep
actions_allowedarray of stringoptional
write_outputsbooleanoptional
write_memorybooleanoptional
on_questionstringoptional
pauseautonone
external_searchbooleanoptional
include_divergencebooleanoptional
blocked_agentsarray of stringoptional

Agent slugs / refs the Master may NOT delegate to for this user. Empty = every agent usable.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional

Data

Data exploration - SQL queries, hybrid search, and ML clusters.

post/api/platform/v1/search/query
API keyorBearer JWT

Routed Warehouse Search

One routed door over tenant warehouse data: each ask lands on typed filters, an NL-to-SQL pass, or vector similarity. Use when you hold a plain question OR typed predicates and want the cheapest lane picked automatically (force one via mode). Returns the lane, rows, any compiled SQL, and retry_guidance naming the exact params to re-send when part of a multi-part ask went unanswered. Act on retry_guidance instead of giving up. Lanes read different stores at different grains — read corpus.

Request body

application/json

querystringoptional

Free-text ask. Meaning-shaped wording ("what do customers say about…") routes to the semantic lane; other questions route to the NL-to-SQL fuzzy lane.

max length 2000
max_subqueriesintegeroptional

How many independent sub-questions a multi-part ask may fan out into. Default 3; up to 5 synchronously and 12 with async:true. RAISE THIS when a reply comes back with retry_guidance.action = "raise_max_subqueries" — it means parts of your question were cut by this cap, and retry_guidance.suggested_params carries the value to use.

min 1max 12
asyncbooleanoptional

Run as a background job instead of blocking. Returns {job:{job_id,status}} straight away; collect it by calling this verb again with that job_id and no query. USE THIS when a reply comes back with retry_guidance.action = "run_async" — the synchronous path is bounded at ~15s and your ask needs longer, and the async path also allows a higher max_subqueries. Prefer it for any deliberately broad, multi-part question.

job_idstringoptional

Collect a job started with async:true. Send this ALONE (no query). While status is "queued"/"running", poll again; on "complete" the full envelope is on detail.

modestringoptional

Lane override. Default auto: filters-with-no-query → filter; meaning-shaped query → semantic; else fuzzy. Lanes read DIFFERENT stores at different grains — read `corpus` on the response to see which one answered.

autofilterfuzzysemantic
surfacestringoptional

Warehouse surface for the filter lane. Default interactions. Ignored by the fuzzy and semantic lanes, which report it back in corpus.ignored_params when you pass it.

interactionsdealsdeal_qualification
audiencestringoptional

Who counts as the voice you want. Default "all". Use "customer_voice" to keep only genuine customer / prospect speech and drop investor, advisor, media, partner, vendor and competitor chatter that merely shares an account record — while STILL keeping a real buyer on such an account (someone on a live opportunity, or a scored champion / economic buyer). This applies the platform's own canonical rule server-side; it is a disjunction you cannot express with `filters`, which are ANDed. interactions only.

allcustomer_voice
hydratebooleanoptional

Semantic lane only. Semantic matches carry a truncated preview and no labels, so they cannot be quoted or attributed. Set true to bridge each match back to its full warehouse row — full `content` plus company, speaker title, pushback and buyer-signal columns. One row per match, containing the matched utterance, so a hit is citable. SPEAKER comes from the ATOMIC utterance that matched, not from the turn stamp: read speaker_attribution on each row. "utterance" = verified from the atomic source. "ambiguous" = two matched utterances share this row and disagree on speaker, so the speaker fields are NULL and nobody is named — check turn_speakers for who is in play. "turn" = the atomic source had no row, so the fields are the turn's FIRST member and are NOT verified. Separately, speaker_ambiguous says the row's TEXT spans more than one speaker (13.58% of turns on the tenant measured 2026-08-15) — a row can be cleanly attributed AND span two voices, so quoting the whole content as one person is still wrong there. Both fields ship on every turn-grain row including the clean ones; corpus.speaker_ambiguous_rows / corpus.speaker_unattributable_rows are the rates. speaker_ambiguous_source says where that verdict came from: "stamped" = read from the column the pipeline writes on the turn itself, "overlay" = reconstructed at read time because the pipeline recorded none for that turn. A missing record is NOT "one speaker" — permanently-excluded interactions never get one — so an unrecorded turn falls back rather than being reported unambiguous, and a "stamped" row also carries speaker_count. corpus.speaker_stamped_rows / corpus.speaker_fallback_rows are the split. Stakeholder columns (role_level, is_champion, is_economic_buyer, champion_score, inferred_persona) are derived from the turn stamp, so they are NULLED when the row is re-attributed to a different speaker rather than left describing someone else. Slower — two reads. Check corpus.hydrated_grain: "turn" is that row-per-match answer; "call" means the turn lookup failed and the rows are arbitrary turns from the right conversations (context, not the matches; also flagged corpus.degraded). Matches whose utterance belongs to no turn have no warehouse row and are counted in corpus.unresolved_matches; matches sharing one turn are corpus.collapsed_matches. Read those two directly rather than inferring a gap from a match_count/row_count delta — corpus.match_count is how many nearest neighbours the lane pulled and is BOUNDED BY limit, not a count of how many things genuinely matched. Caps at 200 distinct ids, reported as corpus.truncated.

coveragebooleanoptional

Opt into gap detection on corpus.coverage. Every response ALREADY carries corpus.coverage with max_timestamp / min_timestamp and an age histogram, computed free from the rows returned. This flag adds `gaps`: windows where the corpus HELD rows and this result set had none — the "your evidence has a hole in it" signal, as opposed to the ordinary quiet periods a plain empty-bucket scan would flag. Costs one extra bucketed read, so it is off by default. Read coverage.basis first: "matched_set" means the numbers describe your whole match set, "returned_rows" means they describe a truncated slice, and "unavailable" means coverage could not be measured — never read that as zero.

filtersarray of objectoptional

Typed predicates (ANDed — there is no OR; for the customer-voice disjunction use `audience`). Semantic mode supports only company_id / occurred_at / speaker_type, and cannot apply any of them on its theme-index fallback — check corpus.filters_applied. The filter lane supports every field the catalog advertises.

array items

fieldstringrequired

A field from search_field://list.

opstringrequired
eqneqinnot_incontainsgtgteltltebetweenis_nullnot_null
valueanyoptional

Scalar for eq/neq/gt/gte/lt/lte/contains; array for in/not_in; [low, high] for between; omitted for is_null/not_null.

order_byobjectoptional

Filter lane: order by a vocabulary field or a metric alias (e.g. "count").

fieldstringrequired
dirstringrequired
ascdesc
limitintegeroptional

Row / match cap; hard max 1000. Default is lane-dependent: 100 on the filter and semantic lanes, 50 on the fuzzy lane (where an unforced plain-language question usually lands), so pass it explicitly when the row count matters.

min 1max 1000
group_byarray of stringoptional

Filter lane: group fields (requires at least one metric).

metricsarray of objectoptional

Filter lane: aggregations (sum/avg need a numeric field).

array items

fnstringrequired
countcount_distinctsumavgminmax
fieldstringoptional

Required for every fn except count.

Responses

200OK
dataobjectrequired
successbooleanrequired
mode_ranstringoptional
resultsarray of anyoptional
compiledobjectoptional
freshnessobjectoptional
corpusobjectoptional
timingobjectoptional
cachedbooleanoptional
detailobjectoptional
jobobjectoptional
errorobjectoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/search/fields
API keyorBearer JWT

Search Filter Fields

Read when composing typed predicates for the routed search verb: the per-surface field catalog (interactions, deals, deal_qualification) listing each field with its type, description, and the comparison operators it admits. Derived live from the warehouse schema catalog - exactly what the filter compiler validates against, so it can never drift from the accepted vocabulary.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional

Observability

Audit logs and execution telemetry.

post/api/platform/v1/evals/run
API keyorBearer JWT

Run Eval

Grade content against your workspace data and get a run id to poll. Use when scoring a prompt or a drafted message: pass inputs (prompt and/or message, plus optional audience, account, mode=rewrite|advisory|gate) — a blinded judge scores relevant positioning, grounding, verified specifics, differentiation and CTA clarity against real customer quotes, and the prompt is scored on its own separate rubric. Returns the handle (eval-run://<id>) plus a console_url to give the user.

Request body

application/json

evalstringoptional

Eval slug or id. Default 'prompt-and-message-eval'. Discover options + their input fields via eval://list.

inputsobjectoptional

Run inputs for the eval's declared fields. prompt-and-message-eval requires at least one of prompt / message, and also accepts audience (a seniority or title to scope the cohort), account (the company it is going to — retrieves what THAT account said), and mode: rewrite (the default, a full improved prompt and message), advisory (anchored suggestions against what you wrote), or gate (grade ONLY what you sent and stop — read the verdict from eval-run://<id>/gate). Read the exact schema from eval://<slug>.

reusestringoptional

cached (default) reuses an active run for the same target (fingerprint); force always starts a fresh run.

cachedforce
evidence_from_runstringoptional

Run id whose frozen customer quotes this run should be graded against, instead of retrieving fresh ones. Use to A/B two drafts: without it each run retrieves its own evidence, so the score difference mixes your edit with a different set of quotes. The source run must be in this workspace and have reached retrieval; the report states the pin and how old that evidence is.

include_externalbooleanoptional

Add public web/market evidence to the grade (default false). One web fan-out runs and its snippets join the pool tagged EXTERNAL — the tier that backs market claims ("analysts report"), never customer voice. Needs the external_search:execute scope (refused without it, never silently dropped) and cannot combine with a pinned run — a pin holds the evidence frozen, and its pool already carries any external quotes it was graded on.

external_capintegeroptional

How many external quotes to retrieve when include_external is set. Clamped to 1..25; default 15. The ack echoes the clamped value as external.cap.

candidate_from_runstringoptional

Run id whose improved version this run should GRADE, instead of writing a new one. Use to re-run the judge over fixed text — the run makes no generate call, so a score difference between two such runs is the judge, not the writer. Pass reuse=force when sampling: two identical pinned requests share one content address, so on the default reuse=cached the second is served the first run and an N-sample spread reads as zero. Also pins that run's quotes (the citations in the frozen text address them), so pass the same id to evidence_from_run or omit it. Refused if this run submits different copy or a different mode than the pinned candidate was written for.

scopeobjectoptional

Narrow WHICH conversations the grade speaks for. Use when the verdict is about a cohort rather than your whole corpus. filters are AND-joined over interactions (utterance grain), deals or deal_qualification (account grain - these resolve to the matching accounts and scope the conversations to them). A slice below the evidence floors (3 speakers, 25 utterances, 2 companies) abstains to whole-corpus grading unless allow_thin_evidence, which grades it anyway and flags below_floors.

filtersarray of objectoptional

Typed predicates, AND-joined. At most 25. Read the filterable fields and their operators per surface from the search field catalog.

array items

surfacestringoptional
interactionsdealsdeal_qualification
fieldstringrequired
opstringrequired
eqneqinnot_incontainsgtgteltltebetweenis_nullnot_null
valueanyoptional
audiencestringoptional

customer_voice restricts the slice to buyer speech; all (default) leaves it unrestricted.

allcustomer_voice
allow_thin_evidencebooleanoptional

Grade the slice even when it falls below the evidence floors, instead of abstaining to the whole corpus. The report carries the real counts and below_floors: true.

Responses

200OK
dataobjectrequired
successbooleanrequired
run_idstringoptional
reusedbooleanoptional
statusstringoptional
eval_slugstringoptional
eval_versionstringoptional
resourcestringoptional
pollobjectoptional

How to read the verdict back: action (status), run_id, resource, report_resource, and wait_ms_max - the largest long-poll budget the read honours, so a caller blocks once instead of looping. The run is queued when this returns; it is not the answer yet.

console_urlstringoptional

Link to this run's report in the workspace console. Give it to the user verbatim so they can open the run — run_id and resource are machine addresses they cannot follow. Works immediately (it shows the live grading trail, then the report). Absent when it could not be resolved; never invent one.

errorobjectoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/evals
API keyorBearer JWT

List Evals

List every eval available to this workspace (prompt-and-message-eval, plus any you authored). Use when choosing which grader to run or rendering an eval picker. Returns slug, name, version, description, input_schema, and case count per eval; fetch eval://<slug> for the full cases + graders.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/evals
API keyorBearer JWT

Create Eval

Create a custom eval — a configured grading pipeline (declared input fields + cases + graders) stored for your workspace. Use when the built-in graders don't fit and you want your own scored report card. Pass slug, name, input_schema, and cases; the whole definition is validated and you get back the new eval's slug + id, or a structured validation_failed with the exact field errors. Built-in slugs are reserved.

Request body

application/jsonrequired

slugstringrequired

kebab-case identifier, unique in your workspace.

namestringrequired
descriptionstringoptional
versionstringoptional

semver, default 1.0.0.

input_schemaobjectoptional

Declared run-input fields ({ fields: [...] }).

casesarray of objectrequired

Cases: each a subject + its graders.

reliabilityobjectoptional

Required for any grader that reports a MAGNITUDE (judge / evidence_judge / improvement_loop): the measured flip rate and the floor a reported lift must clear. Validation refuses without it, so declare it rather than discovering the refusal.

Responses

201Created
dataobjectrequired
successbooleanrequired
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/evals/{slug}
API keyorBearer JWT

Get Eval

Fetch one eval by slug or id, with its input_schema and full cases — each case subject (a provided input field or a generated target) and the graders (rule checks, system-of-record anchors, judge and evidence-judge rubrics) applied to it. Use when building a run form or inspecting what a grader measures. Returns null for an unknown id.

Parameters

slugpathstringrequired

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
patch/api/platform/v1/evals/{slug}
API keyorBearer JWT

Update Eval

Revise one of your workspace's authored evals in place. Use when tuning a custom grader's rubric, thresholds, input fields, or cases. Pass the slug plus the fields to change; the merged definition is re-validated before it is stored, returning the slug + version or a structured validation error. Built-in evals cannot be edited.

Parameters

slugpathstringrequired

The authored eval to revise.

Request body

application/json

namestringoptional
descriptionstringoptional
versionstringoptional
input_schemaobjectoptional
casesarray of objectoptional
reliabilityobjectoptional

Required for any grader that reports a MAGNITUDE (judge / evidence_judge / improvement_loop): the measured flip rate and the floor a reported lift must clear. Validation refuses without it, so declare it rather than discovering the refusal.

Responses

200OK
dataobjectrequired
successbooleanrequired
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
delete/api/platform/v1/evals/{slug}
API keyorBearer JWT

Delete Eval

Archive one of your workspace's authored evals so it no longer lists or runs. Use when retiring a custom grader you no longer need; the slug frees up for re-use and a soft archive keeps the audit trail. Pass the slug. Built-in evals cannot be archived. Returns whether a matching eval was found and archived.

Parameters

slugpathstringrequired

Responses

200OK
dataobjectrequired
successbooleanrequired
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/evals/validate
API keyorBearer JWT

Validate Eval

Dry-run validate a custom eval definition without storing it. Use when building an eval in a form and you want author-time feedback before saving: it runs the same structural checks as creating one (input-schema shape, subject-to-input-field integrity, per-grader config) and returns valid plus a flat list of path + message errors. Never writes anything.

Request body

application/jsonrequired

slugstringrequired
namestringrequired
descriptionstringoptional
versionstringoptional
input_schemaobjectoptional
casesarray of objectrequired
reliabilityobjectoptional

Required for any grader that reports a MAGNITUDE (judge / evidence_judge / improvement_loop): the measured flip rate and the floor a reported lift must clear. Validation refuses without it, so declare it rather than discovering the refusal.

Responses

200OK
dataobjectrequired
validbooleanrequired
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/evals/export
API keyorBearer JWT

Export Eval Runs

Pull this workspace's graded eval runs as flat rows for analysis elsewhere. Use when you need many runs at once rather than one verdict: filter by eval, version, date range, status and verdict, and read back a row per run carrying the score alongside the fields that qualify it. Pass count_only to learn how many runs match — and how many instrument versions they span — before pulling them.

Request body

application/json

evalstringoptional

Eval slug or id. Default 'prompt-and-message-eval'. Required in effect — columns and versions are per-eval, so one export covers one eval.

eval_versionsarray of stringoptional

Restrict to these eval_version values. Omit for every version, but read the version spread on the count first: scores from different versions are produced by different instruments and are not comparable.

fromstringoptional

ISO-8601 lower bound on created_at (inclusive).

tostringoptional

ISO-8601 upper bound on created_at (exclusive).

statusesarray of stringoptional

Restrict to these run statuses. Omit for every status.

verdictsarray of stringoptional

Restrict to these verdict buckets. Omit for every bucket. `ungraded` is a pseudo-bucket for runs carrying no verdict at all - the ones whose overall_score cell is empty - so you can isolate or exclude them; it is not a value any run stores.

count_onlybooleanoptional

Return only the count block (total, cap, version spread, date range) without the rows. Cheap enough to call on every filter change.

redact_quotesbooleanoptional

Blank the verbatim customer quotes in the exported verdict. Affects the raw JSONL download only; the flat rows never carry quote text.

allow_truncationbooleanoptional

Proceed when more than 5000 runs match, taking the most recent 5000. Without it an over-cap response is refused rather than silently cut. The .csv / .jsonl file downloads stream and have no cap, so they never need this.

limitnumberoptional

Take at most this many runs, most recent first (max 5000 here). A deliberate top-N, not a truncation: it satisfies the cap on its own, so a limited call is never refused for matching a larger set.

Responses

200OK
dataobjectrequired
successbooleanrequired
eval_slugstringoptional
countobjectoptional

total, truncated, max_rows, versions (distinct eval_version values in the set), first_run_at and last_run_at. Read `versions` before pooling: more than one means the rows were scored by more than one instrument.

rowsarray of anyoptional

One flat row per run. Every score ships with the fields that qualify it — overall_score with applicable, lift with lift_reportable, the submitted score with input_simulated. A null score is an empty value, never zero.

scopestringoptional

self (your own runs) or workspace (every run; workspace admins only).

errorobjectoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}/feedback
API keyorBearer JWT

Get Eval Run Feedback

Fetch what was reported about one run after the fact: whether its recommendation was applied, how each writer knows, and whether the server could confirm it. Read when deciding whether a past recommendation already landed, or before reporting one as unused. verified is three-state — false means checked and absent, null means nothing checked, and the two are different answers.

Parameters

idpathstringrequired

Responses

200OK
dataobjectrequired
statusstringrequired

The RUN status, mirrored at the root so `data.status` resolves here as it does on every other eval read. The terminal success value is `complete` — never `completed`. It also reads meaningfully here: feedback on a run still `running` is about a recommendation that does not exist yet.

queuedrunningcompletefailedcanceled
run_idstringrequired
feedbackarray of objectrequired

One entry per (actor, subject). An actor re-reporting on the same subject replaces their earlier entry; two actors disagreeing appear as two entries, on purpose.

summaryobjectrequired

Tallies only — no rate. A ratio over the handful of rows one run collects would be arithmetic on a denominator of two; the rate lives on eval://<slug>/adoption, where it has a population and an abstain floor.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
post/api/platform/v1/eval-runs/{id}/feedback
API keyorBearer JWT

Record Eval Feedback

Report what happened AFTER an eval run — whether its recommendation was applied, and how you know. Call when you have acted on a report: rewritten a prompt, filed the improved copy, or decided against it. Requires evidence (did_it_myself | reported_to_me | inferred); report only what you observed, never what you assume a person did. Pass applied_to and the server checks the target actually contains it.

Parameters

idpathstringrequired

Alias for eval_run_id, carrying the REST path segment. Pass eval_run_id; this exists so POST /eval-runs/:id/feedback resolves.

Request body

application/jsonrequired

eval_run_idstringoptional

The run this feedback is about.

outcomestringrequired

What happened to the recommendation. `unsure` is a real answer and is excluded from both halves of any adoption rate — prefer it to guessing.

usedused_with_editsnot_usedunsure
evidencestringrequired

How you know. `did_it_myself` = you performed the action in this session (the only value that can be verified). `reported_to_me` = a person told you. `inferred` = you concluded it; honest, but excluded from published rates. Never claim first-hand knowledge of something a person did outside your session.

did_it_myselfreported_to_meinferred
subject_keystringoptional

What the feedback is about. Omit (or '__run__') for the run as a whole; otherwise a stable key naming one recommendation, so the same recommendation across runs can be counted together.

what_happenedstringoptional

Free text, unconstrained. Say what you actually did, or why the recommendation was not usable — the reason is worth more than the verdict.

applied_toobjectoptional

Where it was applied, e.g. { "kind": "agent", "id": "<uuid>" }. Recognised kinds (agent, routine, knowledge_doc) are dereferenced and checked; anything else is stored unverified rather than rejected.

Responses

200OK
dataobjectrequired
successbooleanrequired
feedback_idstringoptional
createdbooleanoptional

False when this replaced your earlier verdict on the same subject.

verifiedboolean | nulloptional

Three-state. true = the server found the recommendation in applied_to. false = it checked and it is absent. null = nothing was checked. null and false are different answers and must not be collapsed.

verification_notestring | nulloptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/evals/{slug}/kpi
API keyorBearer JWT

Get Eval KPI

Fetch the score trend for one eval as a time series over its completed runs: mean submitted-side score per day/week/month, the improved-side ceiling, refusal rate, and the current-vs-prior-window delta. Read when reporting whether writing quality is improving over time. The trend tracks the grade of what callers SUBMITTED, read from verdict.headline so it means one thing across an eval_version bump; windows under 3 scored runs abstain with a named reason rather than assert a mean.

Parameters

slugpathstringrequired
window_daysqueryintegeroptional

Trailing window to aggregate (default 90, clamped 7-365).

granularityquerystringoptional

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/evals/{slug}/adoption
API keyorBearer JWT

Get Eval Adoption

Fetch whether this eval changed anything: how many runs produced a recommendation, how many were reported on, how many were applied, and how often the server could confirm it. Read when asked whether an eval is worth running, or alongside the KPI — a rising score with no adoption means callers improved on their own. Every count states its denominator; the rate abstains rather than assert one on a thin window.

Parameters

slugpathstringrequired
window_daysqueryintegeroptional

Trailing window (default 90, clamped 7-365).

Responses

200OK
dataobjectrequired
adoptionobjectrequired

Counts, then the rate. `runs_completed` >= `runs_eligible` (refusals and gate-mode runs recommended nothing) >= `runs_with_signal` (someone reported) >= `runs_adopted`. `adoption_rate` is runs_adopted / runs_with_signal, or null with an `abstain_reason` — an abstain (`thin_window`, `no_signal`, `no_eligible_runs`) is never a zero. `counted_evidence` names which evidence values the rate counted; `inferred` is never one of them.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs
API keyorBearer JWT

List Eval Runs

List this workspace eval runs, newest first, filterable by eval_slug and status (queued|running|complete|failed|canceled). Use when rendering an eval run history or checking whether a report card has finished. Returns lean rows; fetch eval_run://<id> for the full verdict.

Parameters

eval_slugquerystringoptional
statusquerystringoptional
limitqueryintegeroptional
offsetqueryintegeroptional
includequerystringoptional

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}
API keyorBearer JWT

Get Eval Run

Fetch one eval run by id: its status and, once complete, the verdict — verdict.headline carries the grade of the copy the caller SUBMITTED beside the grade of the version the eval wrote, plus the pass/partial/fail bucket and per-case + per-grader detail. Use when polling a run started via evals.run or rendering a report card; pass wait_ms (max 30000) to block until it finishes instead of tight-looping. Returns null for a missing id.

Parameters

idpathstringrequired
wait_msqueryintegeroptional

Optional long-poll budget in ms, hard-capped at 30000. The read blocks until the run reaches complete / failed / canceled, then returns the SAME body an immediate poll would have returned.

Responses

200OK
dataobjectrequired
statusstringrequired

The run status, mirrored at the ROOT so `data.status` resolves here exactly as it does on POST /evals/run and on /gate, /drafts, /improvement, /evidence. Identical to `run.status`, which is retained. The terminal success value is `complete` — never `completed`.

queuedrunningcompletefailedcanceled
runobjectrequired

The run row. Null is returned for a missing or cross-tenant id — the two are deliberately indistinguishable.

idstringrequired
eval_slugstringoptional
eval_versionstringoptional
statusstringrequired

Lifecycle state. The terminal success value is `complete` — never `completed`.

queuedrunningcompletefailedcanceled
verdictobjectoptional

The graded report card. Null until the run reaches `complete`.

error_messagestring | nulloptional
created_atstringoptional
finished_atstring | nulloptional
regradeobjectoptional

Present exactly when this run’s evidence pool is pinnable: the parameter set that holds it fixed for the next call. Absent otherwise, never partial.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}/compare/{other_id}
API keyorBearer JWT

Compare Eval Runs

Compare two eval runs and report whether their difference is a result. Read when A/B-ing two drafts: each run retrieves its own quotes unless pinned, and a bumped eval_version re-means the stored score, so a raw difference can be either rather than your edit. Returns both verdicts, the shared-evidence overlap, any version boundary crossed, and a delta ONLY when the pair supports one — otherwise why not, and how to fix it.

Parameters

idpathstringrequired

The baseline run id.

other_idpathstringrequired

The candidate run id to compare against it.

Responses

200OK
dataobjectrequired
comparisonobjectrequired

The comparison. Null is never returned — a missing or cross-tenant id on either side resolves the whole read to a 404, so a compare cannot be used to probe which run ids exist in another workspace.

aobjectrequired

The baseline run, with its own status and scores.

bobjectrequired

The candidate run, same shape.

evidence_overlapobjectrequired

How much of the two runs’ quote pools was shared.

delta_attributablebooleanrequired

Whether the difference can be attributed to the change in graded content. FALSE whenever shared evidence could not be DEMONSTRATED — including when it could not be measured. A comparison that cannot prove its controls is not a weak finding, it is not a finding.

score_deltanumberoptional

PRESENT ONLY when `delta_attributable`. Absent means the pair supports no delta — read `delta_withheld_reason`, NOT "no change".

submitted_score_deltanumberoptional

How much the caller’s OWN copy moved, on [0,1] — the number an A/B is asking for. Derived from the improvement report rather than `overall_score`, so it means the same thing on both sides of a version boundary. Held to the same noise floor.

submitted_score_15_deltanumberoptional

The same movement on the [1,5] axis every human-facing score is stated on.

delta_withheld_reasonstringoptional

Why no delta shipped. Typed because the causes need DIFFERENT things from the reader and most are not fixed by pinning evidence — see `remedy`, which is keyed to this value.

not_scoredevidence_not_controlledartifact_type_mismatchstop_reason_mismatchinside_noise_flooreval_version_boundary
noise_floornumberoptional

The floor |delta| had to clear, present whether or not it cleared — so a caller can see how close it came.

version_boundaryobjectoptional

The eval_version transitions this pair straddles, with each one’s `kind`. Present whenever the two runs carry different versions. `recorded: false` means the ledger has no entry for one of them — "cannot say", not "nothing crossed".

caveatstringrequired

Plain-English statement of what this comparison does and does not support.

remedystringoptional

How to get a reportable delta out of these two runs. Present exactly when `delta_withheld_reason` is.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}/gate
API keyorBearer JWT

Get Eval Run Gate

Fetch the machine verdict on the copy the caller SUBMITTED: passed, checks_passed/checks_total, score_15 against its threshold, and which failed. Use when wiring an eval into a pipeline as a send/hold decision — never gate on overall_score or lift, which follow the rewrite. Pass wait_ms (max 30000) to block until the run settles. gate is null while running or when the run refused (not_applicable_reason says why); a refusal is not a fail.

Parameters

idpathstringrequired
wait_msqueryintegeroptional

Optional long-poll budget in ms, hard-capped at 30000. Blocks until the run reaches complete / failed / canceled, then returns the same body an immediate poll would.

Responses

200OK
dataobjectrequired
run_idstringrequired
eval_slugstringoptional
eval_versionstringoptional

The eval version this run was graded at. Gate thresholds are only comparable within one version — see the eval version ledger.

statusstringrequired

The run status, at the ROOT of the body — unlike GET /eval-runs/{id}, which nests it under `run`. The terminal success value is `complete` — never `completed`.

queuedrunningcompletefailedcanceled
gateobjectrequired

The machine verdict on the copy the caller SUBMITTED. NULL means this run has no submitted-side grade to gate on — still running, refused (see `not_applicable_reason`), or a grader mix that produced none. Never treat null as a fail: `passed: false` is a verdict on the copy and a refusal is emphatically not one.

not_applicable_reasonstringoptional

Present exactly when the run refused to grade, saying why. A refusal is not a fail.

error_messagestringoptional

Present only on a failed run.

regradeobjectoptional

Present exactly when this run’s evidence pool is pinnable: the parameter set that holds it fixed for the next call, so a held draft’s edit is graded against the same quotes. Absent otherwise, never partial.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}/report
API keyorBearer JWT

Get Eval Run Report

Fetch the canonical report card for one eval run as ready-to-paste markdown: your draft score vs the improved one, the bar, the transition, cited customer quotes, and any confidence caveat. Read when presenting a result to a person — paste the markdown as written rather than summarising it, so the numbers reported are the ones Amdahl computed.

Parameters

idpathstringrequired

Responses

200OK
dataobjectrequired
statusstringrequired

The run status, mirrored at the root so `data.status` resolves here as it does on every other eval read. Identical to `report.status`. The terminal success value is `complete` — never `completed`.

queuedrunningcompletefailedcanceled
reportobjectrequired

The canonical report card. `markdown` is a string on every run state; `headline` and `findings` are null until the run reaches `complete`.

run_idstringrequired
eval_slugstringrequired
statusstringrequired
markdownstringrequired
headlineobject | nulloptional
findingsobject | nulloptional

What did not hold up on the submitted copy: `failed[]` (one entry per rubric line missed, each `{dimension, reasoning}`), `contradicting[]`, and `truncated`. `dimension` is the rubric line’s STEM — the clause before the first colon — because the card renders it as a bold lead-in to that line’s `reasoning`, which carries the substance. The gate read names the SAME lines IN FULL: `gate.dimensions_failed` on GET /eval-runs/{id}/gate spells out each line’s whole text, because it travels without a reasoning field and the stem alone would drop the criterion. Same lines, two renderings, on purpose — a diff between the two strings is expected, not a bug. The two can also differ in LENGTH: `failed[]` cuts at 8 and says so via `truncated`, while `gate.dimensions_failed` is uncapped. On the shipped five-line rubric that cut never binds; a tenant-authored eval with a longer rubric can reach it.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}/evidence
API keyorBearer JWT

Get Eval Run Evidence

Fetch the frozen customer-quote pool one eval run graded against: every quote with its id, tier, provenance and whether it reached the graded prompt, plus when the pool was frozen. Read when drafting an edit to re-grade against the SAME evidence (then pass evidence_from_run on the next run so the score delta is the edit, not a retrieval change), or when auditing what a verdict was scored on. evidence is null when the run never recorded a pool.

Parameters

idpathstringrequired

Responses

200OK
dataobjectrequired
run_idstringrequired
eval_slugstringrequired
statusstringrequired

The run status, at the root as on every eval read. The terminal success value is `complete` — never `completed`.

queuedrunningcompletefailedcanceled
evidenceobject | nulloptional

The frozen quote pool this run was graded against. Null means no pool was recorded (the run predates evidence recording, or retrieval never froze a set) — a fact, not an error, and not pinnable.

regradeobjectoptional

The pasteable `evidence_from_run` params for re-grading an edit against this same pool. Present exactly when the pool is pinnable on a settled run; absent otherwise.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}/drafts
API keyorBearer JWT

Get Eval Run Drafts

Fetch both graded artifacts of one eval run side by side: the prompt and message you submitted, the improved versions the eval wrote, each with its score, checks fraction and per-rubric-line reasoning. Read when comparing your draft against the rewrite line by line — this is the only read that carries the texts themselves. Cited quotes stay on the evidence read.

Parameters

idpathstringrequired

Responses

200OK
dataobjectrequired
run_idstringrequired
eval_slugstringrequired
eval_versionstring | nulloptional
statusstringrequired

The run status, at the root as on every eval read. The terminal success value is `complete` — never `completed`.

queuedrunningcompletefailedcanceled
submittedobjectoptional

The prompt and message you sent, each with its score and per-line verdicts.

improvedobjectoptional

The rewritten versions. `prompt` / `message` are null with an `absent_reason` on a run that correctly wrote no rewrite — never an empty string, never a zero score.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/eval-runs/{id}/improvement
API keyorBearer JWT

Get Eval Run Improvement Report

Fetch the before/after improvement report of one eval run in a bounded shape: the per-facet graded pair with scores, per-rubric-line verdicts, cited quotes and the not-applicable counters, plus lift, transition, suggestions and confidence. Read when the full run payload is too large for your transport and you need the facets — no other narrow read carries them.

Parameters

idpathstringrequired

Responses

200OK
dataobjectrequired
run_idstringrequired
eval_slugstringoptional
eval_versionstring | nulloptional
statusstringrequired
queuedrunningcompletefailedcanceled
improvementobject | nullrequired

The before/after report. `facets[]` is the per-facet graded pair; each side carries score_15, checks_passed / checks_total, dimensions, quotes and the not-applicable counters. NULL — never an empty object, and never an empty `facets` — when the run produced no report (mode "gate", or any refusal); read `absent_reason` beside it.

omittedarray of objectrequired

The fields this bounded shape leaves on the full-row read, each with why and where. Present on EVERY response, so the omission is readable rather than inferred from a payload that came back smaller than expected.

array items

fieldstringrequired
whystringrequired
readstringrequired
absent_reasonstring | nulloptional

Present only when `improvement` is null: why the run produced no report.

400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/grader-kinds
API keyorBearer JWT

List Grader Kinds

List every grader kind an eval can use: deterministic (rule checks, no LLM), sor_anchored (compare a figure to a ground-truth warehouse count), and judge (LLM scores a rubric). Use when authoring or explaining an eval. Returns id, name, description, and whether the kind makes an LLM call.

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
get/api/platform/v1/grader-kinds/{id}
API keyorBearer JWT

Get Grader Kind

Fetch one grader kind by id (deterministic / sor_anchored / judge). Use when rendering a single grader-kind detail card. Returns its name, description, and llm-usage flag, or null for an unknown id.

Parameters

idpathstringrequired

Responses

200OK
dataanyoptional
400Invalid input - failed schema validation
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
401Authentication required
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
403Forbidden - missing scope or role
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
404Not found
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional
500Internal server error
errorobjectrequired
codestringrequired
messagestringrequired
detailsobjectoptional