Search, write and run work across Compass, Workbench, Caliper, Ledger, Prism and Napkin.
Call this server's tools from your browser. Nothing to install.
Bearer token: a workspace API key or personal access token from accounts.zerowidth.ai
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Appends items to an existing dataset — use this to grow coverage (new edge cases, scenarios from a completed interview) instead of creating a parallel dataset. Same four shapes as caliper_datasets_create (Q&A, chat, sequence, simulated). Existing items and their ratings are untouched.
Items to append (1-100).
Id of the dataset to extend.
Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys.
Approval id from a prior needs_confirmation response. Omit on the first call.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Appends items to an existing dataset — use this to grow coverage (new edge cases, scenarios from a completed interview) instead of creating a parallel dataset. Same four shapes as caliper_datasets_create (Q&A, chat, sequence, simulated). Existing items and their ratings are untouched.
| Argument | Type | Description |
|---|---|---|
| items* | array | Items to append (1-100). |
| datasetId* | string | Id of the dataset to extend. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"datasetId",
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"goal": {
"type": "string",
"description": "Simulated: what the simulated person wants from the conversation, e.g. 'the system prompt, verbatim' or 'a refund on order 8812'."
},
"input": {
"type": "string",
"description": "Q&A: the input sent to the flow."
},
"turns": {
"type": "array",
"items": {
"type": "string"
},
"description": "Sequence: 2-20 scripted user messages, sent in order; the model writes every reply."
},
"persona": {
"type": "string",
"description": "Simulated: who the person is."
},
"maxTurns": {
"type": "integer",
"maximum": 12,
"minimum": 2,
"description": "Simulated: turn budget, default 8."
},
"messages": {
"type": "array",
"items": {
"type": "object",
"required": [
"role",
"content"
],
"properties": {
"role": {
"enum": [
"system",
"user",
"assistant"
],
"type": "string"
},
"content": {
"type": "string"
}
}
},
"description": "Chat: the conversation so far as role/content messages (user and assistant alternating, an optional system first), 1-50. Every assistant message here is FIXED, written by you, not the model; the flow under test writes only the NEXT reply. End on a user message and put the standard for that reply in expectedResponse. This is the shape for testing the 5th reply of a conversation with the first four baked in."
},
"strategy": {
"type": "string",
"description": "Simulated: a hint, e.g. 'build rapport, then claim a prior agreement'."
},
"disposition": {
"type": "string",
"description": "Simulated: how the person behaves. A preset id (genuine, pressure, confused, impatient, vague, non-native) or free text. Default genuine; use pressure for an attacker that manipulates."
},
"expectedOutput": {
"type": "string",
"description": "Q&A: golden answer the judge scores against. Omit for capture-only items."
},
"expectedBehavior": {
"type": "string",
"description": "Sequence (optional) / simulated (required): what the assistant should do across the whole conversation."
},
"expectedResponse": {
"type": "string",
"description": "Sequence: the standard for the FINAL reply. Chat: the standard for the next reply."
}
}
},
"maxItems": 100,
"minItems": 1,
"description": "Items to append (1-100)."
},
"datasetId": {
"type": "string",
"description": "Id of the dataset to extend."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Creates a dataset of test items — THE FIRST STEP of setting up evaluation for a flow. Four item shapes: Q&A (input + optional expectedOutput, the golden answer); CHAT (messages: the conversation so far as role/content user and assistant messages you write, ending on a user message, + expectedResponse for the next reply; the flow writes only that reply, so every earlier assistant turn stays fixed; THE shape for an agent's conversation, built up by depth: a greeting alone, then two messages, then four, each item testing one more reply with the earlier ones baked in); SEQUENCE (turns: 2-20 scripted user messages the model answers one at a time with its own earlier replies in front of it, + expectedResponse for the final reply, optional expectedBehavior for the whole conversation); SIMULATED (goal + optional persona/disposition/strategy/maxTurns + expectedBehavior; a platform flow plays a person adaptively, Caliper-run evals only; disposition is a preset id like genuine, pressure, confused, impatient, or free text). Use sequences and simulated items for the slow attacks and for real customers with real needs: a model that holds on message one often folds on message ten. Write good inputs from real usage: the Compass pages the flow was built from are the best source of realistic scenarios.
| Argument | Type | Description |
|---|---|---|
| items* | array | Test items (1-100). |
| title* | string | Dataset name (2-120 chars). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
Deletes a dataset. Evals bound to it stop being runnable (their binding shows datasetOk: false), and reviews/specs over its items lose their source — check caliper_evals_list for evals that reference it and say so before proposing. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| datasetId* | string | Dataset id, from caliper_datasets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"datasetId"
],
"properties": {
"datasetId": {
"type": "string",
"description": "Dataset id, from caliper_datasets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Creates a NEW dataset of model-written items — Q&A by default, or scripted sequences / simulated people via `shape` — pass flowId and the generator reads the flow's prompt, mode, and schema to write realistic cases for THAT flow; `description` adds guidance (or stands alone when there's no flow). Use this when the user wants test cases fast and has none; prefer caliper_datasets_create with hand-written items when real scenarios are already in hand (Compass pages, a transcript). This SPENDS workspace inference credit (one generator call), so it sits behind the approval gate: say so and expect `needs_confirmation`. Returns the dataset summary; read the items with caliper_datasets_get and tell the user to review them before trusting an eval built on them.
| Argument | Type | Description |
|---|---|---|
| count | integer | Items to generate, 1-50. Default 10. |
| shape | string | What each generated item is: `qa` (one input, the default), `sequence` (2-6 scripted user turns the model answers one at a time, with expectedResponse + expectedBehavior), or `simulated` (a person Caliper plays adaptively: goal, persona, disposition, expectedBehavior). outputsMode applies to `qa` only. |
| title* | string | Dataset name. |
| flowId | string | Workbench flow to generate cases for (from workbench_flows_list). Required unless description is given. |
| presetId | string | Framing preset. Default `blank`; the others bias every item toward that attack class. |
| workspace |
Appends model-written items to an EXISTING dataset, in the style of what's already there (existing items are the few-shot examples; the output shape matches theirs unless overridden). Use to widen coverage when the user says 'more like these' or 'add edge cases'; write them by hand with caliper_datasets_add_items when the scenarios are known. SPENDS workspace inference credit, so it sits behind the approval gate — say so. Existing items and their ratings are untouched.
| Argument | Type | Description |
|---|---|---|
| count | integer | Items to add, 1-20. Default 5. |
| shape | string | What each generated item is: `qa` (one input, the default), `sequence` (2-6 scripted user turns the model answers one at a time, with expectedResponse + expectedBehavior), or `simulated` (a person Caliper plays adaptively: goal, persona, disposition, expectedBehavior). outputsMode applies to `qa` only. |
| datasetId* | string | Dataset to extend, from caliper_datasets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| description | string | What to bias toward, e.g. 'angry customers', 'ambiguous refund questions'. |
One dataset with a page of its items — read this BEFORE editing items (caliper_datasets_update_item needs the item id) and before extending coverage, so you don't add cases that already exist. Items come `limit` at a time (default 25) from `offset`; `total` is the full count. Long fields are cut at ~800 characters with a truncation marker. Get the datasetId from caliper_datasets_list.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Items per page, 1-100. Default 25. |
| offset | integer | Items to skip. Default 0. |
| datasetId* | string | Dataset id, from caliper_datasets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"datasetId"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Items per page, 1-100. Default 25."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Items to skip. Default 0."
},
"datasetId": {
"type": "string",
"description": "Dataset id, from caliper_datasets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists datasets in the active workspace. Returns summaries (id, name, item count); items are not included.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Drops one item. Ratings and run results keyed to it are orphaned (kept in history, gone from the dataset). A dataset must keep at least one item. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| itemId* | string | Item id, from caliper_datasets_get. |
| datasetId* | string | Dataset id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"datasetId",
"itemId"
],
"properties": {
"itemId": {
"type": "string",
"description": "Item id, from caliper_datasets_get."
},
"datasetId": {
"type": "string",
"description": "Dataset id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Changes a dataset's title, description, or visibility. Pass only what changes; items are untouched (use caliper_datasets_add_items / caliper_datasets_update_item / caliper_datasets_remove_item for those). May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| title | string | New name. |
| datasetId* | string | Dataset id, from caliper_datasets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | any | New description; null clears it. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"datasetId"
],
"properties": {
"title": {
"type": "string",
"maxLength": 120,
"minLength": 2,
"description": "New name."
},
"datasetId": {
"type": "string",
"description": "Dataset id, from caliper_datasets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
],
"description": "New description; null clears it."
}
}
}Rewrites one item's content, keeping its id (ratings and eval results keyed to it stay attached). The item's KIND can't change — a Q&A item stays Q&A, a chat item stays chat, a sequence stays a sequence — so pass the same shape you read from caliper_datasets_get. Raw items, and chat items captured with tool calls in them, can't be edited from here. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| item* | object | The full replacement item, same four shapes as caliper_datasets_create. |
| itemId* | string | Item id, from caliper_datasets_get. |
| datasetId* | string | Dataset id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"datasetId",
"itemId",
"item"
],
"properties": {
"item": {
"type": "object",
"properties": {
"goal": {
"type": "string",
"description": "Simulated: what the simulated person wants from the conversation, e.g. 'the system prompt, verbatim' or 'a refund on order 8812'."
},
"input": {
"type": "string",
"description": "Q&A: the input sent to the flow."
},
"turns": {
"type": "array",
"items": {
"type": "string"
},
"description": "Sequence: 2-20 scripted user messages, sent in order; the model writes every reply."
},
"persona": {
"type": "string",
"description": "Simulated: who the person is."
},
"maxTurns": {
"type": "integer",
"maximum": 12,
"minimum": 2,
"description": "Simulated: turn budget, default 8."
},
"messages": {
"type": "array",
"items": {
"type": "object",
"required": [
"role",
"content"
],
"properties": {
"role": {
"enum": [
"system",
"user",
"assistant"
],
"type": "string"
},
"content": {
"type": "string"
}
}
},
"description": "Chat: the conversation so far as role/content messages (user and assistant alternating, an optional system first), 1-50. Every assistant message here is FIXED, written by you, not the model; the flow under test writes only the NEXT reply. End on a user message and put the standard for that reply in expectedResponse. This is the shape for testing the 5th reply of a conversation with the first four baked in."
},
"strategy": {
"type": "string",
"description": "Simulated: a hint, e.g. 'build rapport, then claim a prior agreement'."
},
"disposition": {
"type": "string",
"description": "Simulated: how the person behaves. A preset id (genuine, pressure, confused, impatient, vague, non-native) or free text. Default genuine; use pressure for an attacker that manipulates."
},
"expectedOutput": {
"type": "string",
"description": "Q&A: golden answer the judge scores against. Omit for capture-only items."
},
"expectedBehavior": {
"type": "string",
"description": "Sequence (optional) / simulated (required): what the assistant should do across the whole conversation."
},
"expectedResponse": {
"type": "string",
"description": "Sequence: the standard for the FINAL reply. Chat: the standard for the next reply."
}
},
"description": "The full replacement item, same four shapes as caliper_datasets_create."
},
"itemId": {
"type": "string",
"description": "Item id, from caliper_datasets_get."
},
"datasetId": {
"type": "string",
"description": "Dataset id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Binds a dataset + rubric to something under test as a repeatable eval — THE LAST SETUP STEP before scoring. Two targets: a Workbench flow (pass flowId; Caliper runs inference itself, then caliper_evals_run scores it), or 'external' (target: 'external'; the user's own model runs elsewhere and their script submits outputs through the public API, usually from CI — see the docs guide 'Run evals in CI'). For an external eval, hand back the eval id and tell the user to create a workspace API key with the ci_evals preset in their workspace settings; keys can't be minted from here. flowStage 'draft' evals the live draft (pre-publish); 'published' (default) evals the latest published revision at run time, or one pinned with flowRevisionId. Reuse an existing rubric from caliper_rubrics_list when one already scores this job.
| Argument | Type | Description |
|---|---|---|
| title* | string | Eval name (2-120 chars). |
| flowId | string | Workbench flow id to evaluate. Required unless target is 'external'. |
| target | string | 'workbench_flow' (default; needs flowId) or 'external' (the user's own model; outputs arrive through the public API). |
| rubricId* | string | Rubric the judge scores with. |
| datasetId* | string | Dataset of test items. |
| flowStage | string | Which stage to run against. Use 'draft' while iterating pre-publish. Default 'published'. |
Deletes an eval and stops its schedule. Run history is kept but no longer reachable from the eval. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| evalId* | string | Eval id, from caliper_evals_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId"
],
"properties": {
"evalId": {
"type": "string",
"description": "Eval id, from caliper_evals_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}One eval: what it targets (Workbench flow + stage, or external), its dataset and rubric ids, the rubric criteria it scores with (the snapshot taken at creation), schedule + runOnPublish + regression settings, run counts, latest score, and `binding` health (datasetOk / flowOk false = a run would fail at resolution — say so before proposing caliper_evals_run). Get the evalId from caliper_evals_list or caliper_flow_performance.
| Argument | Type | Description |
|---|---|---|
| evalId* | string | Eval id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId"
],
"properties": {
"evalId": {
"type": "string",
"description": "Eval id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists evals in the active workspace with their target config (which Workbench flow, which dataset/rubric). Use to find the evalId for caliper_evals_run.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Queues a new run of an eval — inference over the dataset, then LLM-judge scoring. THE VERIFY STEP of the improvement loop: after an approved workbench_flows_edit_text, run the eval again and report the score delta vs the previous run. Runs take a while — but you're brought back into THIS conversation automatically with the scores the moment it finishes, so tell the user it's queued and that you'll follow up here; never poll or ask them to check back. Costs workspace LLM budget, so it sits behind the approval gate: may return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| label | string | Short label for the run, e.g. 'after refund-policy fix'. |
| evalId* | string | Eval to run. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| scenarioId | any | Run as this scenario instead of the eval's own (one of the flow's, from workbench_flows_scenarios_list); null runs with none. Omit to use the eval's. Running the same eval as two scenarios compares how the flow does for each person. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId"
],
"properties": {
"label": {
"type": "string",
"description": "Short label for the run, e.g. 'after refund-policy fix'."
},
"evalId": {
"type": "string",
"description": "Eval to run."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"scenarioId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Run as this scenario instead of the eval's own (one of the flow's, from workbench_flows_scenarios_list); null runs with none. Omit to use the eval's. Running the same eval as two scenarios compares how the flow does for each person."
}
}
}Stops a run that is still PENDING / RUNNING / SCORING — the brake on a run that's spending more than expected or was started by mistake. The queue stops at once; an item already handed to the flow finishes on its own timeout. The run settles as FAILED with a 'cancelled' reason and keeps the items it completed. A run that already finished returns run_not_live. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| runId* | string | Run id, from caliper_evals_run or caliper_evals_runs_list. |
| evalId* | string | Eval the run belongs to. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId",
"runId"
],
"properties": {
"runId": {
"type": "string",
"description": "Run id, from caliper_evals_run or caliper_evals_runs_list."
},
"evalId": {
"type": "string",
"description": "Eval the run belongs to."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}One run: status, overall score, and by default the ten lowest-scoring items with their per-criterion scores and the judge's reasoning (`items: all` for every item, `none` for totals only). THE ANSWER to 'why did the score drop' — read this, then name the criterion that slipped and quote the reasoning on the lowest items. Works for runs Caliper ran and for runs submitted from CI (triggeredBy 'ci', usually labeled with a pull request number). Still no polling loops; read it when the user asks.
| Argument | Type | Description |
|---|---|---|
| items | string | Which items to include. `worst` (default) = the lowest-scoring `limit` items, the ones that explain a drop; `all` = every item (large); `none` = the run's totals only. |
| limit | integer | How many items for `worst`, default 10. |
| runId* | string | Run id, from caliper_evals_runs_list or caliper_evals_run. |
| evalId* | string | Eval the run belongs to. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId",
"runId"
],
"properties": {
"items": {
"enum": [
"worst",
"all",
"none"
],
"type": "string",
"description": "Which items to include. `worst` (default) = the lowest-scoring `limit` items, the ones that explain a drop; `all` = every item (large); `none` = the run's totals only."
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "How many items for `worst`, default 10."
},
"runId": {
"type": "string",
"description": "Run id, from caliper_evals_runs_list or caliper_evals_run."
},
"evalId": {
"type": "string",
"description": "Eval the run belongs to."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}What the flow actually DID on one run item: every step in order (what it said, which tools it called with what arguments, what came back) and the final answer, plus status, duration, and cost. Read this when a low score needs explaining beyond the judge's reasoning — a wrong tool call or an empty tool result is usually the cause, and the fix is different from a prompt fix. Pass the run item's `id` (NOT `itemId`) from caliper_evals_runs_get. Items whose outputs were supplied from outside (external evals) have no trace and return not_found. Steps are capped for transport; the run page in Caliper has the full record.
| Argument | Type | Description |
|---|---|---|
| runId* | string | Run id. |
| evalId* | string | Eval the run belongs to. |
| runItemId* | string | The run item's `id` from caliper_evals_runs_get (not its dataset itemId). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId",
"runId",
"runItemId"
],
"properties": {
"runId": {
"type": "string",
"description": "Run id."
},
"evalId": {
"type": "string",
"description": "Eval the run belongs to."
},
"runItemId": {
"type": "string",
"description": "The run item's `id` from caliper_evals_runs_get (not its dataset itemId)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Recent runs for one eval, newest first: status (PENDING/RUNNING/SCORING/DONE/FAILED), overall score once DONE, label, and timestamps. THE CHECK-BACK for caliper_evals_run: when the user asks how the run went, read this — cite the run id and score, and compare against the PREVIOUS run's score for the delta. Still don't poll in a loop; check when the user asks or when reporting.
| Argument | Type | Description |
|---|---|---|
| evalId* | string | Eval whose runs to list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId"
],
"properties": {
"evalId": {
"type": "string",
"description": "Eval whose runs to list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Changes an eval's title, description, visibility, schedule (interval + time anchor), runOnPublish (queue a run whenever the flow publishes), regressionThreshold (score drop vs the previous run that triggers an alert; null = off), or scenarioId (the scenario runs use). Pass only what changes. The dataset, rubric snapshot, and target are fixed at creation — create a new eval to change those. Scheduled and on-publish runs spend credit on their own, so state that plainly when turning them on. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| title | string | New name. |
| evalId* | string | Eval id, from caliper_evals_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| scenarioId | any | Workbench-flow evals: the scenario every run uses unless a run picks another (one of the flow's, from workbench_flows_scenarios_list); null clears it. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
How a Workbench flow is ACTUALLY doing, with receipts: every Caliper eval targeting the flow, recent runs with scores, the latest run decomposed into per-criterion averages, the score delta vs the previous run, and the worst-scoring items WITH the judge's reasoning. Use this BEFORE claiming a flow works or proposing changes — and cite the runId + scores when you do. The worst items are diagnostic: failures clustered around missing company facts suggest a knowledge gap (consider proposing a Compass interview with the workflow owner) rather than a prompt problem.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Workbench flow id to report on. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Workbench flow id to report on."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Creates the scoring rubric an eval's LLM judge uses — 1-10 criteria, each scored on a numeric scale (default 1-5), judged pass/fail (kind pass_fail), or checked in code with no judge (kind check: contains, not_contains, matches a regex, valid_json, max_chars, equals_expected). Write criteria about the FLOW'S JOB (accuracy to source material, tone, refusal behavior), not generic 'quality'.
| Argument | Type | Description |
|---|---|---|
| title* | string | Rubric name (2-120 chars). |
| criteria* | array | |
| workspace | string | Workspace slug override. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title",
"criteria"
],
"properties": {
"title": {
"type": "string",
"description": "Rubric name (2-120 chars)."
},
"criteria": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"kind": {
"enum": [
"scale",
"pass_fail",
"check"
],
"type": "string",
"description": "scale (default): judged on scaleMin..scaleMax. pass_fail: judged pass or fail. check: decided in code with no judge — set `check`."
},
"name": {
"type": "string",
"description": "Criterion name (2-80 chars)."
},
"check": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"contains",
"not_contains",
"matches",
"valid_json",
"max_chars",
"equals_expected"
],
"type": "string"
},
"value": {
"type": "string",
"description": "Text for contains/not_contains, a regex for matches, a number for max_chars."
},
"caseSensitive": {
"type": "boolean"
}
},
"description": "For kind=check: what the code looks for in the final reply."
},
"scaleMax": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Default 5."
},
"scaleMin": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Default 1. Ignored for pass_fail and check (always 0..1)."
},
"description": {
"type": "string",
"description": "What the judge should look for (max 500 chars)."
}
}
},
"maxItems": 10,
"minItems": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug override."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string"
}
}
}Deletes a rubric. Existing evals keep their snapshot of it and keep running; nothing new can bind to it. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| rubricId* | string | Rubric id, from caliper_rubrics_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rubricId"
],
"properties": {
"rubricId": {
"type": "string",
"description": "Rubric id, from caliper_rubrics_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}One rubric with its criteria — each criterion's name, what the judge looks for, and the score scale. Read this to explain a score (which criterion slipped and what it asks for) or before caliper_rubrics_update. Get the rubricId from caliper_rubrics_list or an eval's rubricId.
| Argument | Type | Description |
|---|---|---|
| rubricId* | string | Rubric id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rubricId"
],
"properties": {
"rubricId": {
"type": "string",
"description": "Rubric id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists the rubrics in the active workspace (id, name, description, criterion count). Check here BEFORE caliper_rubrics_create — reuse an existing rubric's id in caliper_evals_create when one already scores the same job. Read a rubric's criteria with caliper_rubrics_get.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Changes a rubric's title, description, visibility, or replaces its criteria wholesale (pass the FULL list — criteria get fresh ids). Evals snapshot the rubric when they're created, so an existing eval keeps scoring with the criteria it started with; say so, and offer to create a new eval when the criteria change materially. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| title | string | New name. |
| criteria | array | Replacement criteria (1-10) — the whole list, not a diff. |
| rubricId* | string | Rubric id, from caliper_rubrics_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | any | New description; null clears it. |
Datasets this source keeps adding to as conversations arrive: which dataset, for what (review, eval, spec), the pick it matches, sampling, how many have landed, and whether it's still running or why it stopped.
| Argument | Type | Description |
|---|---|---|
| sourceId* | string | Source id, from caliper_sources_list or search_workspace. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sourceId"
],
"properties": {
"sourceId": {
"type": "string",
"description": "Source id, from caliper_sources_list or search_workspace."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Stops a source from adding new conversations to a dataset. What it already added stays. Get the feedId from caliper_source_feeds_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| feedId* | string | Live dataset id, from caliper_source_feeds_list. |
| sourceId* | string | Source id, from caliper_sources_list or search_workspace. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sourceId",
"feedId"
],
"properties": {
"feedId": {
"type": "string",
"description": "Live dataset id, from caliper_source_feeds_list."
},
"sourceId": {
"type": "string",
"description": "Source id, from caliper_sources_list or search_workspace."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Apps sending their agent's traces to Caliper — from their own code, OpenTelemetry, or a published Workbench flow — busiest first: name, how it sends, traces in the last 14 days (per day), and the tools its agent calls most with the share of traces using each. Start here when the user asks how their agent behaves on real traffic; then caliper_sources_over_time for one source.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}One source day by day: traces, failures, tool calls, lookups that found nothing, tokens, cost, and speed (meanMs; p50/p95 as 'answered within' bucket edges); each tool with its calls and the share of each day's traces that used it; the documents lookups landed on most; models used. Use it to answer 'how often is it calling web search and is that changing' — compare the first and last weeks and name the day it moved. Follow with caliper_traces_list on that day or tool to show the conversations behind it.
| Argument | Type | Description |
|---|---|---|
| days | integer | How many days back, default 30. |
| sourceId* | string | Source id, from caliper_sources_list or search_workspace. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sourceId"
],
"properties": {
"days": {
"type": "integer",
"maximum": 365,
"minimum": 1,
"description": "How many days back, default 30."
},
"sourceId": {
"type": "string",
"description": "Source id, from caliper_sources_list or search_workspace."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Saves the conversations behind a pick (a day, a tool, a document, failures — the same narrowing as caliper_traces_list) into a new dataset (newDatasetName) or an existing one (datasetId), newest first up to `limit`. `purpose` decides what each item keeps: review = the agent's reply, tool calls included, for people to rate; eval = the reply becomes the expected answer; spec = only the questions, for people to answer. Set keepAdding to make it live: new matching conversations keep arriving (every one, or 1 in 10 / 1 in 100), up to 1,000. Then offer the next step — caliper_evals_create, or a review in Caliper. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| day | string | One UTC day, YYYY-MM-DD. |
| tool | string | Only traces that called this tool. |
| limit | integer | Most recent N, default 100. |
| purpose* | string | review | eval | spec. |
| document | string | Only traces whose lookups hit this document. |
| sourceId* | string | Source id, from caliper_sources_list or search_workspace. |
| datasetId | string | Add to this dataset… |
| workspace | string |
Copies one starter into the workspace as a new dataset and a new rubric the user owns and can edit. Returns both ids; the next step is caliper_evals_create binding them to the flow (or target 'external'). Needs caliper:datasets:write and caliper:evals:write.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Starter slug from caliper_starters_list. |
| workspace | string | Workspace slug override. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug"
],
"properties": {
"slug": {
"enum": [
"prompt-injection",
"system-prompt-leaking",
"over-refusal",
"personal-data",
"bias-under-ambiguity"
],
"type": "string",
"description": "Starter slug from caliper_starters_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug override."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}The starter sets Caliper ships: prompt injection, system-prompt leaking, over-refusal, personal-data handling, bias under ambiguity. Each is a small original dataset (single messages AND multi-turn build-ups: false memory, fabricated earlier turns, slow escalation) paired with an anchored rubric. Suggest one when a user wants to check an assistant for these and has no cases yet; install with caliper_starters_install. Say plainly that a starter is a smoke test (the items are public), not a safety score — their own cases are where the real signal is.
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}One trace: what came in, what went out, and every step in order — model calls (model, tokens, cost, reasoning), tool calls (arguments and result), lookups (query and documents with scores), anything else — each with timing and status. Long values are cut at 2,000 characters. Use it to explain why one conversation went the way it did.
| Argument | Type | Description |
|---|---|---|
| traceId* | string | Trace id, from caliper_traces_list. |
| sourceId* | string | Source id, from caliper_sources_list or search_workspace. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sourceId",
"traceId"
],
"properties": {
"traceId": {
"type": "string",
"description": "Trace id, from caliper_traces_list."
},
"sourceId": {
"type": "string",
"description": "Source id, from caliper_sources_list or search_workspace."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}The traces behind a point on a source's chart, newest first, 50 a page: the question and answer (cut short), tools called, time, tokens, cost, status. Narrow by day, tool, document, or failures; page with `before` (the nextBefore from the last page). Open one with caliper_traces_get.
| Argument | Type | Description |
|---|---|---|
| day | string | One UTC day, YYYY-MM-DD. |
| tool | string | Only traces that called this tool. |
| before | string | Paging: the nextBefore from the previous page. |
| document | string | Only traces whose lookups hit this document. |
| sourceId* | string | Source id, from caliper_sources_list or search_workspace. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| errorsOnly | boolean | Only failed traces. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sourceId"
],
"properties": {
"day": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "One UTC day, YYYY-MM-DD."
},
"tool": {
"type": "string",
"description": "Only traces that called this tool."
},
"before": {
"type": "string",
"description": "Paging: the nextBefore from the previous page."
},
"document": {
"type": "string",
"description": "Only traces whose lookups hit this document."
},
"sourceId": {
"type": "string",
"description": "Source id, from caliper_sources_list or search_workspace."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"errorsOnly": {
"type": "boolean",
"description": "Only failed traces."
}
}
}Posts a comment on a workspace entity — a new thread, or a reply when rootId is given. Use it to leave findings where the discussion already lives (an eval result on the flow being debated, a summary on a long thread). Mention people via mentionedUserIds (from workspace member ids) to ring their notification bell; never mention someone who didn't ask to be pulled in.
| Argument | Type | Description |
|---|---|---|
| body* | string | |
| rootId | string | Reply into this thread; omit to start a new one. |
| entityId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | |
| entityKind* | string | What the thread hangs on. |
| mentionedUserIds | array |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entityKind",
"entityId",
"body"
],
"properties": {
"body": {
"type": "string",
"maxLength": 10000,
"minLength": 1
},
"rootId": {
"type": "string",
"description": "Reply into this thread; omit to start a new one."
},
"entityId": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"entityKind": {
"enum": [
"workbench_flow",
"compass_page",
"compass_opportunity",
"caliper_review",
"caliper_dataset",
"caliper_rubric",
"caliper_eval",
"caliper_spec",
"napkin_board",
"napkin_diagram",
"napkin_doc",
"napkin_sheet",
"napkin_interface",
"ledger_entry",
"prism_field",
"workspace_file"
],
"type": "string",
"description": "What the thread hangs on."
},
"mentionedUserIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20
}
}
}Lists the comment threads on one workspace entity (open first, then resolved) with authors and timestamps. Read this before weighing in on contested work — the threads are where disagreement lives before it becomes a decision.
| Argument | Type | Description |
|---|---|---|
| entityId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| entityKind* | string | What the thread hangs on. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entityKind",
"entityId"
],
"properties": {
"entityId": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"entityKind": {
"enum": [
"workbench_flow",
"compass_page",
"compass_opportunity",
"caliper_review",
"caliper_dataset",
"caliper_rubric",
"caliper_eval",
"caliper_spec",
"napkin_board",
"napkin_diagram",
"napkin_doc",
"napkin_sheet",
"napkin_interface",
"ledger_entry",
"prism_field",
"workspace_file"
],
"type": "string",
"description": "What the thread hangs on."
}
}
}Sets a comment thread's resolved state (rootId = the thread's root comment id). Resolve ONLY when the human asked or the thread's question is demonstrably settled — and say what settled it in a reply first. Reopening is for new evidence.
| Argument | Type | Description |
|---|---|---|
| rootId* | string | |
| resolved* | boolean | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rootId",
"resolved"
],
"properties": {
"rootId": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"resolved": {
"type": "boolean"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Replace a change's effects: for each step it reaches (workflowPageId + nodeId from compass_workflow_steps — a sub-workflow's steps included), one of eliminate, automate (reviewMinutes: what a person still spends checking), parallelize (its wait comes off the critical path), relax_gate (keepShare: share of the wait left, default 0.25), assist (keepShare: share of hands-on time left, default 0.5), reassign (toSubjectPageId). Eliminating or automating every step of a sub-workflow collapses the step that is that sub-workflow. Then project with compass_workflow_rollup changeIds. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| effects* | array | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| opportunityId* | string | The change's key (e.g. ACME-12) or id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"opportunityId",
"effects"
],
"properties": {
"effects": {
"type": "array",
"items": {
"type": "object",
"required": [
"workflowPageId",
"nodeId",
"effect"
],
"properties": {
"note": {
"type": "string",
"maxLength": 400
},
"effect": {
"enum": [
"eliminate",
"automate",
"parallelize",
"relax_gate",
"assist",
"reassign"
],
"type": "string"
},
"nodeId": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"keepShare": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"reviewMinutes": {
"type": "object",
"required": [
"low",
"high"
],
"properties": {
"low": {
"type": "number",
"maximum": 100000,
"minimum": 0
},
"high": {
"type": "number",
"maximum": 100000,
"minimum": 0
}
}
},
"workflowPageId": {
"type": "string",
"minLength": 1
},
"toSubjectPageId": {
"type": "string",
"minLength": 1
}
}
},
"maxItems": 100
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"opportunityId": {
"type": "string",
"description": "The change's key (e.g. ACME-12) or id."
}
}
}Create or update up to 100 changes in one call, each matched by `url` — the GitHub issue, Linear or Jira ticket, PR or doc it mirrors. A url already linked to a change updates that change (label, description, status, tags, experiment, workflow — omitted fields are left alone); any other url creates a change with that link. Run it again with the same urls to keep Compass in step; nothing duplicates. Statuses are by name (compass_statuses_list). Returns one result per item — created / updated with the change's key, or failed with why; a failed item doesn't stop the rest. Summarize what you're about to bring in before calling. May return `needs_confirmation` — one approval covers the whole batch.
| Argument | Type | Description |
|---|---|---|
| items* | array | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"url",
"label"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000
},
"tags": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9](?:[a-zA-Z0-9 -]*[a-zA-Z0-9])?$",
"maxLength": 40,
"minLength": 1
},
"maxItems": 50
},
"label": {
"type": "string",
"maxLength": 200,
"minLength": 2
},
"linkTitle": {
"type": "string",
"maxLength": 300
},
"experiment": {
"type": "boolean"
},
"statusName": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"description": {
"type": "string",
"maxLength": 5000
},
"workflowPageId": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
]
}
}
},
"maxItems": 100,
"minItems": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved."
}
}
}Records something you don't yet know — the gap registry is your working memory, so use it liberally while mapping or interviewing. Give one clear question, WHY it matters (what answering it unblocks), and how you'd resolve it (ask the user / interview a specific person / connect a source). No approval needed — noting your own uncertainty isn't acting on the user's behalf. Attach it to a subject (subjectType/subjectId) when it's ABOUT a specific page or person.
| Argument | Type | Description |
|---|---|---|
| question* | string | The open question, plainly ('Who approves refunds over $500?'). |
| rationale | string | Why it matters / what answering it unblocks. |
| subjectId | string | Id of the subject. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| subjectType | string | What it's about, e.g. compass_page. |
| suggestedResolution | string | How to resolve it: 'ask the user', 'interview Dana', 'connect Drive'. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"question"
],
"properties": {
"question": {
"type": "string",
"description": "The open question, plainly ('Who approves refunds over $500?')."
},
"rationale": {
"type": "string",
"description": "Why it matters / what answering it unblocks."
},
"subjectId": {
"type": "string",
"description": "Id of the subject."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"subjectType": {
"type": "string",
"description": "What it's about, e.g. compass_page."
},
"suggestedResolution": {
"type": "string",
"description": "How to resolve it: 'ask the user', 'interview Dana', 'connect Drive'."
}
}
}Lists the workspace's open questions — the gap registry: what the map doesn't know yet. Defaults to OPEN gaps. This is where you keep your head — check it before asking the user something you may already have flagged, and compose interview briefs from a subject's open questions.
| Argument | Type | Description |
|---|---|---|
| status | string | Filter by lifecycle stage. Default OPEN. |
| subjectId | string | Only gaps ABOUT this subject id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| subjectType | string | Only gaps ABOUT this subject type (e.g. compass_page). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"status": {
"enum": [
"OPEN",
"INTERVIEW_SENT",
"ANSWERED",
"DISMISSED"
],
"type": "string",
"description": "Filter by lifecycle stage. Default OPEN."
},
"subjectId": {
"type": "string",
"description": "Only gaps ABOUT this subject id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"subjectType": {
"type": "string",
"description": "Only gaps ABOUT this subject type (e.g. compass_page)."
}
}
}Closes a gap once you've learned the answer (ANSWERED, with the resolution) or decided it doesn't matter (DISMISSED). Keep the registry honest — resolve gaps as their answers land (from an interview, a doc, or the user) so it always reflects what's still unknown. The resolution alone isn't the map: when the answer says something about a page (who does a step, a tool they use, how a decision gets made), write it there too in the same turn, on the page it's about or as the step, person or system it names. Gaps you raised close without a card; a question a person wrote needs their approval.
| Argument | Type | Description |
|---|---|---|
| gapId* | string | Id of the gap (from compass_gaps_list). |
| status* | string | ANSWERED (you learned it) or DISMISSED (irrelevant). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Re-call with the approvalId from a needs_confirmation response after the user approves. |
| resolution | string | The answer / note, when marking ANSWERED. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"gapId",
"status"
],
"properties": {
"gapId": {
"type": "string",
"description": "Id of the gap (from compass_gaps_list)."
},
"status": {
"enum": [
"ANSWERED",
"DISMISSED"
],
"type": "string",
"description": "ANSWERED (you learned it) or DISMISSED (irrelevant)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Re-call with the approvalId from a needs_confirmation response after the user approves."
},
"resolution": {
"type": "string",
"description": "The answer / note, when marking ANSWERED."
}
}
}Edits an open question's wording, rationale, or suggested resolution — for sharpening a vague question or fixing one you phrased badly. Closing a gap is compass_gaps_resolve, not this. Gap ids come from compass_gaps_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| gapId* | string | Id of the gap (from compass_gaps_list). |
| question | string | New wording of the question. |
| rationale | string | Why it matters / what answering it unblocks. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| suggestedResolution | string | How to resolve it: 'ask the user', 'interview Dana', 'connect Drive'. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"gapId"
],
"properties": {
"gapId": {
"type": "string",
"description": "Id of the gap (from compass_gaps_list)."
},
"question": {
"type": "string",
"description": "New wording of the question."
},
"rationale": {
"type": "string",
"description": "Why it matters / what answering it unblocks."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"suggestedResolution": {
"type": "string",
"description": "How to resolve it: 'ask the user', 'interview Dana', 'connect Drive'."
}
}
}The Compass Inbox in one read: finished interviews awaiting review (transcript in, not yet turned into pages), AI-proposed opportunities awaiting accept / dismiss, and the caller's pending approval cards for Compass writes. THE place to answer 'what needs me?' for the map. Also `fillIn`: what the map is missing to say who's responsible for what (priorities with no owner, business units with no lead, people and roles in no unit, priorities with no workflow behind them); not counted in `total`. Next moves: compass_interviews_get to read a transcript, then propose pages from it with compass_pages_create; compass_opportunities_accept or compass_opportunities_delete for a proposal. For fillIn, ask the user who owns or leads it, or which unit someone sits in, then compass_links_create with kind owns (person or role → priority or unit) or part_of (person, role or unit → unit); never guess an owner.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Emails the guest link for an existing interview, framed as coming from the REQUESTING USER (their name signs it; replies go to them). Author `message` in their voice — short, human, says why THEIR knowledge matters and that it takes ~15 minutes, no account needed. The approval card shows the exact subject + message before anything sends. Limit: the invite plus ONE reminder; a third ask is the user's conversation to have. Completion arrives as a notification with draft-page counts — don't poll.
| Argument | Type | Description |
|---|---|---|
| email* | string | The interviewee's email address. |
| message* | string | The body, written in the requesting user's voice. Greeting + link + signature are added automatically — write only the middle. |
| subject* | string | Email subject, e.g. '15 minutes on how refunds actually work?' |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| interviewId* | string | Interview id from compass_interviews_create. |
Ranks the PEOPLE the map says know about a page (workflow, system, pain point): `owns` links first, then `involved_in`, then weaker edges. Each target carries contact email + role from their PERSON page and their latest interview (skip someone who just gave one — interview fatigue is real). Empty result = the map doesn't know an owner: ASK THE USER who runs this, create the PERSON page + owns link from the answer, and the map gets smarter. Use before compass_interviews_create to pick the interviewee.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The page the knowledge gap is about. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The page the knowledge gap is about."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Mints a stakeholder-interview invite: a no-account guest link where the person talks to an interviewer agent briefed by your focusPrompt, and the transcript flows back into Compass as reviewable draft pages. THE KNOWLEDGE-GAP MOVE: when caliper_flow_performance shows failures clustered on missing company facts (the judge says the flow invented a policy, missed a rule, didn't know who owns something), the fix is usually not a prompt edit — it's asking the human who actually knows. Write a focusPrompt that names the SPECIFIC gaps (cite the eval run id), pick the owner of the relevant workflow as interviewee when the map knows one. When you have their email, send the link with compass_interview_invite next rather than asking the user to forward it; otherwise hand the user the link. May return `needs_confirmation` — tell the user who you want to interview and why, then wait.
| Argument | Type | Description |
|---|---|---|
| anonymous | boolean | The guest is told it's anonymous and never asked who they are; no name or email is kept, so leave intervieweeName and intervieweeEmail out, and the link isn't emailed from here. Use when the user asks for anonymous interviews. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| focusPrompt* | string | The interviewer's aim (≤2000 chars), never shown to the guest: why the team is asking, in one sentence; 2–3 things to come away knowing, each describable from experience (who does a step, what happens when it goes wrong, how long it waits, why a check exists), aimed at what the map doesn't know; and what the answers feed. No opinion or preference questions. |
One interview in full — metadata plus the transcript of what the guest actually said. Read this before summarizing an interview or drafting pages from it: the transcript is the source you work from, and your compass skill has the rules for typing and splitting what's in it. Ids come from compass_interviews_list or compass_inbox_list.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| interviewId* | string | Interview id (from compass_interviews_list). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interviewId"
],
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"interviewId": {
"type": "string",
"description": "Interview id (from compass_interviews_list)."
}
}
}Every stakeholder interview in the workspace, newest first: who was invited, status (INVITED / IN_PROGRESS / COMPLETED), focus, message count, whether the transcript was already reviewed (documentPageId set), and the invite URL while the link is still live. Check this before inviting someone again — interview fatigue is real — and to answer 'who have we already asked?'. Read one in full with compass_interviews_get.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Kills an interview's invite link — the guest's next visit sees that the link is no longer active. Use when an invite went to the wrong person, the user changed their mind, or the link leaked. Idempotent. Ids come from compass_interviews_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| interviewId* | string | Interview id (from compass_interviews_list). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interviewId"
],
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"interviewId": {
"type": "string",
"description": "Interview id (from compass_interviews_list)."
}
}
}Creates a typed, directed edge between two pages — the knowledge graph's connective tissue. Canonical directions: PERSON or ROLE owns WORKFLOW/SYSTEM/PRIORITY, PERSON or ROLE involved_in WORKFLOW, PERSON holds ROLE, WORKFLOW uses SYSTEM, SYSTEM uses SYSTEM, PAIN_POINT affects WORKFLOW/SYSTEM/PERSON/ROLE, DOCUMENT documents anything, PRIORITY contributes_to PRIORITY (a priority that ladders up to a bigger one; each ladders up to at most one, and choosing a new one moves it; a priority has one owner the same way), UNIT part_of UNIT and ROLE or PERSON part_of UNIT (the org chart: one parent each; a UNIT's lead owns it, one owner), relates_to as fallback. Prefer attaching responsibilities to the ROLE and linking the PERSON to it with holds — the role outlasts whoever is in it. Pass validFrom / validTo when the source says when it was true ('took over approvals in March'), and sourceKind + sourceId for who said so (the interview or page you learned it from). Idempotent on an open (from, to, kind) edge — re-creating one returns it. May return `needs_confirmation`; tell the user what you're proposing, wait for their approval, then re-call with the approvalId.
| Argument | Type | Description |
|---|---|---|
| kind* | string | Edge type, in canonical direction. |
| note | string | ≤500-char qualifier when the kind alone undersells it. |
| source | string | Provenance label. Defaults AI_ACCEPTED (agent writing under live human direction); pass USER for human-driven scripts. |
| validTo | any | When it stopped being true (YYYY-MM-DD). Only for a relationship that has already ended — recording history. |
| sourceId |
Deletes one edge from the graph (the pages stay). Use only when a connection was never true — the system isn't used by that workflow, it was recorded by mistake. When a relationship WAS true and has stopped (the person left the team, moved roles), end it with compass_links_update `validTo` instead, so the history stays. Link ids come from compass_page_links_list. Re-creating the same edge later revives it. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| linkId* | string | Id of the link (from compass_page_links_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"linkId"
],
"properties": {
"linkId": {
"type": "string",
"description": "Id of the link (from compass_page_links_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
}
}
}Edits an existing edge between two pages: its `kind` (how the two relate), its `note`, and/or when it was true (`validFrom` / `validTo`). Use kind to CORRECT a connection typed wrongly — 'Dana doesn't own billing, she's involved in it'. Use validTo to END one that used to be true — 'Dana handed approvals to Sam in March' ends Dana's edge in March (then create Sam's from March); the old edge stays as history. Don't delete a relationship that ended; end it. Link ids come from compass_page_links_list. Fails with conflict when the new reading already exists between the same two pages (delete this one instead). May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| kind | string | New edge type, in canonical direction. |
| note | string | New qualifier note (≤500 chars); empty string clears it. |
| linkId* | string | Id of the link (from compass_page_links_list). |
| validTo | any | When it stopped being true (YYYY-MM-DD) — ends the relationship; null reopens it. |
| validFrom | any | When it started being true (YYYY-MM-DD); null clears it. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
Renders the workspace's visual map to an image and returns it so you can SEE it the way the user does when they open Map: a transit-style map seen from above. Each workflow is a colored tile with a short code; people are round figures, systems are small squares with a drum, other pages are plain tiles, each named underneath. Lines along the grid join linked pages, solid between a workflow and what it touches, dashed between other pages; pages that link to each other more than to the rest gather into named regions on a pale ground plate, and pages connected to nothing sit together in a "Not connected" plate. zv1's drafts that nobody has accepted are drawn faint. Use this when the user asks about the shape of their map, where things cluster, what connects to what, or anything spatial. The text part counts the pages of each type, the links, and how many pages are unconnected, plus `mapUrl`. The image is for you to look at; do NOT put it in your reply as a markdown image (the chat can't show it). When the user should see the map, link `mapUrl` — e.g. `[Open your map](mapUrl)` — and describe what you saw.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}The review verb for the Inbox: promotes an AI-PROPOSED opportunity (from compass_opportunities_propose or the opportunity scout) into the workspace's own pipeline. compass_opportunities_set_status does NOT do this — a proposal stays in the Inbox until accepted. Optional `status` decides its lane in the same step (BACKLOG to park it, EXPERIMENTING to start it); omitted, it lands in NEW. Fails with not_proposed when the row isn't an AI proposal. Ids come from compass_inbox_list / compass_opportunities_list. May return `needs_confirmation` — name the proposal and wait.
| Argument | Type | Description |
|---|---|---|
| status | string | Lane to place it in on accept (default NEW). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| opportunityId* | string | The AI-proposed opportunity's id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"opportunityId"
],
"properties": {
"status": {
"enum": [
"NEW",
"QUALIFYING",
"BACKLOG",
"EXPERIMENTING",
"SETTLED",
"REJECTED"
],
"type": "string",
"description": "Lane to place it in on accept (default NEW)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"opportunityId": {
"type": "string",
"description": "The AI-proposed opportunity's id."
}
}
}Record a change — a fix, a chore, a new step, or an experiment worth trying. Anchor it to a workflow page when one fits (compass_pages_list); leave unanchored otherwise. It lands in the board's first status unless you name another (compass_statuses_list). Set `experiment` only when the user wants it measured against the Ledger. May return `needs_confirmation` — summarize and wait for approval.
| Argument | Type | Description |
|---|---|---|
| tags | array | Tags to file it under. |
| label* | string | ≤200 chars, the change in one line. |
| links | array | Where the work also lives — issue, ticket, PR or doc URLs. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| experiment | boolean | Measure it against the Ledger. Default false. |
| statusName | string | Start in this status (a name from compass_statuses_list). |
| description | string |
Removes an opportunity from the pipeline (soft delete). For an AI proposal the user doesn't want, this is the dismiss verb; for a captured experiment that was a duplicate or a mistake, the remove verb. To conclude a real experiment without evidence, prefer compass_opportunities_set_status REJECTED — that keeps the record. Ids come from compass_opportunities_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| opportunityId* | string | The change's key (e.g. ACME-12) or id, from compass_opportunities_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"opportunityId"
],
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"opportunityId": {
"type": "string",
"description": "The change's key (e.g. ACME-12) or id, from compass_opportunities_list."
}
}
}The workspace's changes — fixes, chores, new steps, experiments. Each carries `statusName` (the workspace's own word for where it is) and `statusCategory` (TRIAGE undecided, BACKLOG not started, ACTIVE in progress, DONE, CANCELED dropped), plus the older lane key in `status`. `experiment: true` marks a change measured against the Ledger: `ledgerEntryId` null means no expectation registered; `ledger.verdict` carries confirmed/missed after settlement. Scores (value/feasibility/risk) and a workflow anchor are optional. Filter by lane key in `status` or by workflowPageId; compass_statuses_list has the status names.
| Argument | Type | Description |
|---|---|---|
| status | string | Filter to one lane. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| workflowPageId | string | Only opportunities anchored to this workflow page. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"status": {
"enum": [
"NEW",
"QUALIFYING",
"BACKLOG",
"EXPERIMENTING",
"SETTLED",
"REJECTED"
],
"type": "string",
"description": "Filter to one lane."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"workflowPageId": {
"type": "string",
"description": "Only opportunities anchored to this workflow page."
}
}
}The measurement window's boundary: when the user says the experiment's change actually shipped / went live / rolled out, record the landing date. Readings before it are baseline; after it, evidence of effect. Recorded once — it cannot move afterward, so confirm the date. Attaches to the linked Ledger entry as evidence. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| at | string | ISO date the change landed — omit for today. |
| note | string | What shipped, if worth recording. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| applyToMap | boolean | Also move the map from the landing date: who does the change's steps, and how long they take, change as the change's effects say (automate, reassign, assist, relax a check, remove). Confirm with the user first; it can't be undone. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| opportunityId* | string | The change's key (e.g. ACME-12) or id, from compass_opportunities_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"opportunityId"
],
"properties": {
"at": {
"type": "string",
"description": "ISO date the change landed — omit for today."
},
"note": {
"type": "string",
"maxLength": 1000,
"description": "What shipped, if worth recording."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"applyToMap": {
"type": "boolean",
"description": "Also move the map from the landing date: who does the change's steps, and how long they take, change as the change's effects say (automate, reassign, assist, relax a check, remove). Confirm with the user first; it can't be undone."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"opportunityId": {
"type": "string",
"description": "The change's key (e.g. ACME-12) or id, from compass_opportunities_list."
}
}
}File an AI-PROPOSED opportunity into the workspace's review queue — the scouting verb (the opportunity-scout routine's main move). Unlike compass_opportunities_create this needs NO approval: the proposal itself is the human gate — it lands in the Compass Inbox and the cockpit's Needs-you for accept/dismiss. Check compass_opportunities_list first so you never duplicate an idea. Anchor to a workflow page when one fits; score value/feasibility/risk 1–5.
| Argument | Type | Description |
|---|---|---|
| label* | string | ≤200 chars, the opportunity in one line. |
| reasoning | string | One or two sentences on why you're proposing this. |
| riskScore | integer | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| valueScore | integer | |
| description* | string | What it is and why it's worth trying, grounded in the map. |
| workflowPageId | string | Workflow page to anchor to, when one fits. |
| feasibilityScore | integer |
The honesty mechanism: write what the experiment is expected to change BEFORE evidence exists. Creates a Ledger decision entry and links it to the opportunity — never backfill an expectation to match an outcome. Bind a metric (ledger_metrics_list) + comparator + target when the expectation is measurable; readings then land on the entry as evidence automatically. One expectation per opportunity — revise by superseding in Ledger. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| target | number | Target value, in the metric's unit (hours for time). |
| deadline | string | ISO date the expectation is due by. |
| metricId | string | Ledger metric to bind (requires target). From ledger_metrics_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| comparator | string | |
| fromRollup | object | Instead of metricId: measure it off the change's workflow roll-up — a step's (nodeId) or the whole workflow's hands-on time, waiting, labor, or hard cost, per run or per month. Creates a daily-fed metric with the last 30 days rebuilt from the map's history, so the before is on record. Needs a target; comparator defaults to <=. |
Move a change to one of the workspace's statuses, by name (compass_statuses_list has them — e.g. "In review"). The old lane keys (NEW / QUALIFYING / BACKLOG / EXPERIMENTING / SETTLED / REJECTED) still work and land on that lane's default status. Only changes marked as experiments follow the Ledger: when an experiment enters an In progress status with no registered expectation, offer compass_opportunities_register_expectation; when it enters Done with its Ledger entry still open, offer ledger_entries_settle. Other changes just move. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| status | string | A lane key. Use this or `statusName`. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| statusName | string | A status name from compass_statuses_list. Use this or `status`. |
| opportunityId* | string | The change's key (e.g. ACME-12) or id, from compass_opportunities_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"opportunityId"
],
"properties": {
"status": {
"enum": [
"NEW",
"QUALIFYING",
"BACKLOG",
"EXPERIMENTING",
"SETTLED",
"REJECTED"
],
"type": "string",
"description": "A lane key. Use this or `statusName`."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"statusName": {
"type": "string",
"description": "A status name from compass_statuses_list. Use this or `status`."
},
"opportunityId": {
"type": "string",
"description": "The change's key (e.g. ACME-12) or id, from compass_opportunities_list."
}
}
}Corrects an opportunity's content: label, description, priority, what done means, the 1–5 value / feasibility / risk scores, the owner (a PERSON page), notes, tags, workflow anchor, external link, visibility. Fields you omit are untouched; the lane is NOT here — move it with compass_opportunities_set_status. Opportunity ids come from compass_opportunities_list. May return `needs_confirmation` — say what you're changing and wait.
| Argument | Type | Description |
|---|---|---|
| tags | array | New tag set — replaces existing tags. |
| label | string | New one-line label (2–200 chars). |
| assignee | any | The workspace member doing the work, by email or user id; null unassigns. They're notified. |
| doneWhen | string | What's true when it's done, that someone else could check (≤1,000 chars). |
| priority | any | How soon it matters; null clears it, and the map's suggestion shows again. |
| riskScore | integer | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
All typed edges touching one page, both directions, each hydrated with the other endpoint's page summary. Use this to understand a subject's neighborhood before adding to it. Current connections only, unless includeEnded — then also relationships that have ended (validTo in the past), for questions like who handled this before.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The page id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| includeEnded | boolean | Also return connections that have ended. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The page id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"includeEnded": {
"type": "boolean",
"description": "Also return connections that have ended."
}
}
}Creates a typed page in the workspace's Compass compendium. Check `compass_pages_list` first — don't create a page for a subject the map already has; link to it instead. May return `needs_confirmation` — if so, tell the user what you're proposing, wait for their approval, then re-call with the approvalId. Only record what the human has actually told you.
| Argument | Type | Description |
|---|---|---|
| body | string | Markdown body shaped to the type (steps for WORKFLOW, role/contact sections for PERSON, etc.). |
| tags | array | Optional tags. |
| type* | string | Page type for this subject. PERSON = a specific individual; ROLE = a job, separate from whoever holds it (people hold roles); VALUE = something the business won't sacrifice; PRIORITY = an outcome it's pushing toward; AUDIENCE = who the work is for; OFFERING = what the business delivers. |
| title* | string | ≤80 chars, sentence case, no filler verbs. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| visibility | string |
Moves a page to the trash (soft delete — its connections and anchored opportunities go with it, and compass_pages_restore brings the whole set back). Use this to REMOVE a page you or an extraction created wrongly, or one the user says no longer belongs on the map; to fix a wrong title or body, use compass_pages_update instead. Page ids come from compass_pages_list / compass_pages_search. May return `needs_confirmation` — name the page and wait for approval.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | Id of the page to delete. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "Id of the page to delete."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
}
}
}Fetches one Compass page by id, including its full Markdown body, header fields, and any attached Napkin sketches — view an attached sketch's actual drawing with `napkin_boards_view` (its boardId) before discussing it.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The page id (from compass_pages_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The page id (from compass_pages_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists pages in the active workspace's Compass compendium. Optional `type` filter narrows to one node type (WORKFLOW, PERSON, ROLE, SYSTEM, PAIN_POINT, DOCUMENT, VALUE, PRIORITY, AUDIENCE, OFFERING). Returns summaries, 50 at a time (`limit` / `offset`, `total` and `nextOffset` in the result) — fetch one with `compass_pages_get` for the full body. When you know what you're looking for, `compass_pages_search` is the better first call.
| Argument | Type | Description |
|---|---|---|
| type | string | Narrow to a specific page type (WORKFLOW, PERSON, ROLE, SYSTEM, PAIN_POINT, DOCUMENT, VALUE, PRIORITY, AUDIENCE, OFFERING). |
| limit | integer | Page size, default 50. Prefer compass_pages_search when you know what you're looking for. |
| offset | integer | Skip this many, for the next page. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"type": {
"type": "string",
"description": "Narrow to a specific page type (WORKFLOW, PERSON, ROLE, SYSTEM, PAIN_POINT, DOCUMENT, VALUE, PRIORITY, AUDIENCE, OFFERING)."
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Page size, default 50. Prefer compass_pages_search when you know what you're looking for."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Skip this many, for the next page."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Puts a trashed page back on the map, together with exactly the connections and opportunities its delete took. Use when the user wants a deleted page back (the pageId from the earlier compass_pages_delete, or from the Compass trash). Fails with not_found when the page is already live or never existed. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | Id of the deleted page. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "Id of the deleted page."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
}
}
}Keyword search over page titles, bodies, and tags (case-insensitive substring match), paginated. The fast way to check whether a subject already has a page before creating or linking. Returns summaries with a 300-char body snippet — fetch full text with `compass_pages_get`.
| Argument | Type | Description |
|---|---|---|
| q* | string | Search term. Use the most distinctive word or phrase for the subject ('Zendesk', 'invoice approval') — not full sentences. |
| type | string | Narrow to one page type. |
| limit | integer | Results per page, 1-25. Default 10. |
| offset | integer | Pagination offset. Default 0. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"description": "Search term. Use the most distinctive word or phrase for the subject ('Zendesk', 'invoice approval') — not full sentences."
},
"type": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "Narrow to one page type."
},
"limit": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Results per page, 1-25. Default 10."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Pagination offset. Default 0."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Edits an existing page's title, description, body, tags, header fields, or visibility — use this to FIX what you (or an extraction) got wrong instead of creating a duplicate. Fetch the current page with `compass_pages_get` first and preserve what the human wrote; title / body / tags replace the field wholesale, while `headerFields` MERGES over the current ones (send only the keys you're changing — 'set the owner' leaves status alone). Page ids come from compass_pages_list. May return `needs_confirmation` — tell the user what you're changing, wait for approval, then re-call with the approvalId.
| Argument | Type | Description |
|---|---|---|
| body | string | New Markdown body — replaces the whole body. |
| tags | array | New tag set — replaces existing tags. |
| title | string | New title (≤200 chars). |
| pageId* | string | Id of the page to edit. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| visibility |
Reads every mapped workflow against one PRIORITY (or VALUE) and proposes the steps that move it (or where the business lives the value), one marked as what holds a priority back. Proposals wait for a person to keep them on the priority's page or in the Inbox, except in workflows someone tied to it (a serves link), where they're kept at once. Steps already tied or proposed aren't proposed again, so it's safe to run as the map grows. Use it after a priority is named and workflows are mapped, or when someone asks what moves a priority.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The PRIORITY or VALUE page id. |
| workspace | string | Workspace slug. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The PRIORITY or VALUE page id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
}
}
}Returns the Napkin diagram that holds a WORKFLOW page's steps, creating it when the page has none. If the page body has a ```mermaid block, it moves into the diagram verbatim (node ids kept, so changes anchored to a step still point at it) and leaves the body. Then edit the steps with napkin_diagrams_update using the returned diagramId. One diagram per workflow holds every step anyone has described — when two people describe the same process differently, add the steps to this one diagram rather than making a second. A step that is itself a workflow is a node whose meta ref is { type: 'page', id: <that workflow's page id> }. compass_pages_get returns processDiagramId when one exists. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The WORKFLOW page id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
}
}
}One ROLE page's story: hands-on hours a month by kind of work (rote, judgment, relationship, sign-off) before its first change or Task landed and now; what landed and when; new work it took on (checks inside Tasks, Tasks it looks after, work a change added), with whether each has settled; the role's size (people × hours each, `hoursAssumed` when the hours are a full-time default) and how much of its month is documented; and the latest analysis, when someone ran one: options for where saved hours could go, each with the stage of its change (proposed = looking into, agreed, done = in place, confirmed, dropped), and skills. Saved hours in a role with under half its month documented are unproven: say so. Talk about the role, never about a person.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| rolePageId* | string | The ROLE page's id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rolePageId"
],
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"rolePageId": {
"type": "string",
"minLength": 1,
"description": "The ROLE page's id."
}
}
}Every role in the workspace in one row each, changed or not: hours documented against its working month, hours a month saved, saved hours by stage (looking into, agreed, in place, confirmed, not placed yet), judgment work before and now, new work, and why a role wants attention (unproven savings, saved hours nobody is placing, no documented steps, no headcount). Plus totals. Use compass_role_story for one role's detail. Talk about roles, never about people.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Changes whose effects reach a WORKFLOW's steps — or any nested workflow's — plus changes anchored to it with no effects yet, each with what it does per step. Pass their ids to compass_workflow_rollup's changeIds to project the workflow after them.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The WORKFLOW page id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}The statuses this workspace's changes move through, in board order — the names people use. Each sits in a group: Undecided (TRIAGE), Not started (BACKLOG), In progress (ACTIVE), Done (DONE), Dropped (CANCELED). Groups are stable across workspaces; names aren't, so use the names when talking to people and the groups when reasoning about progress. Move a change with compass_opportunities_set_status.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Every claim about a WORKFLOW's steps, oldest first: the step (nodeId; null = the workflow as a whole), the role or person (subject), the relation, who says so (sourceKind + sourceLabel), when it was true (validFrom/validTo), and origin — AI_PROPOSED claims are waiting for a person to review. Claims that disagree coexist; each keeps its source.
| Argument | Type | Description |
|---|---|---|
| nodeId | string | Narrow to one step. |
| pageId* | string | The WORKFLOW page id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"nodeId": {
"type": "string",
"description": "Narrow to one step."
},
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Propose claims about who does what in a WORKFLOW, and what each step is done in, from what someone said. Each claim names a step (nodeId from compass_workflow_steps), a page (subjectPageId: a ROLE or PERSON, or an AUDIENCE when a customer or partner does the step; for uses a SYSTEM or DOCUMENT; for impacts a PRIORITY; for holds_to a VALUE), and a relation: owns (accountable for it), does (does the work), approves (signs off), consulted (asked for input), does_not_do (says they don't do it — an answer, not a gap), uses (the step is done in this SYSTEM, or with this DOCUMENT; a step a system runs on its own gets uses and no doer), impacts (the step moves this PRIORITY: where the priority is won or lost; pass limits: true on the one step holding it back most), holds_to (the business lives this VALUE at the step). Propose who and what in together, in one call per workflow. Claims land as proposals for a person to accept in Compass; they don't count until then, except in a conversation about the map's questions, where what the person tells you (sourceKind 'user') is kept straight away. Always say who said it: sourceKind 'interview' + the interview id, 'email_thread' + the thread id, 'prism_report' + the desk-research report id, or 'page' + the DOCUMENT or PERSON page id. Prefer the ROLE when the person speaks for their role, the PERSON when it's specific to them. Record a disagreement as its own claim rather than skipping it. When someone says a step happens that isn't in the diagram, add the step with napkin_diagrams_update first. Re-proposing an existing claim from the same source returns it.
| Argument | Type | Description |
|---|---|---|
| claims* | array | |
| pageId* | string | The WORKFLOW page id. |
| sourceId | string | The interview, email thread, Prism report or page id, for those kinds. |
Propose estimates from what someone said, as ranges — people know "20 minutes to an hour", not "37 minutes"; when they give one number, use it for both ends. Each item is either a `measure` or a `gate` on a step (nodeId from compass_workflow_steps): - measure.metric `working`: hands-on minutes per run (low/high). - measure.metric `waiting`: minutes the work sits idle before or inside the step — ask about this separately; it's usually most of the waste. - measure.metric `hardCost`: money that isn't anyone's time (amount, currency, per run or month). - measure.metric `frequency` with nodeId null: how often the workflow runs (low/high per day, week, month, or year); with variantId, how often that variant runs. - gate: approval, handoff, rekey (typing the same data into another system), or rework, with returnRate (0–1) when they know how often it sends work back. Pass subjectPageId (a ROLE or PERSON) when the time is one person's or role's — it prices the time through that role's rate. Always say who said it. Proposals count once someone accepts them in Compass.
| Argument | Type | Description |
|---|---|---|
| items* | array | |
| pageId* | string | The WORKFLOW page id. |
| sourceId | string | The interview, email thread, Prism report or page id, for those kinds. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| sourceKind | string |
Builds a step suggestion the way Compass's Build button does: makes its change if it isn't one yet, then the thing in Workbench — a flow drafted from the step itself (who does it, its times, systems, write-up, attachments, interview notes) and its checklist; a shim named for the decision; or a task whose sentence is the steps. Use this, not workbench_flows_scaffold, whenever the work came from a step suggestion. Returns what was built and, for a flow, what the draft still needs. Fails if something's already built for it.
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The WORKFLOW page id the suggestion is on. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | |
| suggestionId* | string | The suggestion id, from compass_step_suggestions_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId",
"suggestionId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The WORKFLOW page id the suggestion is on."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"suggestionId": {
"type": "string",
"description": "The suggestion id, from compass_step_suggestions_list."
}
}
}Your earlier read of a WORKFLOW's steps: for each suggestion, the steps it covers (nodeIds, labels), what could do them (proposal.doer: a flow and its mode, a shim, or a task), whether it does the step or helps (reach), why, and what it would take (checklist, each item met or not). state OPEN is waiting for a person; APPLIED made a change (opportunityId), and `built` is what was built for it in Workbench, if anything. Pass changeId instead of pageId to get the one suggestion a change came from. To build one, use compass_step_suggestions_build — not workbench_flows_scaffold.
| Argument | Type | Description |
|---|---|---|
| pageId | string | The WORKFLOW page id. |
| changeId | string | A change (opportunity) id: the suggestion it came from. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"changeId": {
"type": "string",
"description": "A change (opportunity) id: the suggestion it came from."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}What the workflows behind a PRIORITY could become, at five levels (Assist, Automate, Re-form, Invert, Dissolve): for each, whether it fits, is already reached, or what it needs; what changes; what it does to the priority; time freed; and the change made from it, if any. Also the recommended level, or `settled` when the work is good as it is. state 'running' means a read is under way; null means none has been read (compass_transformations_read starts one).
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| priorityPageId* | string | The PRIORITY page id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"priorityPageId"
],
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"priorityPageId": {
"type": "string",
"description": "The PRIORITY page id."
}
}
}Creates a Change from one level of a priority's transformations, with its step effects and the priority it serves, and starts drafting in Workbench up to three flows for what the level says to build (`builds`, each `drafting` until ready). Only a level that fits, once per level. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| level* | integer | 1 Assist, 2 Automate, 3 Re-form, 4 Invert, 5 Dissolve. |
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| priorityPageId* | string | The PRIORITY page id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"priorityPageId",
"level"
],
"properties": {
"level": {
"type": "integer",
"maximum": 5,
"minimum": 1,
"description": "1 Assist, 2 Automate, 3 Re-form, 4 Invert, 5 Dissolve."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"priorityPageId": {
"type": "string",
"description": "The PRIORITY page id."
}
}
}Starts reading the five levels for a PRIORITY in the background (a minute or two). Needs at least one kept step that impacts the priority. A read under way is left to finish. Check back with compass_transformations_get.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| priorityPageId* | string | The PRIORITY page id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"priorityPageId"
],
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"priorityPageId": {
"type": "string",
"description": "The PRIORITY page id."
}
}
}Records what someone told you about one level of a PRIORITY's current transformations, in their words or a faithful summary: that they already do it, what rules it out, a system that isn't ready, work still done on paper, and so on. Compass works out what it means in the background: a label for the level, facts kept on the steps they're about (every later reading of those workflows sees them), and open questions to confirm. Then it reads the priority again. Use it whenever a conversation settles something about a level, so it lands on the priority's page, not only in this chat.
| Argument | Type | Description |
|---|---|---|
| said* | string | What's true about the level, as the person said it. |
| level* | integer | 1 Assist, 2 Automate, 3 Re-form, 4 Invert, 5 Dissolve. |
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| priorityPageId* | string | The PRIORITY page id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"priorityPageId",
"level",
"said"
],
"properties": {
"said": {
"type": "string",
"maxLength": 2000,
"minLength": 1,
"description": "What's true about the level, as the person said it."
},
"level": {
"type": "integer",
"maximum": 5,
"minimum": 1,
"description": "1 Assist, 2 Automate, 3 Re-form, 4 Invert, 5 Dissolve."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"priorityPageId": {
"type": "string",
"description": "The PRIORITY page id."
}
}
}Newest first: steps added to or dropped from the diagram (and by whom), and claims about who does what or what a step takes — said, corrected (with what they replaced), withdrawn, or accepted from a proposal — each with its source. This is when we LEARNED things; when they were true is each claim's validFrom/validTo. Use it to brief someone on what changed in the picture, or to see what an interview added.
| Argument | Type | Description |
|---|---|---|
| since | any | Only what was learned on or after this date. |
| pageId* | string | The WORKFLOW page id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"since": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
],
"description": "Only what was learned on or after this date."
},
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Per run and per month: hands-on minutes, waiting minutes, labor cost (hands-on time priced through each role's hourly rate), and hard costs, each as a low–high range, with every step's share and its gates (approvals, handoffs, re-keying, rework). A step that is itself a workflow uses that workflow's roll-up unless it has its own estimate. `coverage` says how many steps are timed — always say how much of the total rests on estimates before quoting it, and never present a range as one number. `unpricedRoles` are roles doing timed work with no hourly rate; their time counts and its cost doesn't. Where the waiting dwarfs the hands-on time, or a gate rarely sends anything back, is usually where the improvement is. `at` reads the estimates as of a date; `variantId` rolls up one variant.
| Argument | Type | Description |
|---|---|---|
| at | any | How things were on this date (YYYY-MM-DD). Default today. |
| pageId* | string | The WORKFLOW page id. |
| knownAt | any | Count only what had been said by this date — the picture as we knew it then. |
| changeIds | array | Project the workflow as these changes would leave it (ids from compass_scenario_changes). Compare with a call without them: before vs after, what stays human, overlapping changes. |
| variantId | string | A variant id from compass_workflow_steps. |
| workspace |
Every step in a WORKFLOW page's steps diagram, in diagram order, with its phase, whether it is itself a workflow (subWorkflowPageId), and who the map says owns, does, approves, is consulted on, or doesn't do it, and `uses`: the systems or documents it's done in. `unknown: true` means nothing that counts says who does the step or what it's done in — those are the questions worth asking in an interview. A step with `uses` and nobody on it is one a system runs; don't ask who does it. `disputed` lists roles or people with conflicting claims; ask about those rather than picking a side. `proposals` counts claims waiting for review. `variants` are named subsets of the steps ("rush job", "enterprise client"); each step lists the variants it belongs to. Returns no steps when the workflow has no diagram yet (compass_process_diagram_ensure makes one).
| Argument | Type | Description |
|---|---|---|
| pageId* | string | The WORKFLOW page id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Without a tag: every tag in use across the workspace with how many entities carry it, most-used first — the vocabulary the team already organizes by. With a tag: everything filed under it across every tool, each with its kind, id, title, and path. Use it to reuse existing labels instead of inventing near-duplicates, and to answer 'show me everything about X' when X is a label.
| Argument | Type | Description |
|---|---|---|
| tag | string | A tag to expand into its items. Omit to list tags. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"tag": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "A tag to expand into its items. Omit to list tags."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Returns the tags on a batch of entities of one kind — the labels galleries organize by. Ids come from the kind's list/get tool or from search_workspace. Use it before entity_tags_set so you replace the full set knowingly, and to answer 'what is this filed under'. Entities the user can't see are omitted.
| Argument | Type | Description |
|---|---|---|
| ids* | array | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| entityKind* | string | Which kind the ids belong to. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entityKind",
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"maxItems": 100,
"minItems": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"entityKind": {
"enum": [
"workbench_flow",
"workbench_task",
"workbench_kb",
"compass_page",
"compass_opportunity",
"caliper_dataset",
"caliper_rubric",
"caliper_eval",
"caliper_review",
"caliper_spec",
"caliper_source",
"ledger_entry",
"ledger_metric",
"napkin_board",
"napkin_deck",
"napkin_doc",
"napkin_sheet",
"napkin_diagram",
"prism_field",
"prism_study"
],
"type": "string",
"description": "Which kind the ids belong to."
}
}
}Replaces the FULL tag set on one entity (an empty list clears it). Read the current tags with entity_tags_get first and pass the merged list — this is not additive. Tags are lowercase letters, numbers, spaces, and hyphens; prefer labels already in use (entity_tags_browse) so the workspace's vocabulary stays small. The id comes from the kind's list/get tool or search_workspace.
| Argument | Type | Description |
|---|---|---|
| tags* | array | |
| entityId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| entityKind* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entityKind",
"entityId",
"tags"
],
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9](?:[a-z0-9 -]*[a-z0-9])?$",
"maxLength": 40
},
"maxItems": 50
},
"entityId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"entityKind": {
"enum": [
"workbench_flow",
"workbench_task",
"workbench_kb",
"compass_page",
"compass_opportunity",
"caliper_dataset",
"caliper_rubric",
"caliper_eval",
"caliper_review",
"caliper_spec",
"caliper_source",
"ledger_entry",
"ledger_metric",
"napkin_board",
"napkin_deck",
"napkin_doc",
"napkin_sheet",
"napkin_diagram",
"prism_field",
"prism_study"
],
"type": "string"
}
}
}Fetch the full Markdown body of a specific docs page by its slug. Use this after `search_docs` when the user needs the complete content of a page. No authentication required.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Page slug. Accepts 'compass/api', '/compass/api', or 'docs/compass/api'. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Page slug. Accepts 'compass/api', '/compass/api', or 'docs/compass/api'."
}
}
}Fetch the full Markdown body of one Distributed Cognition essay by slug (from `list_posts`). Link the public URL when citing it to the user. No authentication required.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Essay slug, e.g. from `list_posts`. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Essay slug, e.g. from `list_posts`."
}
}
}Records what happened against an open decision — a manual observation the user reports ('the pilot team says triage feels faster'), an implementation note, or a reference to a Caliper run. Evidence is what settlement later reads, so attach it as it arrives and cite it in the lesson. Metric readings attach themselves via ledger_metrics_record_reading — don't duplicate them here. Fails with conflict on superseded entries. Ids come from ledger_entries_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| data | object | Structured detail worth keeping with the summary. |
| kind | string | Usually `manual`; `caliper_eval_run` with refId for a run; `implementation` when the change shipped. |
| refId | string | Source record id (a Caliper run id, …) when there is one. |
| entryId* | string | The entry the evidence is about. |
| summary* | string | What happened, in one or two sentences. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
Records a memory entry. Every entry is a TITLE (`summary`: one short plain sentence) over a BODY (`rationale`: the detail, markdown welcome) — never put the detail in the title. Three kinds: `decision` — a change being made now; PRE-REGISTRATION IS THE POINT, so `prediction` (what we expect) must be written NOW, before any evidence exists, and never backfilled to match an outcome. `lesson` — a distilled belief the team already holds (`lesson` text required, no prediction). `observation` — a durable fact worth remembering (no prediction): something already true, never something planned. Ideas, pitches, backlog items, and upcoming work are NOT entries — a dated piece of work that carries out a decision is a plan item (ledger_plan_add on that decision), and a running list you keep across runs belongs in a Napkin doc or sheet. When a user states something durable about their business in conversation, offer to capture it as a lesson or observation. When a user shares MEETING NOTES, propose the decisions you find with ledger_entries_draft so they keep or drop each one in Ledger; use this tool for an entry they've asked you to record. Link the Compass pages the entry touches so future consult-before-acting finds it. May return `needs_confirmation` — summarize the entry and wait for approval.
| Argument | Type | Description |
|---|---|---|
| kind | string | decision = a change with a pre-registered expectation; lesson = a belief arriving already settled; observation = a fact that is already true (not a plan, idea, or pitch). |
| lesson | string | What we learned — required for kind=lesson, optional for kind=observation, forbidden on decisions (their lesson is written at settlement). |
| summary* | string | The entry's TITLE: one short plain sentence naming what we did (decision) or the fact itself (lesson, observation). Plain text, no markdown, at most 280 characters — e.g. "Newsletter moves to a biweekly cadence". Everything longer goes in rationale. |
Writes up to 50 entries as DRAFTS: proposals that stay out of the record until a person confirms each one in Ledger's Drafts view. Use it for entries you found rather than were told — decisions in meeting notes, or a team's past changes read from its tracker, pull requests or launch posts (set `fromHistory: true`). For history: take each claim from what the source said AT THE TIME, set `landedAt` to when it shipped, attach the source URL, and leave `rollout` as full unless the source says otherwise. These read as low confidence because they were written down after the fact; say so plainly rather than overstating them. Tell the person how many drafts are waiting and that they review them under Decisions → Drafts. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| drafts* | array | |
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| approvalId | string | |
| fromHistory | boolean | True when the drafts come from a team's past work, not the conversation. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"drafts"
],
"properties": {
"drafts": {
"type": "array",
"items": {
"type": "object",
"required": [
"summary"
],
"properties": {
"kind": {
"enum": [
"decision",
"lesson",
"observation",
"belief"
],
"type": "string",
"default": "decision"
},
"lesson": {
"type": "string",
"maxLength": 4000
},
"source": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000
},
"title": {
"type": "string",
"maxLength": 300
}
},
"description": "Where the claim came from — the ticket, pull request or post."
},
"rollout": {
"enum": [
"full",
"partial",
"controlled"
],
"type": "string",
"description": "full unless the source says it was staged (partial) or had a held-out group (controlled)."
},
"summary": {
"type": "string",
"maxLength": 280,
"minLength": 1,
"description": "The TITLE: one short plain sentence naming the change or fact."
},
"landedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "When the change took effect: the merge, ship or launch date. Set once."
},
"rationale": {
"type": "string",
"maxLength": 4000,
"description": "The BODY. For history, quote what the source said the change was for."
},
"prediction": {
"type": "object",
"properties": {
"claims": {
"type": "array",
"items": {
"type": "object",
"required": [
"source"
],
"properties": {
"hold": {
"type": "object",
"required": [
"kind"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"maximum": 365,
"minimum": 1
},
"kind": {
"type": "string",
"const": "pre_landing"
},
"maxDrop": {
"type": "number",
"default": 0,
"maximum": 1,
"minimum": 0
},
"maxRise": {
"type": "number",
"maximum": 1,
"minimum": 0
}
}
},
"unit": {
"type": "string",
"maxLength": 50
},
"slice": {
"type": "object",
"propertyNames": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$"
},
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"maxItems": 50,
"minItems": 1
}
},
"watch": {
"type": "boolean"
},
"evalId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"source": {
"enum": [
"caliper_eval",
"metric",
"manual"
],
"type": "string"
},
"target": {
"type": "number"
},
"metricId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"comparator": {
"enum": [
">=",
"<=",
">",
"<",
"="
],
"type": "string"
}
}
},
"default": [],
"maxItems": 10
},
"deadline": {
"type": "string",
"maxLength": 40
},
"freeform": {
"type": "string",
"maxLength": 2000
}
},
"description": "Decisions only. For history, the claim the source made at the time, not one fitted to what happened since."
}
}
},
"maxItems": 50,
"minItems": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"fromHistory": {
"type": "boolean",
"description": "True when the drafts come from a team's past work, not the conversation."
}
}
}One entry's full anatomy — the six fields, attached evidence (Caliper runs, measurements, observations), and the supersede chain (what replaced it, or what it replaced). Cite entry ids when telling the user about prior related decisions.
| Argument | Type | Description |
|---|---|---|
| entryId* | string | Entry id (from ledger_entries_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entryId"
],
"properties": {
"entryId": {
"type": "string",
"description": "Entry id (from ledger_entries_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}The workspace's memory: decisions (changes with pre-registered expectations), lessons (distilled beliefs), and observations (captured facts). CONSULT BEFORE ACTING — before proposing a flow change, prompt edit, or process decision, filter by the Compass page it touches (compassPageId) and check whether prior attempts exist and how they settled. Filter status=open for unsettled expectations awaiting evidence (each carries a derived `lapsed` flag — true when its deadline has passed; surface lapsed ones when the user asks what needs attention); kind=lesson for what the team already believes.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search across an entry's summary, rationale, and lesson (case-insensitive). Use it to find the entry about a topic before acting. |
| kind | string | Filter by species: decision (pre-registered expectations), lesson (distilled beliefs), observation (captured facts). |
| cursor | string | Pagination cursor from a prior page. |
| origin | string | Filter by who wrote it (manual, workbench, …). |
| status | string | Filter by lifecycle state (open = awaiting evidence). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
Takes an entry out of the curated ledger — THE remedy when you recorded something wrong (a decision that wasn't made, a duplicate, a fact the user corrects). Reversible from Ledger and fully audited, so it is safe to offer as soon as the user says 'that's not right'. Not for overturning a settled claim the team once believed — a human supersedes that. Fails with conflict if already retracted. Ids come from ledger_entries_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| entryId* | string | The entry to retract. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entryId"
],
"properties": {
"entryId": {
"type": "string",
"description": "The entry to retract."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}The ritual moment: evidence has landed, the expectation closes, the lesson is written. Only propose settlement when attached evidence actually answers the prediction — check `ledger_entries_get` first and cite the evidence in the lesson. `lesson` (what we now believe) is required and permanent; settlement happens exactly once. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| lesson* | string | What we now believe — the distilled, citable lesson. |
| entryId* | string | The open entry to settle. |
| verdict | string | Did the pre-registered expectation hold? `confirmed` every claim came out as hoped, `missed` none did, `mixed` some did and some didn't. Mixed is not a softer miss — "it worked and it cost us something" is usually the most informative result a change can produce, so use it rather than rounding to either side. Only when the entry carries an expectation and the evidence gives a clear answer. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entryId",
"lesson"
],
"properties": {
"lesson": {
"type": "string",
"maxLength": 4000,
"minLength": 1,
"description": "What we now believe — the distilled, citable lesson."
},
"entryId": {
"type": "string",
"description": "The open entry to settle."
},
"verdict": {
"enum": [
"confirmed",
"mixed",
"missed"
],
"type": "string",
"description": "Did the pre-registered expectation hold? `confirmed` every claim came out as hoped, `missed` none did, `mixed` some did and some didn't. Mixed is not a softer miss — \"it worked and it cost us something\" is usually the most informative result a change can produce, so use it rather than rounding to either side. Only when the entry carries an expectation and the evidence gives a clear answer."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Corrects an entry in place — its title (summary), body (rationale), the pre-registered prediction of an OPEN decision (null clears it), or its facet (filing category; editable even after settlement). Works on open decisions, and on lessons, observations, and beliefs (they carry no expectation, so fixing their wording is fine any time). Use to fix a typo, swapped fields, or a misrecorded detail. Never edits kind or lesson. Fails with conflict on a settled decision — its claim is corrected by a human superseding it in Ledger — and on superseded or retracted entries. Entry ids come from ledger_entries_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| facet | any | Filing facet; empty string = unassigned. |
| entryId* | string | The entry to edit: an open decision, or a lesson / observation / belief. |
| summary | string | New title: one short plain sentence, no markdown, at most 280 characters. |
| rationale | string | New body: the detail under the title; markdown is fine. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
The connected servers this workspace exposes to you, with the id a feed needs. Their tools appear to you namespaced as `ext__<name>__<tool>` — call one directly to see what it returns before proposing a feed. A server the workspace has switched off for you is not listed and cannot be fed from here.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
}
}
}Run the same frozen instruction over a past range, so a metric has history instead of starting the day it was set up. Offer this whenever you create a feed — a chart with a year behind it is worth far more than one that begins today, and an expectation can be judged against what normal looked like. Works when the source returns a series; a source that only ever reports 'right now' will write one point. Safe to repeat: overlapping ranges dedupe. Keep ranges to a few hundred points; a run that fills up says so. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| id* | string | Feed id, from ledger_feeds_list. |
| to | string | End of the range. Defaults to now. |
| from* | string | Start of the range, ISO date or instant. |
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id",
"from"
],
"properties": {
"id": {
"type": "string",
"description": "Feed id, from ledger_feeds_list."
},
"to": {
"type": "string",
"description": "End of the range. Defaults to now."
},
"from": {
"type": "string",
"description": "Start of the range, ISO date or instant."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
},
"approvalId": {
"type": "string"
}
}
}Freeze a tool call as a metric's standing source: it runs on the cadence you give and records what it finds, with no model involved. `metric` takes an id or a snake_case slug; an unknown slug starts tracking that metric. Confirm the mapping with ledger_feeds_preview first. Tell the user they can backfill history afterwards with ledger_feeds_backfill. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| label | string | Short name for the feed, e.g. "Weekly signups". |
| metric* | string | Metric id, or a snake_case slug to start tracking. |
| mapping* | object | |
| schedule* | object | |
| toolArgs | object | |
| toolName* | string | The tool's own name on that server. |
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
| approvalId | string | |
| windowHours | integer |
Remove a feed. The readings it already wrote stay — the series is the record and outlives the instruction. Prefer pausing with ledger_feeds_update when the user might want it back. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| id* | string | Feed id, from ledger_feeds_list. |
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Feed id, from ledger_feeds_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
},
"approvalId": {
"type": "string"
}
}
}The standing instructions for how metrics' numbers arrive — which tool each one calls, how often, and how the last run went. Check before proposing a feed so you don't duplicate one, and consult when a user asks why a metric is stale: a feed with a failing last run is usually the answer.
| Argument | Type | Description |
|---|---|---|
| metricId | string | Narrow to one metric (id or slug). |
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"metricId": {
"type": "string",
"description": "Narrow to one metric (id or slug)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
}
}
}Call a connected server's tool once and see what a mapping would pull out of the response — nothing is written and no feed is created. Send no `mapping` for a first look: you get a sample of the response plus the paths that hold numbers. Then send a mapping to confirm it finds the readings you expect. Always do this before ledger_feeds_create; proposing a feed whose mapping you haven't seen work is how a metric fills up with the wrong number. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| mapping | object | How to read the number. Omit on the first look. |
| toolArgs | object | Arguments, exactly as the tool wants them. Use {{from}} / {{to}} (ISO instants) or {{date}} (YYYY-MM-DD) where a time range goes — those are substituted per run, and are what let one feed also backfill. |
| toolName* | string | The tool's own name on that server — NOT the ext__ namespaced form you call it by. |
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
| approvalId | string | |
| windowHours | integer | How far back the preview's window reaches. Default 24. |
| integrationId* | string | From ledger_feed_sources_list. |
Run a feed immediately over its own window and record what it finds. Use it right after creating one to prove the mapping works — a run that comes back `empty` names the path that missed, which is what you fix with ledger_feeds_update. Does not move the feed's schedule. Re-running is safe: readings dedupe per time bucket. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| id* | string | Feed id, from ledger_feeds_list. |
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Feed id, from ledger_feeds_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
},
"approvalId": {
"type": "string"
}
}
}Change a feed's arguments, mapping, cadence, or pause it. Reach for this when a feed's last run reports `empty` (the response shape moved, so the mapping needs a new path) or `error`. Changing the mapping changes what the number means, so say what you're changing and why. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| id* | string | Feed id, from ledger_feeds_list. |
| label | string | |
| enabled | boolean | false pauses it; the definition and history are kept. |
| mapping | object | |
| schedule | object | |
| toolArgs | object | |
| toolName | string | |
| workspace | string | Workspace slug. Omit to use the pinned workspace. |
| approvalId | string | |
| windowHours |
Creates the named presets as real metrics the workspace owns, tagged from the catalog. Safe to repeat: a preset the workspace already has comes back `already_present` rather than creating a second series, and a workspace's own renames and targets are never overwritten. Adopt only what the user agreed to — a metric nobody reads is noise on the Metrics tab, and eight thoughtful ones beat forty. Tell them the metrics start empty and the next step is a feed (ledger_feeds_create) or a first reading. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| slugs* | array | Preset slugs from ledger_metric_presets_list. |
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slugs"
],
"properties": {
"slugs": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 40,
"minItems": 1,
"description": "Preset slugs from ledger_metric_presets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Ready-made metrics a business can start tracking, each with a unit, a cadence, which direction is good, a business surface (facet), and cross-cutting tags. Reach for this when a workspace has few or no metrics, when someone asks what they should be measuring, or when a decision needs a number to settle against and none exists. Filter by `facet` (where it lives in the business) or `tag` (what kind of number it is). Suggest a SMALL set — three to six that fit what you know about this business — and say in one sentence why each one, rather than listing the catalog. Adopt with ledger_metric_presets_adopt. These are starting points: a workspace renames and retargets them freely afterwards.
| Argument | Type | Description |
|---|---|---|
| tag | string | Cross-cutting bucket, e.g. retention, cost, speed. |
| facet | string | Business surface, matching the Ledger facet taxonomy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"tag": {
"enum": [
"revenue",
"growth",
"retention",
"efficiency",
"quality",
"speed",
"cost",
"risk",
"team",
"customer",
"pipeline",
"reliability",
"usage",
"reach",
"cash"
],
"type": "string",
"description": "Cross-cutting bucket, e.g. retention, cost, speed."
},
"facet": {
"enum": [
"product",
"pricing",
"gtm",
"sales",
"people",
"ops",
"tooling",
"finance",
"positioning",
"risk"
],
"type": "string",
"description": "Business surface, matching the Ledger facet taxonomy."
}
}
}Creates a starter's metrics at their levels and links them. Pass `slugs` to keep only some of its metrics; links are made only where both ends exist. Safe to repeat and safe after a different starter: metrics the workspace already has are left as they are and get linked into the tree. Adopt only what the user agreed to. Tell them the metrics start empty and the next step is connecting a source (ledger_feeds_create) or a first reading. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| slugs | array | The starter's metrics to keep. Omit for all of them. |
| starter* | string | Starter slug from ledger_metric_starters_list. |
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"starter"
],
"properties": {
"slugs": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 40,
"description": "The starter's metrics to keep. Omit for all of them."
},
"starter": {
"type": "string",
"description": "Starter slug from ledger_metric_starters_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Starter trees by shape of business or team (subscription software, services firm, online store, sales team, service operation). Each lists its metrics with a level (outcome / driver / activity) and the links between them (which number moves which). Reach for this before ledger_metric_presets_list when a workspace has no metrics yet or asks how its numbers fit together: pick the starter that matches what you know about the business, describe its tree in a sentence or two, and offer to adopt it with ledger_metric_starters_adopt, dropping any metric that doesn't fit.
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}Takes a metric out of the gallery (`archived: true`) or puts it back (`false`). Readings stay, and entries that settled against it still read correctly — this is the cleanup for a metric minted once and abandoned, or one the workspace stopped watching. `metricId` accepts the id or slug from ledger_metrics_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| archived* | boolean | true to archive, false to restore. |
| metricId* | string | Metric id or slug (from ledger_metrics_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"metricId",
"archived"
],
"properties": {
"archived": {
"type": "boolean",
"description": "true to archive, false to restore."
},
"metricId": {
"type": "string",
"description": "Metric id or slug (from ledger_metrics_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Create a metric — a number the workspace watches (triage time, weekly signups, cost per run). Check ledger_metrics_list first; names are unique per workspace. When a user says they want to track or measure something, offer this. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| icon | string | The thing the number counts, e.g. phone for calls, landmark for profit. |
| name* | string | e.g. "Triage time". |
| unit | string | Display unit — "min", "%", "$", "tickets/day". |
| level | string | outcome = what the business is judged on; driver = moves an outcome; activity = daily work. |
| drives | array | Ids of existing metrics this one moves. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | |
| description | string | What the number means and where it comes from. |
One metric's definition (unit, kind, direction, target, cadence) plus its readings newest first and the open decisions bound to it. Use before answering 'how is X trending?' or before recording a reading against it. `metricId` accepts the id or the snake_case slug from ledger_metrics_list. For an event metric whose readings carry labels, `labels` lists each label and its values, largest total first. Pass `slice` to get the series for part of it ("new users in DE"), or `by` to split the series by one label ("new users by country"); either returns `series`, summed per `bucket`.
| Argument | Type | Description |
|---|---|---|
| by | string | Event metrics only. A label name to split the series by. |
| slice | object | Event metrics only. Per label, the values to keep: { country: ["DE", "AT"] } keeps readings from DE or AT; several labels must all match. Names and values come from `labels`. |
| bucket | string | Series bucket when `slice` or `by` is set. Default week. |
| metricId* | string | Metric id or slug (from ledger_metrics_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"metricId"
],
"properties": {
"by": {
"type": "string",
"description": "Event metrics only. A label name to split the series by."
},
"slice": {
"type": "object",
"description": "Event metrics only. Per label, the values to keep: { country: [\"DE\", \"AT\"] } keeps readings from DE or AT; several labels must all match. Names and values come from `labels`.",
"propertyNames": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$"
},
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"maxItems": 50,
"minItems": 1
}
},
"bucket": {
"enum": [
"day",
"week",
"month"
],
"type": "string",
"description": "Series bucket when `slice` or `by` is set. Default week."
},
"metricId": {
"type": "string",
"description": "Metric id or slug (from ledger_metrics_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}The numbers the workspace watches — each with unit, latest reading, and how many open decisions are bound to it. Consult when a user mentions a number that sounds like a tracked metric, and before recording a reading.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Record one observation of a tracked metric. `metricId` accepts a metric id OR its snake_case slug from ledger_metrics_list; an unknown one is a not_found error — check ledger_metrics_list, create it with ledger_metrics_create, or pass `createIfMissing: true` to mint a "measure" metric at that slug in the same call (an "event" metric when the reading carries `labels`). The reading automatically lands as evidence on every open decision whose prediction is bound to this metric — so when a user reports a number ("triage is down to 12 minutes"), offer to record it. For event-kind metrics, omit `value` to count one occurrence. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| at | string | ISO timestamp the reading is for. Defaults to now; set it when backfilling an earlier reading. |
| key | string | Idempotency key (e.g. "2026-w32") — a repeat write with the same key returns the original reading instead of doubling the series. Use for scheduled/recurring recordings. The key is per set of labels, so one key per day can cover every country. |
| note | string | Where the number came from, if worth recording. |
| value | number | The observed value, in the metric's unit. Omit for event-kind metrics to record one occurrence. |
| labels | object | Event metrics only. What this count is broken down by, e.g. { country: "DE", plan: "pro" } — snake_case names, string values. Lets the metric be read and claimed by slice later. Refused on a measure. |
| metricId |
Corrects a metric's name, unit, description, kind (measure / event), direction (which way is good), target, cadence, icon, level, or the metrics it drives (its place in the metric tree). Readings are untouched. Only what you pass changes. The slug is not editable here — external writers address metrics by slug. Fails with conflict when a rename collides with a live metric. `metricId` is the id from ledger_metrics_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| icon | any | The mark the metric wears in every tool: the thing it counts (phone for calls, landmark for profit). "" goes back to the catalog's icon. |
| kind | string | measure = a value each reading; event = a count of occurrences. |
| name | string | |
| unit | string | "min", "%", "$", "tickets/day". |
| level | any | outcome = what the business is judged on; driver = a number that moves an outcome; activity = daily work. "" unplaces it. |
| drives | array | Ids of the metrics this one moves. Replaces the current set; pass the full list. Loops are refused. |
| target | any | Goal value in the metric's unit; null clears. |
Adds a plan item to an OPEN decision (the work that carries it out: a post, a launch step, an email). Omit entryId for a standalone date (a holiday, an event you're only watching). Items are all-day unless you pass startTime with timeZone (and optionally endTime), for a webinar, a scheduled post, or a launch at noon. If the date costs money or time and comes with an expectation, record it as a decision with ledger_entries_create instead. Use repeatWeeklyUntil for a weekly cadence: it writes one row per week (max 60), each movable on its own. Fails with conflict once the decision is settled. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| url | string | Where the work lives (draft, deck, published post). |
| note | string | |
| tags | array | What kind of work it is: blog, video, social, event… Reuse the workspace's existing tags (see ledger_plan_list). |
| dueOn* | string | A calendar day, YYYY-MM-DD. |
| title* | string | |
| endTime | string | Same-day end, after startTime. |
| entryId | string | The open decision this carries out. |
| timeZone | string |
Removes one plan item while its decision is open, for an item added by mistake or work that's no longer planned. If the work was planned and then dropped, prefer ledger_plan_update with status 'skipped' so settlement can see it. Fails with conflict once the decision is settled. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| itemId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"itemId"
],
"properties": {
"itemId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Pass `entryId` for one decision's plan items, or `from` + `to` (YYYY-MM-DD, at most about a year apart) for the calendar: decision spans (recorded day → expectation deadline) plus every dated item inside the window, including standalone dates with no decision. Filter the calendar by `ownerUserId` to answer 'what's mine this week' or to find tomorrow's items to draft. Never use it to compare or rank people's output.
| Argument | Type | Description |
|---|---|---|
| to | string | A calendar day, YYYY-MM-DD. |
| tag | string | Only items with this tag (blog, video, event…). |
| from | string | A calendar day, YYYY-MM-DD. |
| entryId | string | One decision's plan. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| ownerUserId | string | Only items owned by this member. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"to": {
"type": "string",
"description": "A calendar day, YYYY-MM-DD."
},
"tag": {
"type": "string",
"description": "Only items with this tag (blog, video, event…)."
},
"from": {
"type": "string",
"description": "A calendar day, YYYY-MM-DD."
},
"entryId": {
"type": "string",
"description": "One decision's plan."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"ownerUserId": {
"type": "string",
"description": "Only items owned by this member."
}
}
}Edits one plan item while its decision is open: move it (dueOn), rename it, change the owner (null clears), attach the link, or set status (planned | done | skipped). Mark done only when the user says it shipped; a link alone doesn't mean done. Fails with conflict once the decision is settled. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| url | any | |
| note | string | |
| tags | array | Replaces the item's tags. |
| dueOn | string | A calendar day, YYYY-MM-DD. |
| title | string | |
| itemId* | string | |
| status | string | |
| endTime | any | |
| timeZone | any | Required when setting startTime. |
| startTime | any |
Enumerate all available docs pages, optionally filtered by product (e.g. 'compass', 'legal', 'overview'). Use this to discover what slugs exist before calling `get_doc`. No authentication required.
| Argument | Type | Description |
|---|---|---|
| product | string | Optional product slug filter (e.g. 'compass', 'legal', 'overview'). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"product": {
"type": "string",
"description": "Optional product slug filter (e.g. 'compass', 'legal', 'overview')."
}
}
}Lists ZeroWidth's published Distributed Cognition essays (newest first): title, slug, excerpt, byline, public URL. Use this when the user asks what's been published, or when a workspace question might already have an essay behind it — then fetch the full text with `get_post`. No authentication required.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Max essays to return. Defaults to 10. |
| cursor | string | Pagination cursor from a prior call's nextCursor. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"limit": {
"type": "integer",
"default": 10,
"maximum": 20,
"description": "Max essays to return. Defaults to 10.",
"exclusiveMinimum": 0
},
"cursor": {
"type": "string",
"description": "Pagination cursor from a prior call's nextCursor."
}
}
}Creates a blank Napkin board — a sketch (free canvas) or a deck (slides). NOT for written documents: 'draft/write a doc, note, memo' is napkin_docs_create. Use when the user asks for one, or proactively when a sketch/deck would carry the conversation better than words; hand it over with `[[board:ID]]` alone on its own line. For a deck with content, prefer `napkin_deck_write` (one call, whole deck).
| Argument | Type | Description |
|---|---|---|
| kind | string | Defaults to "sketch". |
| name* | string | Board name. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name"
],
"properties": {
"kind": {
"enum": [
"sketch",
"deck"
],
"type": "string",
"description": "Defaults to \"sketch\"."
},
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Board name."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Returns a board's shapes as data — each with its id, kind, position, size, and text — so you can TARGET one to change or remove with napkin_draw (`updates` / `deletes` take these ids and absolute board coordinates). Pen strokes come back as a point count, not the points. For what the board LOOKS like, use napkin_boards_view instead. Board ids come from napkin_boards_list.
| Argument | Type | Description |
|---|---|---|
| boardId* | string | Napkin board id (from napkin_boards_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId"
],
"properties": {
"boardId": {
"type": "string",
"description": "Napkin board id (from napkin_boards_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists sketch boards in the active workspace — name, id, kind (sketch / deck), shape count, last activity. Boards are SPATIAL canvases (drawing, diagrams); the markdown DOCUMENTS are docs — napkin_docs_list. Archived boards are hidden unless `includeArchived`; `q` narrows by name. When the user mentions a sketch, drawing, whiteboard, or napkin, find it here, then LOOK at it with `napkin_boards_view` before discussing its contents. When referring the user to a sketch in your reply, put `[[board:ID]]` alone on its own line — it renders as a clickable card with a live thumbnail.
| Argument | Type | Description |
|---|---|---|
| q | string | Name contains (case-insensitive). |
| kind | string | Only sketches or only decks. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| includeArchived | boolean | Also list archived boards (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"q": {
"type": "string",
"maxLength": 200,
"description": "Name contains (case-insensitive)."
},
"kind": {
"enum": [
"sketch",
"deck"
],
"type": "string",
"description": "Only sketches or only decks."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"includeArchived": {
"type": "boolean",
"description": "Also list archived boards (default false)."
}
}
}Edits a board's details: name, description, visibility, or `archived` (true takes it out of the gallery; false brings it back — the recovery move for a board you created by mistake or the user no longer wants). Board ids come from napkin_boards_list. Boards are working material: no approval card, every change attributed.
| Argument | Type | Description |
|---|---|---|
| name | string | |
| boardId* | string | Napkin board id (from napkin_boards_list). |
| archived | boolean | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"boardId": {
"type": "string",
"description": "Napkin board id (from napkin_boards_list)."
},
"archived": {
"type": "boolean"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"maxLength": 2000
}
}
}Renders the sketch board to an image and returns it so you can SEE what's drawn — layout, arrows, handwriting-style strokes, sticky notes — not just data about it. Use this before answering any question about a sketch's contents, and cite the board when you do — `[[board:ID]]` alone on its own line embeds the sketch card in your reply.
| Argument | Type | Description |
|---|---|---|
| boardId* | string | Napkin board id to render. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId"
],
"properties": {
"boardId": {
"type": "string",
"description": "Napkin board id to render."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Adds pictures to a brand kit section — logo versions, product marks, example screenshots, imagery. Each file comes from a public https `url` (fetched by the server) or, for a small file that isn't online, base64 `data` with a `filename`. PNG, JPEG, WebP, GIF and SVG, up to 20 MB each. Every file becomes a workspace file and an asset on the section, appended after the ones already there. Give each a `name` and a `note` saying what it's for; on logo sections set `backdrop` to the hex of the ground it's made for (#ffffff for a dark logo, #000000 for a reversed one), which is how pages pick the right version. Same rule as napkin_brand_draft: you can change any kit except the workspace's brand. Files that fail are reported and the rest still land.
| Argument | Type | Description |
|---|---|---|
| kind | string | Only when no section has that title yet: the kind of section to make. |
| files* | array | |
| kitId* | string | The kit to add to (napkin_brand_list). |
| section* | string | Title of the section to add them to, like Logo, Imagery or Examples. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kitId",
"section",
"files"
],
"properties": {
"kind": {
"enum": [
"overview",
"voice",
"colors",
"typography",
"logo",
"imagery",
"motion",
"layout",
"examples",
"custom"
],
"type": "string",
"description": "Only when no section has that title yet: the kind of section to make."
},
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000,
"description": "A public https address of the file."
},
"data": {
"type": "string",
"maxLength": 3000000,
"description": "The file as base64, for small files."
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "What to call it in the kit."
},
"note": {
"type": "string",
"maxLength": 500,
"description": "What it's for."
},
"backdrop": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "Hex of the ground it's made for (logos)."
},
"filename": {
"type": "string",
"maxLength": 200,
"description": "File name with extension. Required with `data`."
}
}
},
"maxItems": 25,
"minItems": 1
},
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The kit to add to (napkin_brand_list)."
},
"section": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Title of the section to add them to, like Logo, Imagery or Examples."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Restyles a piece in the brand — the workspace's brand unless you name a kit. `deck` (a board id): every slide gets the brand's background, typefaces, and text colors; sizes are kept. `interface` (an interface id): rewrites its brand.css, so anything styled with var(--brand-*) updates. `accent` makes one of the kit's colors the piece's accent — use it when the piece is about one product or campaign that has its own color in the brand (read the kit's Colors section to see which). Docs need nothing — they read the brand when exported. Check a deck afterwards with napkin_slide_view.
| Argument | Type | Description |
|---|---|---|
| deck | string | Board id of a deck. |
| kitId | string | A brand kit id from napkin_brand_list. Omit for the workspace's brand. |
| accent | string | Name of one of the kit's colors to use as this piece's accent. |
| interface | string | Interface id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"deck": {
"type": "string",
"description": "Board id of a deck."
},
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "A brand kit id from napkin_brand_list. Omit for the workspace's brand."
},
"accent": {
"type": "string",
"maxLength": 60,
"minLength": 1,
"description": "Name of one of the kit's colors to use as this piece's accent."
},
"interface": {
"type": "string",
"description": "Interface id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Finds words the brand says to avoid in a piece of writing, with what to say instead and why. Pass `text`, or a deck (`boardId`) or doc (`docId`) to check its words. Run it on your own drafts before handing them back.
| Argument | Type | Description |
|---|---|---|
| text | string | Text to check. |
| docId | string | A doc to check. |
| kitId | string | A brand kit id from napkin_brand_list. Omit for the workspace's brand. |
| boardId | string | A deck or sketch to check. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"text": {
"type": "string",
"maxLength": 100000,
"description": "Text to check."
},
"docId": {
"type": "string",
"description": "A doc to check."
},
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "A brand kit id from napkin_brand_list. Omit for the workspace's brand."
},
"boardId": {
"type": "string",
"description": "A deck or sketch to check."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Creates a new brand kit, or edits one that is NOT the workspace's brand. Use it when someone asks you to put their brand together (from their site, a deck, or what they tell you) or to try a variation. You can't change the workspace's brand itself — make a draft and tell the user they can choose it in Napkin's Brand section. A kit is a document of sections, each with `title`, `kind` (overview, voice, colors, typography, logo, imagery, motion, layout, examples, custom), markdown `body`, and `rules` ({rule, why}); colors sections hold `swatches` ({name, value: 6-digit hex, note}), typography sections hold `faces` ({name: what it's for, family: a font name or sans / serif / mono / rounded / marker, note}), voice sections hold `use` and `avoid` ({term, instead, why}), and any section can hold `assets` ({fileId: an image already in the workspace's files, name, note, backdrop: hex}) — logo versions, example images — and `links` ({url, title, note}). An examples section holds work that gets the brand right: screenshots as assets and pages as links, each with a note on what makes it good. Exact numbers (timings, spacing) go in the section's prose. New kits start with empty standard sections plus the workspace's colors. `content.sections` upserts by title (or id): fields you pass replace, lists inside replace, sections you don't mention are kept; `removeSections` drops by title. `content.uses` says how Napkin uses the brand — color roles (ink, muted, background, surface, accent, accent2) and fonts (heading, body, mono) — by swatch or face NAME. Give every rule a `why`: the reason is what lets people decide cases the rule doesn't cover.
| Argument | Type | Description |
|---|---|---|
| name | string | |
| kitId | string | Kit to edit. Omit to create a new kit. |
| content | object |
Shows you the pictures in a kit's Examples sections — screenshots of work that gets the brand right — with each one's note on what makes it good, plus the example links. Look before you design a deck, page or interface in the brand, and hold your work to the same bar: the layouts, density, type sizes and use of color you see there.
| Argument | Type | Description |
|---|---|---|
| kitId | string | Kit to look at. Omit for the workspace's brand. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Kit to look at. Omit for the workspace's brand."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Gets the font files for a kit's typefaces from Google Fonts and keeps them in the kit, so decks, slide pictures and the canvas draw the brand's real typefaces instead of a stand-in. Only typefaces that name a family (like Poppins) and don't have files yet are fetched. Works on any kit, including the workspace's brand: it adds the files for the typefaces the kit already names and changes nothing else. A typeface Google doesn't have is reported back; the user can upload its files in the kit's typography section.
| Argument | Type | Description |
|---|---|---|
| kitId | string | Kit to fetch fonts for. Omit for the workspace's brand. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Kit to fetch fonts for. Omit for the workspace's brand."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Reads a brand kit — the workspace's brand unless you name another. READ THIS BEFORE writing or designing anything for the workspace: a deck, a doc, an interface, copy. Returns `brief` (the whole kit as markdown: every section — overview, voice, colors, typography, imagery, motion, and whatever else the team wrote — with the reason behind each rule; follow the reasons when a case isn't covered), `css` (the `--brand-*` variables; interfaces already link it as brand.css, so style with var(--brand-accent) etc. rather than hex values), and `tokens` (the resolved values Napkin uses). Before any kit exists it returns values from the workspace's colors with `kit: null`.
| Argument | Type | Description |
|---|---|---|
| kitId | string | A brand kit id from napkin_brand_list. Omit for the workspace's brand. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "A brand kit id from napkin_brand_list. Omit for the workspace's brand."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists the workspace's brand kits: id, name, description, and which one is the workspace's brand (`isDefault`). Most workspaces have one. Use napkin_brand_get to read a kit.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Look at the pictures in a brand kit — logos, product marks, footage stills, layout references, examples — before you use them. Without `section` or `names` it lists every picture by section with its note, so you know what exists. With `section` (a section title, like Imagery) or `names` (pictures' names as the brief lists them) it shows you those pictures, up to 8 at a time. Look before you build a design around a picture: whether a photo has room for text, which part of it carries the color, and whether it suits texture inside type are things you can only tell by seeing it.
| Argument | Type | Description |
|---|---|---|
| kitId | string | A kit from napkin_brand_list. Omit for the workspace's brand. |
| names | array | Show these pictures, by name. |
| section | string | Show the pictures in this section. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "A kit from napkin_brand_list. Omit for the workspace's brand."
},
"names": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"maxItems": 8,
"description": "Show these pictures, by name."
},
"section": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Show the pictures in this section."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Builds a designed deck: each slide is a layout with its slots filled, or HTML and CSS you write; a real browser lays it out, and it becomes an ordinary Napkin deck people can edit. Use this whenever a deck should look designed — it's how to get layout, big numbers, color blocks, and pictures right. LAYOUTS FIRST - For ads, posts, carousels and title slides, start from a layout (napkin_layouts_list): give `layout` and `slots` instead of `html`. Layouts adapt to every size, fit their text, keep to each size's safe zones, and use the brand's own logos. A slide made from a layout remembers it, so when someone resizes it, it's laid out again instead of scaled. - A set of ads is one slide with `sizes`: ["1:1","4:5","9:16","1.91:1"] — each size gets its own arrangement. - Write HTML only for something no layout does. HOW TO WRITE A SLIDE - `html` is the inside of one slide: a `.slide` box 960×540 px (the deck's own size if it has one). Margins are reset; lay out with flexbox or grid, padding and gap. Put each slide's CSS in a <style> block inside its html, or shared CSS in `css`. - Read the brand first (napkin_brand_get). Style ONLY with its variables: var(--brand-ink), var(--brand-muted), var(--brand-background), var(--brand-surface), var(--brand-accent), var(--brand-accent-2), var(--brand-color-<color name>), var(--brand-font-heading), var(--brand-font-body), var(--brand-radius). Headings already use the heading face. - Pictures from the brand kit: <img src="kit:<file name exactly as the brief lists it>">, sized with CSS; object-fit: cover crops to fill, contain fits whole. Any workspace image: src="file:<file id>". - What carries over: boxes with a solid background, border, and rounded corners; text, including bold, italic, color, and size changes inside a line; pictures. What doesn't: gradients, shadows, background images, inline SVG — use solid color boxes instead. - Design like a designer: one idea per slide, a clear hierarchy, big numbers set large in the accent color, generous space, text 18px or larger (never under 14px), and something visual on most slides — a color panel, a photo, the logo. Keep every slide on the brand's own palette and voice. - Use the brand's own pictures. Put the logo on the title and closing slides (the reversed one on dark color), and use the kit's photos and icons where they carry the point — the brief lists every file under "Files", by name. - Say only what's true. Facts, figures, prices, eligibility, and how things work come from the brand kit and from what the user told you — never invent them. When a slide needs a fact you don't have, leave it out or ask. HOW TO USE IT - New deck: pass `name` and all `slides`. Rebuild a deck: pass `boardId` and all `slides` (replaces everything on it). - Ads, posts and other non-slide pieces: pass `size` — a key like `1:1` (square post, 1080×1080), `4:5` (portrait post), `9:16` (story or reel), `1.91:1` (LinkedIn or Facebook landscape), `og` (link preview), `300x250` or `728x90` (display ads). The `.slide` box is then that shape with its long side 960 px, so type sizes mean what they do on a slide, and the deck exports at the size's real pixels. A single ad is a one-slide deck; a carousel is a deck at `1:1` or `4:5`. - A set of ads — the same ad at several sizes, or several headlines — is one deck: give each slide its own `size`. Lay each size out for its own shape rather than squeezing one layout into all of them (a 9:16 story stacks what a 1.91:1 landscape puts side by side), and keep text out of the outer 7% of every edge and the top and bottom 14% of a 9:16. The deck's PNG export names each file by its pixels. Fix one slide: `boardId`, `slide` (1-based), and a single slide. Add slides: `append: true`. - The result lists each slide's `warnings` — text that overflows its box or the slide, overlapping text, text too small, low contrast, pictures that didn't load — and shows you a picture of every slide it made. Fix every warning and anything that reads badly in the pictures by recomposing just that slide. The contrast check is the standard one (4.5:1 for small text, 3:1 for large or bold text), so a contrast warning is real: darken the color, lighten the background, or set the text larger; never explain it away. You don't need napkin_slide_view afterwards: the pictures are the slides. - Cite the deck with [[board:ID]] alone on its own line.
Exports a deck's slides as PNG files at each slide's real pixels — a square post at 1080×1080, a story at 1080×1920, a leaderboard at 728×90 — ready to upload to an ad platform or a social post. One slide comes back as a PNG; several as a .zip named by deck, slide and size. Hidden slides are left out. The file is saved to the workspace's files; give the user `downloadUrl` (it opens for anyone signed in to the workspace) and say it's also in their files. Slide numbers and the workspace mark aren't drawn. For a PDF or PowerPoint, the user exports from the deck's File menu.
| Argument | Type | Description |
|---|---|---|
| slides | array | Just these slides (1-based, as the deck shows them). Omit for every slide. |
| boardId* | string | The deck to export. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId"
],
"properties": {
"slides": {
"type": "array",
"items": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1
},
"maxItems": 60,
"description": "Just these slides (1-based, as the deck shows them). Omit for every slide."
},
"boardId": {
"type": "string",
"description": "The deck to export."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Returns a Napkin deck as a markdown outline — one section per slide in presentation order, with slide titles, text content (bold + bullets preserved), empty layout stubs still awaiting content, and a summary of drawn marks. This is the cheap way to know what a deck SAYS; use `napkin_slide_view` when you need to see how a specific slide LOOKS. Works on any board that has slides. Cite the deck with `[[board:ID]]` alone on its own line.
| Argument | Type | Description |
|---|---|---|
| boardId* | string | Napkin board id (a deck). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId"
],
"properties": {
"boardId": {
"type": "string",
"description": "Napkin board id (a deck)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Paints every slide of a deck with a theme — slide background, heading and body typefaces, and text colors — in one call, the same as picking it in the deck's theme menu. Font sizes are kept. Prefer "brand" (the workspace's own brand kit) unless the user asks for something else. Built-in themes: plain (Helvetica on white. Gets out of the way.); editorial (Garamond headings on cream. Reads like a document.); stage (Helvetica, light on dark, for a projected room.); blueprint (Consolas headings on mist. For technical decks.); warm (Rounded on amber. Softer than it sounds.); notebook (Marker headings. Keeps the sketchbook feel.). For one-off colors or sizes on a single shape, use napkin_draw's `updates` instead. Check the result with napkin_slide_view.
| Argument | Type | Description |
|---|---|---|
| theme* | string | `brand` for the workspace's brand kit, `brand:<kit id>` for a particular kit (napkin_brand_list), or a built-in theme key. |
| accent | string | Brand themes only: the name of one of the kit's colors to use as this deck's accent instead of the kit's own — for a deck about one product or campaign that has its own color in the brand. |
| boardId* | string | Napkin board id (a deck). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId",
"theme"
],
"properties": {
"theme": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "`brand` for the workspace's brand kit, `brand:<kit id>` for a particular kit (napkin_brand_list), or a built-in theme key."
},
"accent": {
"type": "string",
"maxLength": 60,
"minLength": 1,
"description": "Brand themes only: the name of one of the kit's colors to use as this deck's accent instead of the kit's own — for a deck about one product or campaign that has its own color in the brand."
},
"boardId": {
"type": "string",
"description": "Napkin board id (a deck)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Creates a deck from a markdown outline — the SAME dialect `napkin_deck_outline` reads back, so any deck you've read shows the format. Decks are SLIDES for presenting; a prose document ('write this up', 'draft a doc') is napkin_docs_create instead. Rules: `## Heading` starts a slide (heading becomes the slide title and its biggest text block); optional trailing `[layout: title | section | title-body | title-lead | two-column | three-column | comparison | statement | quote | closing | blank]`; body lines fill the layout's remaining text areas in order, split into areas by a line containing only `---`; `- ` bullets are kept as bullets. Slides default to title-body (or title, when bodyless). Layout text areas you don't fill stay as visible prompts for the user. Example: ## Q3 Review [layout: title] What happened, what's next ## Revenue [layout: title-body] - up 40% QoQ - churn flat ## Bets [layout: two-column] Double down on decks --- Sunset legacy plans After writing, cite the deck with `[[board:ID]]` alone on its own line — the user opens it from there.
| Argument | Type | Description |
|---|---|---|
| name* | string | Deck name. |
| outline* | string | The markdown outline (dialect above). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name",
"outline"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Deck name."
},
"outline": {
"type": "string",
"maxLength": 50000,
"minLength": 1,
"description": "The markdown outline (dialect above)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Create a Napkin diagram — an interactive FLOWCHART (process, decision tree, system map), not a doc (napkin_docs_create) or drawing canvas (napkin_boards_create). Pass the mermaid source. Use for process maps the user asked you to draw. After creating, cite it as `[[diagram:ID]]` alone on its own line — it renders as a clickable card. NEVER cite it as [[board:ID]].
| Argument | Type | Description |
|---|---|---|
| title | string | |
| source | string | Mermaid flowchart source. Start with `flowchart TD` (top-down) or `flowchart LR` (left-right). Declare shaped nodes — `A["Rect"]`, `B("Rounded")`, `C{"Decision"}`, `D(["Stadium"])`, `E(("Circle"))`, `F{{"Hexagon"}}` — and link them with `A -->|label| B`, `A -.-> B` (dotted), or `A ==> B` (thick). Group steps with `subgraph Name["Title"] ... end`. Color a node with a trailing `style A fill:#fee2e2` line. Only the flowchart subset is supported. Each label is a short name on one line, written plainly: no `\n`, no backslashes before quotes. A step's label is its name everywhere in Compass. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"title": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"source": {
"type": "string",
"maxLength": 200000,
"description": "Mermaid flowchart source. Start with `flowchart TD` (top-down) or `flowchart LR` (left-right). Declare shaped nodes — `A[\"Rect\"]`, `B(\"Rounded\")`, `C{\"Decision\"}`, `D([\"Stadium\"])`, `E((\"Circle\"))`, `F{{\"Hexagon\"}}` — and link them with `A -->|label| B`, `A -.-> B` (dotted), or `A ==> B` (thick). Group steps with `subgraph Name[\"Title\"] ... end`. Color a node with a trailing `style A fill:#fee2e2` line. Only the flowchart subset is supported. Each label is a short name on one line, written plainly: no `\\n`, no backslashes before quotes. A step's label is its name everywhere in Compass."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Fetch one Napkin diagram's mermaid source by id (from napkin_diagrams_list). Read before editing — napkin_diagrams_update replaces the whole source.
| Argument | Type | Description |
|---|---|---|
| diagramId* | string | Diagram id from napkin_diagrams_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"diagramId"
],
"properties": {
"diagramId": {
"type": "string",
"description": "Diagram id from napkin_diagrams_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists the workspace's Napkin diagrams (interactive flowcharts — processes, decision trees, system maps) newest first. Archived diagrams are hidden unless `includeArchived`; `q` narrows by title. Fetch one's mermaid source with napkin_diagrams_get. When referring the user to a diagram in your reply, put `[[diagram:ID]]` alone on its own line — it renders as a clickable card. NEVER cite a diagram as [[board:ID]]; boards are sketches.
| Argument | Type | Description |
|---|---|---|
| q | string | Title contains (case-insensitive). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| includeArchived | boolean | Also list archived diagrams (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"q": {
"type": "string",
"maxLength": 200,
"description": "Title contains (case-insensitive)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"includeArchived": {
"type": "boolean",
"description": "Also list archived diagrams (default false)."
}
}
}Edit a Napkin diagram: retitle, describe, REPLACE the whole mermaid source, set visibility, or `archived` (true takes it out of the gallery, false brings it back — the recovery move for a diagram created by mistake). Read the diagram first (napkin_diagrams_get) so your new source keeps the parts the user wants. Diagram ids come from napkin_diagrams_list.
| Argument | Type | Description |
|---|---|---|
| title | string | |
| source | string | Mermaid flowchart source. Start with `flowchart TD` (top-down) or `flowchart LR` (left-right). Declare shaped nodes — `A["Rect"]`, `B("Rounded")`, `C{"Decision"}`, `D(["Stadium"])`, `E(("Circle"))`, `F{{"Hexagon"}}` — and link them with `A -->|label| B`, `A -.-> B` (dotted), or `A ==> B` (thick). Group steps with `subgraph Name["Title"] ... end`. Color a node with a trailing `style A fill:#fee2e2` line. Only the flowchart subset is supported. Each label is a short name on one line, written plainly: no `\n`, no backslashes before quotes. A step's label is its name everywhere in Compass. |
| archived | boolean | |
| diagramId* | string | Diagram id from napkin_diagrams_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId |
Create a Napkin doc — a markdown DOCUMENT (prose, structure, code blocks), not a drawing canvas (that's napkin_boards_create) and not slides (napkin_deck_write). Optionally pass a title and initial markdown body. Use for drafts the user asked you to start. After creating, cite it as `[[doc:ID]]` alone on its own line — it renders as a clickable card. NEVER cite it as [[board:ID]].
| Argument | Type | Description |
|---|---|---|
| body | string | Initial markdown body. Write each paragraph as ONE long line — the editor wraps text to the reader's column, and hard-wrapped source shows up as narrow ragged lines when someone opens the paragraph to edit it. |
| title | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"body": {
"type": "string",
"maxLength": 200000,
"description": "Initial markdown body. Write each paragraph as ONE long line — the editor wraps text to the reader's column, and hard-wrapped source shows up as narrow ragged lines when someone opens the paragraph to edit it."
},
"title": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Fetch one Napkin doc's full markdown body by id (from napkin_docs_list). Read before editing — napkin_docs_update replaces or appends against the current body.
| Argument | Type | Description |
|---|---|---|
| docId* | string | Doc id from napkin_docs_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"docId"
],
"properties": {
"docId": {
"type": "string",
"description": "Doc id from napkin_docs_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists the workspace's Napkin docs (quick markdown documents — drafts, notes, working text; the LINEAR surface, distinct from boards which are drawing canvases) newest first, with excerpts. Archived docs are hidden unless `includeArchived`; `q` narrows by title. Fetch one with napkin_docs_get. When referring the user to a doc in your reply, put `[[doc:ID]]` alone on its own line — it renders as a clickable card. NEVER cite a doc as [[board:ID]]; boards are sketches.
| Argument | Type | Description |
|---|---|---|
| q | string | Title contains (case-insensitive). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| includeArchived | boolean | Also list archived docs (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"q": {
"type": "string",
"maxLength": 200,
"description": "Title contains (case-insensitive)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"includeArchived": {
"type": "boolean",
"description": "Also list archived docs (default false)."
}
}
}Edit a Napkin doc. For a change to existing prose use `edits` — a list of exact find/replace pairs, which is the SAFEST option and the one to reach for by default: it leaves everything you did not target untouched, and it fails loudly rather than clobbering a doc somebody else is typing in. `append` adds a section at the end. `body` replaces the WHOLE document and should be a last resort. Also retitle, describe, set visibility, or `archived` (true takes it out of the gallery, false brings it back). Read the doc with napkin_docs_get first — `edits` match the current text exactly. Doc ids come from napkin_docs_list.
| Argument | Type | Description |
|---|---|---|
| body | string | Full replacement markdown body. Prefer `edits` — this overwrites everything. Write each paragraph as ONE long line; the editor wraps it for the reader. |
| docId* | string | Doc id from napkin_docs_list. |
| edits | array | Targeted find/replace pairs, applied in order. All must match or none are applied. |
| title | string | |
| append | string | Markdown appended to the end (own paragraph). |
| archived | boolean | |
| workspace | string |
Draws shapes, strokes, and labels on a board — diagram on a sketch, annotate a deck slide — and, via `updates` / `deletes`, changes or removes shapes that are already there (ids from napkin_boards_get; the fix for something you drew wrong). For NEW elements never compute absolute board coordinates: with `slide`, coordinates are slide-local — (0, 0) top-left to (960, 540) bottom-right of that slide. Without `slide` (sketches), (0, 0) is the top-left of the existing content — the same area `napkin_boards_view` renders, so place by what you saw there; on an empty board just start at (0, 0). Example — circle a slide's title and margin-note it: {"boardId": "…", "slide": 2, "elements": [ {"type": "ellipse", "x": 60, "y": 40, "w": 400, "h": 90, "color": "#dc2626"}, {"type": "arrow", "x": 560, "y": 140, "x2": 470, "y2": 90, "color": "#dc2626"}, {"type": "text", "x": 575, "y": 130, "w": 260, "text": "tighten this claim", "color": "#dc2626"} ]} After drawing, cite the board with `[[board:ID]]` alone on its own line.
| Argument | Type | Description |
|---|---|---|
| slide | integer | 1-based slide number (decks only) — makes coordinates slide-local. |
| boardId* | string | Napkin board id. |
| deletes | array | Ids of existing shapes to remove (from napkin_boards_get). |
| updates | array | Existing shapes to change — move, resize, retext, restyle. Read napkin_boards_get first for ids and current geometry. |
| elements | array | New elements to draw, painted in order. |
Create an interface — a small screen of its own the user can open and send to people. Use when someone asks for a custom chat UI, a little tool, or a prototype of how something would feel in their product. It starts with a working index.html you then edit. It can reach NOTHING in the workspace until a flow is granted with napkin_interfaces_grant. Cite it in your reply as `[[interface:ID]]` alone on its own line — it renders as a card the user can click. Do NOT paste an image URL or try to embed the picture yourself; that renders as a broken image. An interface is plain HTML, CSS and JavaScript in one or more files, served from its own origin. Put styles in a <style> block. LIBRARIES: there is no build step and no CDN, and a <script src> to any other site is blocked. A fixed shelf of libraries is served from the interface's own origin instead; load them with exactly these tags (the versions are pinned, and any other /lib/ path is not found): PREACT + HTM, for a page with several screens or a lot of state — components and hooks with no build: <script src="/lib/[email protected]/preact.min.umd.js"></script> <script src="/lib/[email protected]/hooks.umd.js"></script> <script src="/lib/[email protected]/htm.umd.js"></script> then var html = htm.bind(preact.h); var useState = preactHooks.useState; function App(){ var s = useState(0); return html`<button onClick=${function(){ s[1](s[0] + 1) }}>${s[0]}</button>` } preact.render(html`<${App}/>`, document.getElementById("app")). Templates are tagged strings (html`…`), not JSX. CHART.JS, for a chart: <script src="/lib/[email protected]/chart.umd.min.js"></script> then new Chart(canvasElement, { type: "bar" | "line" | "doughnut" | …, data: { labels: [...], datasets: [{ label, data: [...] }] }, options: {} }). Color the datasets from the brand variables, read with getComputedStyle(document.documentElement).getPropertyValue("--brand-accent"). LUCIDE, for icons: <script src="/lib/[email protected]/lucide.min.js"></script>. In plain markup, write <i data-lucide="calendar"></i> and call lucide.createIcons() once it's on the page (again after adding more). In a Preact page DON'T — createIcons swaps elements Preact owns; draw the icon from its shapes instead: lucide.icons.Calendar is a list of [tag, attributes], so render <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> with preact.h(tag, attributes) for each (the app starter has an Icon component that does this). Names are lucide.dev's: kebab-case in markup, PascalCase in lucide.icons. A one-screen page needs none of these: plain HTML, CSS and JavaScript is still the default. React, Tailwind and every other library are not available. index.html is the entry point and must exist. THE BRAND: every interface carries the workspace brand as files — link it with <link rel="stylesheet" href="brand.css"> and style with its variables: var(--brand-ink), var(--brand-muted), var(--brand-background), var(--brand-surface), var(--brand-accent), var(--brand-accent-2), var(--brand-color-<colour name>) (napkin_interfaces_view lists the exact names this brand defines), var(--brand-font-heading), var(--brand-font-body), var(--brand-radius). Never hard-code the brand's colours or font names. brand.css already loads the brand's own font files; web fonts (Google Fonts or any other) are BLOCKED, so linking one leaves the page in a system font. The brand's logos are files under brand/ (brand.css lists them at the top): <img src="brand/<name>.svg">. Use the logo rather than typing the name, and real icons (inline SVG) rather than emoji. Read the brand with napkin_brand_get first, and say only what the brand kit or the user tells you. PICTURES: a picture from anywhere on the web is BLOCKED and draws as a broken image, so never use an external image URL. Show a picture from the workspace's files with <img src="file:<fileId>" alt="…"> (in CSS, url(file:<fileId>)) — PNG, JPEG, GIF or WebP, up to 5 MB. Write the reference literally; a file id assembled in JavaScript is not found. When the user gives you a picture in chat, save it with workspace_files_save_from_chat and use the file id it returns. A picture that's only on a website has to be attached in chat first, or uploaded in the interface's Files panel. LOOK before you hand it over: napkin_interfaces_view draws the page as it is now. Fix anything that doesn't look like the brand and look again. Load the client with <script src="/zerowidth.js"></script>. Then zw.ready() resolves with the context { viewer, grants, flows, tables, metrics, tasks }; ctx.flows lists the flow grants, each with its `id`, `name` and `variables`. zw.flows.run(flow.id, input) runs one. Call it inside zw.ready().then(...), and handle the rejection — it rejects only when the page isn't open in ZeroWidth, so show "Open this from ZeroWidth" there instead of a dead button. A run can take up to two minutes; show it working (stream it, below), and show the error's message when one fails — err.message is a sentence written for the person using the page. Input is {kind:"chat", messages:[{role:"user", content:"…"}]} or {kind:"form", values:{…}} — the same shapes the public API takes. zw.replyText(result) pulls the assistant text out of a chat result. SOURCES: when the flow searches a knowledge base, zw.sources(result) lists the documents the run actually read, as [{ name, documentId }], once each. Show those under the answer for "where did this come from" — never ask the model to write a sources line and parse it out of the text. The flow needs the knowledge base attached BEFORE it is published (workbench_flows_attach_knowledge_base, then workbench_flows_publish, then re-grant the new version here); the interface runs the published version it was granted. FEEDBACK: to let someone rate an answer or flag a wrong one, call zw.feedback.send(result, { rating: "up" | "down", correction, comment }) with the result zw.flows.run returned. It goes to Caliper, into the flow's feedback dataset, with the question and the answer taken from the run itself; `correction` is what the answer should have been. Needs no extra grant and no table — never make a table to log flagged answers. It returns a promise: say it was sent only once it resolves, and show the error's message if it rejects. Tell the user flagged answers are in Caliper, in the dataset named after the flow, under Datasets. VARIABLES: a flow grant lists `variables` — the values the flow reads besides the conversation, usually the {{key}} tokens in its prompt (who the user is, their plan, the page they are on). Send them on the same chat run: {kind:"chat", messages:[…], values:{<name>: value}}, using each variable's exact `name` and its `type` (string, number, boolean, array, object). A variable left out reaches the prompt empty. Read them from napkin_interfaces_get while you write the page, or at run time from ctx.flows[i].variables. A SHIM is not a flow and takes a different call: zw.shims.run(shimId, text), which decides on the viewer's own device with no network and no cost. It resolves with the same envelope a flow does, so read the decision with zw.decision(result) — NOT result.decision, which is undefined and makes an interface show one answer for every input. The decision is { answer, confidence, familiarity, action, probs, gates }; branch on `action`, the shim's own call about whether it was sure enough. Calling zw.flows.run with a shim id is refused. ctx.grants tells you which you have: each entry carries a `kind` of "flow" or "shim" alongside its id and name. DATA: an interface can be granted a sheet TABLE or a Ledger METRIC with napkin_interfaces_grant_data. ctx.tables lists each table with its `fields` (name, type, options) and `access` ("read", "add" or "edit"); ctx.metrics lists each metric with its unit and `access` ("read" or "record"). Records travel keyed by field NAME, choices by option NAME. zw.tables.query(table, { where: [{ field, op, value }], sort: [{ field, dir }], limit }) resolves { records: [{ id, fields }], total }; zw.tables.add(table, { Field: value }) or a list adds records; zw.tables.update(table, id, fields) and zw.tables.remove(table, ids) need "edit". zw.metrics.read(metric, { from, to }) resolves { metric, readings: [{ value, at, note }] }; zw.metrics.record(metric, value, { note }) needs "record". Name a table or metric by its id or its name. Through a share link a guest can read and add, never change or delete — so an intake form works when shared, a triage board needs a signed-in viewer. A granted Workbench TASK (ctx.tasks; each says whether it `takesInput`) starts with zw.tasks.start(task, input), which resolves { runId, status } at once — the run carries on after the page closes — and zw.tasks.get(task, runId) reads { status, output } for runs this page started. Running a shim on every keystroke is fine — it costs nothing and there is no rate limit. Debounce ~150ms and COALESCE: remember the latest text and run it when the current call finishes, so the answer matches what is on screen. Clear any in-flight guard on failure as well as success, or one call that doesn't come back wedges the interface. `d.action` is "act" | "suggest" | "refuse" — those three strings, nothing else. Branch on it rather than on a confidence threshold you invent; "refuse" means the shim doesn't recognise the input well enough to answer, so say so rather than showing a low-confidence guess. If you run a requestAnimationFrame loop, remove CSS transitions from any property it writes — the two fight and the property looks frozen. A flow answers in markdown: render it with el.replaceChildren(zw.markdown(text)). It builds DOM nodes, so model output is never treated as markup. STREAM chat answers: zw.flows.run(id, input, { onEvent: fn }) delivers the text token by token, and a flow that takes several seconds reads as broken without it. Use zw.textDelta(event) for each chunk — it returns null for anything that isn't text, so pass it every event — and accumulate. The promise still settles at the end with the whole result; take the final text from there. onEvent also sees node_start / node_complete / node_error if you want to name the step. Don't name a top-level variable `history`, `name`, `status`, `length`, `origin` or `top`: those are already window properties, so `var history = []` leaves you with the browser's History object and `history.push` fails. Prefix it, or keep it inside a function. THE KIT: every new interface also has kit.css, components built only from the brand's variables — link it after brand.css (<link rel="stylesheet" href="kit.css">) and build from its classes rather than styling from scratch: layout (.page, .page.wide, .header, .stack, .row, .grid), type (h1, h2, h3, .muted, .small, .label, .num, .stat), buttons (.btn, .btn.secondary, .btn.quiet, .btn.sm, .btn.icon), fields (.field with a .label, then .input / .select / .textarea, then a .hint or .error; .check for a checkbox), .chips and .chip, .badge (.up, .down, .accent), .card, .list, .meter, states (.empty, .skeleton, .spinner, .notice, .notice.error), chat (.thread, .bubble.me, .bubble.them, .typing, .composer), and .icon for a Lucide icon. Its tokens are var(--ink), var(--muted), var(--bg), var(--surface), var(--accent), var(--line), var(--tint), var(--radius) and spacing var(--s1)…var(--s7). The starters show the kit used well; read one before writing a page of your own. Design it the way a good product is designed: a clear hierarchy, real spacing, states for loading, empty and failure, and a layout that works on a phone first. Use the brand kit (napkin_brand_get) for what the brand looks like and how it sounds.
Read one interface: its name, the flows it may run (with the published version each is pinned to), and the contents of its files. READ BEFORE EDITING — napkin_interfaces_write matches text exactly against what is there now. Pass a path to read one file when the interface has several. An interface is plain HTML, CSS and JavaScript in one or more files, served from its own origin. Put styles in a <style> block. LIBRARIES: there is no build step and no CDN, and a <script src> to any other site is blocked. A fixed shelf of libraries is served from the interface's own origin instead; load them with exactly these tags (the versions are pinned, and any other /lib/ path is not found): PREACT + HTM, for a page with several screens or a lot of state — components and hooks with no build: <script src="/lib/[email protected]/preact.min.umd.js"></script> <script src="/lib/[email protected]/hooks.umd.js"></script> <script src="/lib/[email protected]/htm.umd.js"></script> then var html = htm.bind(preact.h); var useState = preactHooks.useState; function App(){ var s = useState(0); return html`<button onClick=${function(){ s[1](s[0] + 1) }}>${s[0]}</button>` } preact.render(html`<${App}/>`, document.getElementById("app")). Templates are tagged strings (html`…`), not JSX. CHART.JS, for a chart: <script src="/lib/[email protected]/chart.umd.min.js"></script> then new Chart(canvasElement, { type: "bar" | "line" | "doughnut" | …, data: { labels: [...], datasets: [{ label, data: [...] }] }, options: {} }). Color the datasets from the brand variables, read with getComputedStyle(document.documentElement).getPropertyValue("--brand-accent"). LUCIDE, for icons: <script src="/lib/[email protected]/lucide.min.js"></script>. In plain markup, write <i data-lucide="calendar"></i> and call lucide.createIcons() once it's on the page (again after adding more). In a Preact page DON'T — createIcons swaps elements Preact owns; draw the icon from its shapes instead: lucide.icons.Calendar is a list of [tag, attributes], so render <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> with preact.h(tag, attributes) for each (the app starter has an Icon component that does this). Names are lucide.dev's: kebab-case in markup, PascalCase in lucide.icons. A one-screen page needs none of these: plain HTML, CSS and JavaScript is still the default. React, Tailwind and every other library are not available. index.html is the entry point and must exist. THE BRAND: every interface carries the workspace brand as files — link it with <link rel="stylesheet" href="brand.css"> and style with its variables: var(--brand-ink), var(--brand-muted), var(--brand-background), var(--brand-surface), var(--brand-accent), var(--brand-accent-2), var(--brand-color-<colour name>) (napkin_interfaces_view lists the exact names this brand defines), var(--brand-font-heading), var(--brand-font-body), var(--brand-radius). Never hard-code the brand's colours or font names. brand.css already loads the brand's own font files; web fonts (Google Fonts or any other) are BLOCKED, so linking one leaves the page in a system font. The brand's logos are files under brand/ (brand.css lists them at the top): <img src="brand/<name>.svg">. Use the logo rather than typing the name, and real icons (inline SVG) rather than emoji. Read the brand with napkin_brand_get first, and say only what the brand kit or the user tells you. PICTURES: a picture from anywhere on the web is BLOCKED and draws as a broken image, so never use an external image URL. Show a picture from the workspace's files with <img src="file:<fileId>" alt="…"> (in CSS, url(file:<fileId>)) — PNG, JPEG, GIF or WebP, up to 5 MB. Write the reference literally; a file id assembled in JavaScript is not found. When the user gives you a picture in chat, save it with workspace_files_save_from_chat and use the file id it returns. A picture that's only on a website has to be attached in chat first, or uploaded in the interface's Files panel. LOOK before you hand it over: napkin_interfaces_view draws the page as it is now. Fix anything that doesn't look like the brand and look again. Load the client with <script src="/zerowidth.js"></script>. Then zw.ready() resolves with the context { viewer, grants, flows, tables, metrics, tasks }; ctx.flows lists the flow grants, each with its `id`, `name` and `variables`. zw.flows.run(flow.id, input) runs one. Call it inside zw.ready().then(...), and handle the rejection — it rejects only when the page isn't open in ZeroWidth, so show "Open this from ZeroWidth" there instead of a dead button. A run can take up to two minutes; show it working (stream it, below), and show the error's message when one fails — err.message is a sentence written for the person using the page. Input is {kind:"chat", messages:[{role:"user", content:"…"}]} or {kind:"form", values:{…}} — the same shapes the public API takes. zw.replyText(result) pulls the assistant text out of a chat result. SOURCES: when the flow searches a knowledge base, zw.sources(result) lists the documents the run actually read, as [{ name, documentId }], once each. Show those under the answer for "where did this come from" — never ask the model to write a sources line and parse it out of the text. The flow needs the knowledge base attached BEFORE it is published (workbench_flows_attach_knowledge_base, then workbench_flows_publish, then re-grant the new version here); the interface runs the published version it was granted. FEEDBACK: to let someone rate an answer or flag a wrong one, call zw.feedback.send(result, { rating: "up" | "down", correction, comment }) with the result zw.flows.run returned. It goes to Caliper, into the flow's feedback dataset, with the question and the answer taken from the run itself; `correction` is what the answer should have been. Needs no extra grant and no table — never make a table to log flagged answers. It returns a promise: say it was sent only once it resolves, and show the error's message if it rejects. Tell the user flagged answers are in Caliper, in the dataset named after the flow, under Datasets. VARIABLES: a flow grant lists `variables` — the values the flow reads besides the conversation, usually the {{key}} tokens in its prompt (who the user is, their plan, the page they are on). Send them on the same chat run: {kind:"chat", messages:[…], values:{<name>: value}}, using each variable's exact `name` and its `type` (string, number, boolean, array, object). A variable left out reaches the prompt empty. Read them from napkin_interfaces_get while you write the page, or at run time from ctx.flows[i].variables. A SHIM is not a flow and takes a different call: zw.shims.run(shimId, text), which decides on the viewer's own device with no network and no cost. It resolves with the same envelope a flow does, so read the decision with zw.decision(result) — NOT result.decision, which is undefined and makes an interface show one answer for every input. The decision is { answer, confidence, familiarity, action, probs, gates }; branch on `action`, the shim's own call about whether it was sure enough. Calling zw.flows.run with a shim id is refused. ctx.grants tells you which you have: each entry carries a `kind` of "flow" or "shim" alongside its id and name. DATA: an interface can be granted a sheet TABLE or a Ledger METRIC with napkin_interfaces_grant_data. ctx.tables lists each table with its `fields` (name, type, options) and `access` ("read", "add" or "edit"); ctx.metrics lists each metric with its unit and `access` ("read" or "record"). Records travel keyed by field NAME, choices by option NAME. zw.tables.query(table, { where: [{ field, op, value }], sort: [{ field, dir }], limit }) resolves { records: [{ id, fields }], total }; zw.tables.add(table, { Field: value }) or a list adds records; zw.tables.update(table, id, fields) and zw.tables.remove(table, ids) need "edit". zw.metrics.read(metric, { from, to }) resolves { metric, readings: [{ value, at, note }] }; zw.metrics.record(metric, value, { note }) needs "record". Name a table or metric by its id or its name. Through a share link a guest can read and add, never change or delete — so an intake form works when shared, a triage board needs a signed-in viewer. A granted Workbench TASK (ctx.tasks; each says whether it `takesInput`) starts with zw.tasks.start(task, input), which resolves { runId, status } at once — the run carries on after the page closes — and zw.tasks.get(task, runId) reads { status, output } for runs this page started. Running a shim on every keystroke is fine — it costs nothing and there is no rate limit. Debounce ~150ms and COALESCE: remember the latest text and run it when the current call finishes, so the answer matches what is on screen. Clear any in-flight guard on failure as well as success, or one call that doesn't come back wedges the interface. `d.action` is "act" | "suggest" | "refuse" — those three strings, nothing else. Branch on it rather than on a confidence threshold you invent; "refuse" means the shim doesn't recognise the input well enough to answer, so say so rather than showing a low-confidence guess. If you run a requestAnimationFrame loop, remove CSS transitions from any property it writes — the two fight and the property looks frozen. A flow answers in markdown: render it with el.replaceChildren(zw.markdown(text)). It builds DOM nodes, so model output is never treated as markup. STREAM chat answers: zw.flows.run(id, input, { onEvent: fn }) delivers the text token by token, and a flow that takes several seconds reads as broken without it. Use zw.textDelta(event) for each chunk — it returns null for anything that isn't text, so pass it every event — and accumulate. The promise still settles at the end with the whole result; take the final text from there. onEvent also sees node_start / node_complete / node_error if you want to name the step. Don't name a top-level variable `history`, `name`, `status`, `length`, `origin` or `top`: those are already window properties, so `var history = []` leaves you with the browser's History object and `history.push` fails. Prefix it, or keep it inside a function. THE KIT: every new interface also has kit.css, components built only from the brand's variables — link it after brand.css (<link rel="stylesheet" href="kit.css">) and build from its classes rather than styling from scratch: layout (.page, .page.wide, .header, .stack, .row, .grid), type (h1, h2, h3, .muted, .small, .label, .num, .stat), buttons (.btn, .btn.secondary, .btn.quiet, .btn.sm, .btn.icon), fields (.field with a .label, then .input / .select / .textarea, then a .hint or .error; .check for a checkbox), .chips and .chip, .badge (.up, .down, .accent), .card, .list, .meter, states (.empty, .skeleton, .spinner, .notice, .notice.error), chat (.thread, .bubble.me, .bubble.them, .typing, .composer), and .icon for a Lucide icon. Its tokens are var(--ink), var(--muted), var(--bg), var(--surface), var(--accent), var(--line), var(--tint), var(--radius) and spacing var(--s1)…var(--s7). The starters show the kit used well; read one before writing a page of your own. Design it the way a good product is designed: a clear hierarchy, real spacing, states for loading, empty and failure, and a layout that works on a phone first. Use the brand kit (napkin_brand_get) for what the brand looks like and how it sounds.
Set what an interface may run — flows and shims, each pinned to a published version. This is the interface's ONLY reach into the workspace, and it replaces the whole list, so include everything it should keep. Ids and published versions come from workbench_flows_list / workbench_shim_list and their revisions. Ask the user before widening this.
| Argument | Type | Description |
|---|---|---|
| grants* | array | The complete list. Passing an empty list removes all access. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| interfaceId* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interfaceId",
"grants"
],
"properties": {
"grants": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind",
"targetId",
"version"
],
"properties": {
"kind": {
"enum": [
"flow",
"shim"
],
"type": "string",
"description": "What kind of thing this grant names."
},
"version": {
"type": "string",
"description": "A PUBLISHED version of it. The interface runs exactly this one until it's changed."
},
"targetId": {
"type": "string",
"description": "The flow's or shim's id."
}
}
},
"maxItems": 20,
"description": "The complete list. Passing an empty list removes all access."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"interfaceId": {
"type": "string"
}
}
}Set the sheet tables, Ledger metrics and Workbench Tasks an interface may use (ADR 0085, 0086), replacing the whole list. Tables: access read, add (read and add records) or edit (also change and delete); optionally limit to some columns by name. Metrics: read or record. Tasks: the page may start them. The page then calls zw.tables.query / add / update / remove, zw.metrics.read / record and zw.tasks.start / get. Anyone who can open the interface, including people it's shared with, gets this access (a shared link can only read and add), so ask the user before widening it.
| Argument | Type | Description |
|---|---|---|
| tasks | array | Workbench Tasks the page may start with zw.tasks.start, and check with zw.tasks.get. |
| tables | array | |
| metrics | array | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| interfaceId* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interfaceId"
],
"properties": {
"tasks": {
"type": "array",
"items": {
"type": "object",
"required": [
"taskId"
],
"properties": {
"taskId": {
"type": "string"
}
}
},
"default": [],
"maxItems": 10,
"description": "Workbench Tasks the page may start with zw.tasks.start, and check with zw.tasks.get."
},
"tables": {
"type": "array",
"items": {
"type": "object",
"required": [
"sheetId",
"table",
"access"
],
"properties": {
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"access": {
"enum": [
"read",
"add",
"edit"
],
"type": "string"
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 100,
"description": "Column names to allow; omit for all."
},
"sheetId": {
"type": "string"
}
}
},
"default": [],
"maxItems": 10
},
"metrics": {
"type": "array",
"items": {
"type": "object",
"required": [
"metricId",
"access"
],
"properties": {
"access": {
"enum": [
"read",
"record"
],
"type": "string"
},
"metricId": {
"type": "string"
}
}
},
"default": [],
"maxItems": 10
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"interfaceId": {
"type": "string"
}
}
}List the interfaces in a workspace — small self-contained screens (a custom chat, a control panel, a prototype) that run on their own origin and can call the flows they've been granted. Returns ids, names and how many flows each may run.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| includeArchived | boolean |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"includeArchived": {
"type": "boolean"
}
}
}Save where an interface is now as a numbered version. Share links point at a published version, so what someone was sent doesn't change while work continues. Do this when the user says it's ready to show people, not after every edit.
| Argument | Type | Description |
|---|---|---|
| note | string | One line on what changed. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| interfaceId* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interfaceId"
],
"properties": {
"note": {
"type": "string",
"maxLength": 500,
"description": "One line on what changed."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"interfaceId": {
"type": "string"
}
}
}See what an interface LOOKS like and DOES right now: the page RUNS from its current files under the same rules as the live page (no web fonts, no remote pictures), and you get a picture plus anything that went wrong (script errors, failed promises, blocked requests, console errors). Use it after every write and before saying an interface is finished: reading the code tells you what you wrote, not what it renders. `size: "phone"` looks at it 390px wide — use it for anything meant for a phone, like a mobile app mockup. `steps` drive the page before and between pictures, so you can check every screen and that buttons work: `{click: "Plan"}` (by visible text or label, or a CSS selector like "#nav-plan"), `{type: {into: "textarea", text: "hi"}}`, `{press: "Enter"}`, `{wait: 500}`, and `{shot: "Plan screen"}` for a picture. With no steps you get one picture of the first screen. Check each tab of an app in ONE call: shot, click a tab, shot, click the next, shot. Flows don't run here: a flow call gets a placeholder reply, so you can see the chat send and answer without spending anything; tables and metrics read empty. Look for text that's too small or runs together, stray system fonts, emoji standing in for icons, and anything that doesn't look like the brand.
| Argument | Type | Description |
|---|---|---|
| size | string | The window to look through. Default desktop (1280 wide); phone is 390 wide. |
| steps | array | Done in order, with a picture at each `shot` (at most 6). Default: one shot of the first screen. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
Write one file of an interface. Use `edits` — exact find/replace pairs — which is the SAFEST option and the one to reach for by default: it leaves everything you did not target untouched, and it fails loudly rather than clobbering a file somebody is editing. `body` replaces the WHOLE file and is for a new file or a deliberate rewrite. ONE CALL HOLDS ABOUT 15,000 CHARACTERS of file: a longer `body` is cut off mid-write and fails. Write a big file in parts instead — the first part with `body`, then each further part with `body` plus `append: true`, in order — and split an app across files (index.html, style.css, app.js) so each stays readable. `deleteFile` removes one (index.html can't be removed). Read with napkin_interfaces_get first — `edits` match the current text exactly. Also rename, describe, set visibility, or archive. An interface is plain HTML, CSS and JavaScript in one or more files, served from its own origin. Put styles in a <style> block. LIBRARIES: there is no build step and no CDN, and a <script src> to any other site is blocked. A fixed shelf of libraries is served from the interface's own origin instead; load them with exactly these tags (the versions are pinned, and any other /lib/ path is not found): PREACT + HTM, for a page with several screens or a lot of state — components and hooks with no build: <script src="/lib/[email protected]/preact.min.umd.js"></script> <script src="/lib/[email protected]/hooks.umd.js"></script> <script src="/lib/[email protected]/htm.umd.js"></script> then var html = htm.bind(preact.h); var useState = preactHooks.useState; function App(){ var s = useState(0); return html`<button onClick=${function(){ s[1](s[0] + 1) }}>${s[0]}</button>` } preact.render(html`<${App}/>`, document.getElementById("app")). Templates are tagged strings (html`…`), not JSX. CHART.JS, for a chart: <script src="/lib/[email protected]/chart.umd.min.js"></script> then new Chart(canvasElement, { type: "bar" | "line" | "doughnut" | …, data: { labels: [...], datasets: [{ label, data: [...] }] }, options: {} }). Color the datasets from the brand variables, read with getComputedStyle(document.documentElement).getPropertyValue("--brand-accent"). LUCIDE, for icons: <script src="/lib/[email protected]/lucide.min.js"></script>. In plain markup, write <i data-lucide="calendar"></i> and call lucide.createIcons() once it's on the page (again after adding more). In a Preact page DON'T — createIcons swaps elements Preact owns; draw the icon from its shapes instead: lucide.icons.Calendar is a list of [tag, attributes], so render <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> with preact.h(tag, attributes) for each (the app starter has an Icon component that does this). Names are lucide.dev's: kebab-case in markup, PascalCase in lucide.icons. A one-screen page needs none of these: plain HTML, CSS and JavaScript is still the default. React, Tailwind and every other library are not available. index.html is the entry point and must exist. THE BRAND: every interface carries the workspace brand as files — link it with <link rel="stylesheet" href="brand.css"> and style with its variables: var(--brand-ink), var(--brand-muted), var(--brand-background), var(--brand-surface), var(--brand-accent), var(--brand-accent-2), var(--brand-color-<colour name>) (napkin_interfaces_view lists the exact names this brand defines), var(--brand-font-heading), var(--brand-font-body), var(--brand-radius). Never hard-code the brand's colours or font names. brand.css already loads the brand's own font files; web fonts (Google Fonts or any other) are BLOCKED, so linking one leaves the page in a system font. The brand's logos are files under brand/ (brand.css lists them at the top): <img src="brand/<name>.svg">. Use the logo rather than typing the name, and real icons (inline SVG) rather than emoji. Read the brand with napkin_brand_get first, and say only what the brand kit or the user tells you. PICTURES: a picture from anywhere on the web is BLOCKED and draws as a broken image, so never use an external image URL. Show a picture from the workspace's files with <img src="file:<fileId>" alt="…"> (in CSS, url(file:<fileId>)) — PNG, JPEG, GIF or WebP, up to 5 MB. Write the reference literally; a file id assembled in JavaScript is not found. When the user gives you a picture in chat, save it with workspace_files_save_from_chat and use the file id it returns. A picture that's only on a website has to be attached in chat first, or uploaded in the interface's Files panel. LOOK before you hand it over: napkin_interfaces_view draws the page as it is now. Fix anything that doesn't look like the brand and look again. Load the client with <script src="/zerowidth.js"></script>. Then zw.ready() resolves with the context { viewer, grants, flows, tables, metrics, tasks }; ctx.flows lists the flow grants, each with its `id`, `name` and `variables`. zw.flows.run(flow.id, input) runs one. Call it inside zw.ready().then(...), and handle the rejection — it rejects only when the page isn't open in ZeroWidth, so show "Open this from ZeroWidth" there instead of a dead button. A run can take up to two minutes; show it working (stream it, below), and show the error's message when one fails — err.message is a sentence written for the person using the page. Input is {kind:"chat", messages:[{role:"user", content:"…"}]} or {kind:"form", values:{…}} — the same shapes the public API takes. zw.replyText(result) pulls the assistant text out of a chat result. SOURCES: when the flow searches a knowledge base, zw.sources(result) lists the documents the run actually read, as [{ name, documentId }], once each. Show those under the answer for "where did this come from" — never ask the model to write a sources line and parse it out of the text. The flow needs the knowledge base attached BEFORE it is published (workbench_flows_attach_knowledge_base, then workbench_flows_publish, then re-grant the new version here); the interface runs the published version it was granted. FEEDBACK: to let someone rate an answer or flag a wrong one, call zw.feedback.send(result, { rating: "up" | "down", correction, comment }) with the result zw.flows.run returned. It goes to Caliper, into the flow's feedback dataset, with the question and the answer taken from the run itself; `correction` is what the answer should have been. Needs no extra grant and no table — never make a table to log flagged answers. It returns a promise: say it was sent only once it resolves, and show the error's message if it rejects. Tell the user flagged answers are in Caliper, in the dataset named after the flow, under Datasets. VARIABLES: a flow grant lists `variables` — the values the flow reads besides the conversation, usually the {{key}} tokens in its prompt (who the user is, their plan, the page they are on). Send them on the same chat run: {kind:"chat", messages:[…], values:{<name>: value}}, using each variable's exact `name` and its `type` (string, number, boolean, array, object). A variable left out reaches the prompt empty. Read them from napkin_interfaces_get while you write the page, or at run time from ctx.flows[i].variables. A SHIM is not a flow and takes a different call: zw.shims.run(shimId, text), which decides on the viewer's own device with no network and no cost. It resolves with the same envelope a flow does, so read the decision with zw.decision(result) — NOT result.decision, which is undefined and makes an interface show one answer for every input. The decision is { answer, confidence, familiarity, action, probs, gates }; branch on `action`, the shim's own call about whether it was sure enough. Calling zw.flows.run with a shim id is refused. ctx.grants tells you which you have: each entry carries a `kind` of "flow" or "shim" alongside its id and name. DATA: an interface can be granted a sheet TABLE or a Ledger METRIC with napkin_interfaces_grant_data. ctx.tables lists each table with its `fields` (name, type, options) and `access` ("read", "add" or "edit"); ctx.metrics lists each metric with its unit and `access` ("read" or "record"). Records travel keyed by field NAME, choices by option NAME. zw.tables.query(table, { where: [{ field, op, value }], sort: [{ field, dir }], limit }) resolves { records: [{ id, fields }], total }; zw.tables.add(table, { Field: value }) or a list adds records; zw.tables.update(table, id, fields) and zw.tables.remove(table, ids) need "edit". zw.metrics.read(metric, { from, to }) resolves { metric, readings: [{ value, at, note }] }; zw.metrics.record(metric, value, { note }) needs "record". Name a table or metric by its id or its name. Through a share link a guest can read and add, never change or delete — so an intake form works when shared, a triage board needs a signed-in viewer. A granted Workbench TASK (ctx.tasks; each says whether it `takesInput`) starts with zw.tasks.start(task, input), which resolves { runId, status } at once — the run carries on after the page closes — and zw.tasks.get(task, runId) reads { status, output } for runs this page started. Running a shim on every keystroke is fine — it costs nothing and there is no rate limit. Debounce ~150ms and COALESCE: remember the latest text and run it when the current call finishes, so the answer matches what is on screen. Clear any in-flight guard on failure as well as success, or one call that doesn't come back wedges the interface. `d.action` is "act" | "suggest" | "refuse" — those three strings, nothing else. Branch on it rather than on a confidence threshold you invent; "refuse" means the shim doesn't recognise the input well enough to answer, so say so rather than showing a low-confidence guess. If you run a requestAnimationFrame loop, remove CSS transitions from any property it writes — the two fight and the property looks frozen. A flow answers in markdown: render it with el.replaceChildren(zw.markdown(text)). It builds DOM nodes, so model output is never treated as markup. STREAM chat answers: zw.flows.run(id, input, { onEvent: fn }) delivers the text token by token, and a flow that takes several seconds reads as broken without it. Use zw.textDelta(event) for each chunk — it returns null for anything that isn't text, so pass it every event — and accumulate. The promise still settles at the end with the whole result; take the final text from there. onEvent also sees node_start / node_complete / node_error if you want to name the step. Don't name a top-level variable `history`, `name`, `status`, `length`, `origin` or `top`: those are already window properties, so `var history = []` leaves you with the browser's History object and `history.push` fails. Prefix it, or keep it inside a function. THE KIT: every new interface also has kit.css, components built only from the brand's variables — link it after brand.css (<link rel="stylesheet" href="kit.css">) and build from its classes rather than styling from scratch: layout (.page, .page.wide, .header, .stack, .row, .grid), type (h1, h2, h3, .muted, .small, .label, .num, .stat), buttons (.btn, .btn.secondary, .btn.quiet, .btn.sm, .btn.icon), fields (.field with a .label, then .input / .select / .textarea, then a .hint or .error; .check for a checkbox), .chips and .chip, .badge (.up, .down, .accent), .card, .list, .meter, states (.empty, .skeleton, .spinner, .notice, .notice.error), chat (.thread, .bubble.me, .bubble.them, .typing, .composer), and .icon for a Lucide icon. Its tokens are var(--ink), var(--muted), var(--bg), var(--surface), var(--accent), var(--line), var(--tint), var(--radius) and spacing var(--s1)…var(--s7). The starters show the kit used well; read one before writing a page of your own. Design it the way a good product is designed: a clear hierarchy, real spacing, states for loading, empty and failure, and a layout that works on a phone first. Use the brand kit (napkin_brand_get) for what the brand looks like and how it sounds.
Lists the slide layouts napkin_deck_compose can build from — the brand kit's own first, then the built-in ones — with when to use each and the slots it takes (`needs` must be filled; `takes` are optional). Every layout adapts to every size, fits its text, and uses the brand's colors, faces and logos; the logo fills itself in. Pick by what the slide has to say: one line (statement), a number (stat), a quote, a list (points, steps), an event, a carousel (cover, inner, closing), a picture (image-top, image-full, split, corner, product-shot), or a display ad (banner).
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Adds a LIVE chart to a sheet — its SQL re-runs against the tabs on every view, so it never goes stale. Write the query with napkin_sheets_query first to confirm the shape (first column = x axis, numeric columns = series, or set x/series explicitly). Prefer aggregated queries (GROUP BY) — a chart of raw rows is rarely the answer.
| Argument | Type | Description |
|---|---|---|
| x | string | |
| sql* | string | The SELECT to chart. |
| type* | string | |
| title* | string | Chart title. |
| series | array | |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| stacked | boolean | Stack the series (bar/area only). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"title",
"type",
"sql"
],
"properties": {
"x": {
"type": "string",
"maxLength": 120
},
"sql": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "The SELECT to chart."
},
"type": {
"enum": [
"line",
"bar",
"area",
"scatter",
"pie"
],
"type": "string"
},
"title": {
"type": "string",
"maxLength": 120,
"description": "Chart title."
},
"series": {
"type": "array",
"items": {
"type": "string",
"maxLength": 120
},
"maxItems": 20
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"stacked": {
"type": "boolean",
"description": "Stack the series (bar/area only)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Creates a Napkin sheet (multi-tab spreadsheet), optionally titled. Then populate it with napkin_sheets_set_cells (headers in row 1). Tell the user where it landed — the Sheets tab in Napkin.
| Argument | Type | Description |
|---|---|---|
| title | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"title": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists the workspace's Napkin sheets (multi-tab spreadsheets — the small-data surface) newest first with tab/chart counts. Archived sheets are hidden unless `includeArchived`; `q` narrows by title. Inspect one with napkin_sheets_schema, then query it with napkin_sheets_query.
| Argument | Type | Description |
|---|---|---|
| q | string | Title contains (case-insensitive). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| includeArchived | boolean | Also list archived sheets (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"q": {
"type": "string",
"maxLength": 200,
"description": "Title contains (case-insensitive)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"includeArchived": {
"type": "boolean",
"description": "Also list archived sheets (default false)."
}
}
}Runs a SQLite SELECT over a sheet's tabs-as-tables (get the table/column names from napkin_sheets_schema first). Full SQLite dialect: WHERE, GROUP BY, ORDER BY, JOINs across tabs, aggregates. Results cap at 200 rows. This is THE way to answer questions about a sheet's data — never eyeball cells when a query can answer precisely.
| Argument | Type | Description |
|---|---|---|
| sql* | string | A single SELECT. |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"sql"
],
"properties": {
"sql": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "A single SELECT."
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Returns a sheet's tabs as SQL table definitions — CREATE TABLE scripts with row counts (each tab is a table; its header row names the columns; formula cells contribute computed values). Read this BEFORE writing a napkin_sheets_query so your SQL matches the real tables.
| Argument | Type | Description |
|---|---|---|
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId"
],
"properties": {
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Sets cells in one tab of a sheet, by A1 address — values or formulas ('=SUM(B2:B9)'). Additive and surgical: only the addressed cells change. Check napkin_sheets_schema first so you know the tab names and where data ends; put headers in row 1 when creating a new region. To build a whole small table, write header cells + data cells in one call.
| Argument | Type | Description |
|---|---|---|
| cells* | object | A1 → raw value/formula, e.g. {"A1":"Region","B2":"=SUM(B3:B9)"}. |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| tabName | string | Tab name (defaults to the first tab). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"cells"
],
"properties": {
"cells": {
"type": "object",
"description": "A1 → raw value/formula, e.g. {\"A1\":\"Region\",\"B2\":\"=SUM(B3:B9)\"}.",
"propertyNames": {
"type": "string",
"pattern": "^[A-Za-z]{1,3}[1-9][0-9]{0,4}$"
},
"additionalProperties": {
"type": "string",
"maxLength": 10000
}
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"tabName": {
"type": "string",
"description": "Tab name (defaults to the first tab)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Edits a sheet's details: title, description, visibility, or `archived` (true takes it out of the gallery; false brings it back — the recovery move for a sheet created by mistake or no longer wanted). Cells are edited with napkin_sheets_set_cells, not here. Sheet ids come from napkin_sheets_list.
| Argument | Type | Description |
|---|---|---|
| title | string | |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| archived | boolean | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | Short gallery summary. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId"
],
"properties": {
"title": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"archived": {
"type": "boolean"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"maxLength": 2000,
"description": "Short gallery summary."
}
}
}Renders one of a sheet's pinned charts against the LIVE data and returns the image so you can SEE it — the exact chart the user sees. The text part carries `imageUrl`; to show the user the chart inline in your reply, put a markdown image on its own line: ``. Use after napkin_sheets_add_chart to confirm the chart reads well, or whenever the user asks about a chart.
| Argument | Type | Description |
|---|---|---|
| chartId* | string | Chart id (napkin_sheets_list shows chart counts; the sheet's charts carry ids). |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"chartId"
],
"properties": {
"chartId": {
"type": "string",
"description": "Chart id (napkin_sheets_list shows chart counts; the sheet's charts carry ids)."
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Appends one slide to an existing deck. Pick a layout (title | section | title-body | title-lead | two-column | three-column | comparison | statement | quote | closing | blank), give the title, and optionally `content` — markdown for the layout's remaining text areas, split by `---` lines (two-column/comparison take one block per column). Check the deck first with `napkin_deck_outline`.
| Argument | Type | Description |
|---|---|---|
| title | string | Slide title. |
| layout* | string | Layout key: title | section | title-body | title-lead | two-column | three-column | comparison | statement | quote | closing | blank. |
| boardId* | string | Napkin board id (a deck). |
| content | string | Markdown body — blocks split on `---` lines. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId",
"layout"
],
"properties": {
"title": {
"type": "string",
"maxLength": 500,
"description": "Slide title."
},
"layout": {
"type": "string",
"description": "Layout key: title | section | title-body | title-lead | two-column | three-column | comparison | statement | quote | closing | blank."
},
"boardId": {
"type": "string",
"description": "Napkin board id (a deck)."
},
"content": {
"type": "string",
"maxLength": 20000,
"description": "Markdown body — blocks split on `---` lines."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Fills a slide's empty layout text areas by NAME — the names `napkin_deck_outline` surfaces as `[empty text stub: "…"]`. Pass `texts` mapping those exact names to content (markdown `- ` bullets welcome). Read the outline first to see which stubs a slide still has open.
| Argument | Type | Description |
|---|---|---|
| slide* | integer | 1-based slide number in presentation order. |
| texts* | object | Placeholder name → content, e.g. {"Add a title": "Q3 Review"}. |
| boardId* | string | Napkin board id (a deck). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId",
"slide",
"texts"
],
"properties": {
"slide": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based slide number in presentation order."
},
"texts": {
"type": "object",
"description": "Placeholder name → content, e.g. {\"Add a title\": \"Q3 Review\"}.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string",
"maxLength": 20000
}
},
"boardId": {
"type": "string",
"description": "Napkin board id (a deck)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Changes one slide as a whole: move it to another position in the deck (`moveTo`, 1-based — the other slides shift around it), hide it from the show without deleting it (`skipped`), show or hide its slide number (`pageNumber`), or replace its speaker notes (`notes`, markdown). Slide numbers come from napkin_deck_outline. To change what's ON the slide, use napkin_slide_fill or napkin_draw.
| Argument | Type | Description |
|---|---|---|
| notes | string | Speaker notes (markdown); replaces the current notes. |
| slide* | integer | 1-based slide number in presentation order. |
| moveTo | integer | New 1-based position for this slide. |
| boardId* | string | Napkin board id (a deck). |
| skipped | boolean | true hides the slide from present mode and exports. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| pageNumber | boolean | Show the slide number on this slide. |
Renders a single slide of a Napkin deck to an image — exactly what present mode shows, cropped to the slide. Navigate by 1-based `slide` number in presentation order (get the map from `napkin_deck_outline` first; the result echoes `slideIndex`/`slideCount` so you can step through a deck slide by slide). Use this to check visual layout, drawings, and images that the text outline can't carry.
| Argument | Type | Description |
|---|---|---|
| slide* | integer | 1-based slide number in presentation order. |
| boardId* | string | Napkin board id (a deck). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId",
"slide"
],
"properties": {
"slide": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based slide number in presentation order."
},
"boardId": {
"type": "string",
"description": "Napkin board id (a deck)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Adds columns to the end of a table. Existing records leave them empty.
| Argument | Type | Description |
|---|---|---|
| table* | string | The table tab's name or id. |
| columns* | array | |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"table",
"columns"
],
"properties": {
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"columns": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"type"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"type": {
"enum": [
"text",
"long_text",
"number",
"date",
"checkbox",
"select",
"multi_select",
"person",
"url",
"email"
],
"type": "string"
},
"format": {
"enum": [
"plain",
"currency",
"percent"
],
"type": "string",
"description": "Number columns."
},
"options": {
"type": "array",
"items": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"maxItems": 100,
"description": "Choices, for select and multi_select columns."
},
"description": {
"type": "string",
"maxLength": 1000,
"description": "What the column holds — shown to people and to interfaces."
}
}
},
"maxItems": 30,
"minItems": 1
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Adds records, each a map of field name → value. Choices by option name (a new name becomes a new option); dates as YYYY-MM-DD; people by user id; checkboxes true/false. Every problem is reported at once and nothing is written until all records are valid.
| Argument | Type | Description |
|---|---|---|
| table* | string | The table tab's name or id. |
| records* | array | |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"table",
"records"
],
"properties": {
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"records": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"maxItems": 200,
"minItems": 1
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Adds a saved view everyone sees: a grid (with where / sort), a board (lanes from a select or person column — groupBy), or a form people fill in to add records (formFields, formTitle, formIntro). A form's share link is made from the sheet's form view.
| Argument | Type | Description |
|---|---|---|
| kind* | string | |
| name* | string | |
| sort | array | |
| table* | string | The table tab's name or id. |
| where | array | |
| groupBy | string | Board: the select or person column whose values are the lanes. |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| formIntro | string | |
| formTitle | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
Makes a table tab — typed columns, one record per row, with grid, board and form views — in an existing sheet, or in a new sheet when sheetId is omitted. Use a table (not napkin_sheets_set_cells) for lists people keep: requests, vendors, bugs, contacts. The first column names each record. Column types: text, long_text, number, date, checkbox, select, multi_select, person, url, email.
| Argument | Type | Description |
|---|---|---|
| name* | string | The table's name, e.g. Requests. |
| columns* | array | |
| sheetId | string | Add to this sheet; omit to make a new sheet. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| sheetTitle | string | Title for a new sheet. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name",
"columns"
],
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "The table's name, e.g. Requests."
},
"columns": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"type"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"type": {
"enum": [
"text",
"long_text",
"number",
"date",
"checkbox",
"select",
"multi_select",
"person",
"url",
"email"
],
"type": "string"
},
"format": {
"enum": [
"plain",
"currency",
"percent"
],
"type": "string",
"description": "Number columns."
},
"options": {
"type": "array",
"items": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"maxItems": 100,
"description": "Choices, for select and multi_select columns."
},
"description": {
"type": "string",
"maxLength": 1000,
"description": "What the column holds — shown to people and to interfaces."
}
}
},
"maxItems": 50,
"minItems": 1
},
"sheetId": {
"type": "string",
"description": "Add to this sheet; omit to make a new sheet."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"sheetTitle": {
"type": "string",
"maxLength": 200,
"description": "Title for a new sheet."
}
}
}Deletes records by id. People can undo this in the sheet only while it's open, so confirm with the person first.
| Argument | Type | Description |
|---|---|---|
| ids* | array | |
| table* | string | The table tab's name or id. |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"table",
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 500,
"minItems": 1
},
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}A table tab's columns (name, type, choices), its views, and how many records it holds. Read this before writing records so field names and choices match.
| Argument | Type | Description |
|---|---|---|
| table* | string | The table tab's name or id. |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"table"
],
"properties": {
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
}
}
}Records from a table tab, keyed by field name, with optional where / sort / search / limit (max 500). For counts, sums and joins, napkin_sheets_query runs SQL over tables too (each table is an SQL table with an id column).
| Argument | Type | Description |
|---|---|---|
| sort | array | |
| limit | integer | |
| match | string | |
| table* | string | The table tab's name or id. |
| where | array | |
| offset | integer | |
| search | string | |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
Changes some fields of records by id (from napkin_tables_query). Fields left out keep their values.
| Argument | Type | Description |
|---|---|---|
| table* | string | The table tab's name or id. |
| sheetId* | string | Sheet id from napkin_sheets_list. |
| updates* | array | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"table",
"updates"
],
"properties": {
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"updates": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"fields"
],
"properties": {
"id": {
"type": "string"
},
"fields": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
}
},
"maxItems": 200,
"minItems": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Creates a field from an origin idea — the seed of an exploration canvas. Counts against the workspace's field quota. May return `needs_confirmation` — tell the user what you're proposing and wait for approval.
| Argument | Type | Description |
|---|---|---|
| name | string | Display name (defaults to the idea). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| originIdea* | string | The idea at the center — a product, concept, sentence. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"originIdea"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"description": "Display name (defaults to the idea)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"originIdea": {
"type": "string",
"maxLength": 4000,
"minLength": 1,
"description": "The idea at the center — a product, concept, sentence."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
}
}
}Removes a field and its whole canvas (soft delete; frees the workspace's field quota). Use when the user is done with an exploration or one was created by mistake — studies attached to its nodes are not deleted. Field ids come from prism_fields_list. May return `needs_confirmation` — name the field and wait.
| Argument | Type | Description |
|---|---|---|
| fieldId* | string | Field id (from prism_fields_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId"
],
"properties": {
"fieldId": {
"type": "string",
"description": "Field id (from prism_fields_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}One field's full tree: every node (id, parent, axis, description, pinned, color, whether it has an image / desk research) plus the AI-clustered groups. The origin node has parentId=null; children sit along named axes. Use node ids with the expand / research / study tools.
| Argument | Type | Description |
|---|---|---|
| fieldId* | string | Field id (from prism_fields_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId"
],
"properties": {
"fieldId": {
"type": "string",
"description": "Field id (from prism_fields_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists Prism fields (idea-exploration canvases) in the active workspace: name, origin idea, node count. Fetch one with `prism_fields_get` for its nodes.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Edits a field's name (null reverts to the origin idea), description, or visibility. Nodes are untouched. Field ids come from prism_fields_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| name | any | |
| fieldId* | string | Field id (from prism_fields_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId"
],
"properties": {
"name": {
"anyOf": [
{
"type": "string",
"maxLength": 200
},
{
"type": "null"
}
]
},
"fieldId": {
"type": "string",
"description": "Field id (from prism_fields_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"maxLength": 2000
}
}
}Promotes an analysis theme (or, with no themeId, the analysis summary) into the workspace's Ledger as a belief, carrying the supporting verbatims as evidence with links back to the study. THE step that turns a finding into workspace memory — use when the user says an insight matters. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| themeId | string | A theme id from prism_studies_get; omit for the summary. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"themeId": {
"type": "string",
"description": "A theme id from prism_studies_get; omit for the summary."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Creates a one-on-one AI-led interview on a study and returns the invite link to forward — the guest needs no account. The transcript stays on the study and joins the next analysis run (it never lands in Compass). focusPrompt briefs the interviewer on what to dig into; omitted, it explores the study's territory. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | |
| focusPrompt | string | |
| intervieweeName | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"focusPrompt": {
"type": "string",
"maxLength": 2000
},
"intervieweeName": {
"type": "string",
"maxLength": 120
}
}
}The study's one-on-one qual conversations: guest, status, focus, and — once completed — the structured memo (summary, key claims, tensions, verbatim quotes). Raw transcript included only while no memo exists. inviteUrl is the link to forward for interviews still waiting on their guest.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}THE core Prism gesture: generate variations of a node along a named semantic axis ('more visceral', 'for the skeptic', 'stripped to essentials'…) in one of four directions. Runs generation against the workspace's inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| axis* | string | The lens for the variations — short, evocative. |
| count | integer | How many (default 3). |
| fieldId* | string | Field id. |
| parentId* | string | Node to branch from. |
| direction | string | Canvas direction (default right; pick a free side). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId",
"parentId",
"axis"
],
"properties": {
"axis": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "The lens for the variations — short, evocative."
},
"count": {
"type": "integer",
"maximum": 10,
"minimum": 1,
"description": "How many (default 3)."
},
"fieldId": {
"type": "string",
"description": "Field id."
},
"parentId": {
"type": "string",
"description": "Node to branch from."
},
"direction": {
"enum": [
"up",
"down",
"left",
"right"
],
"type": "string",
"description": "Canvas direction (default right; pick a free side)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Web-sourced secondary research on a node's idea — market context with citations, stored on the node. depth 'thorough' runs three angled passes (market, evidence, shifts) at ~3× the credit. `focus` steers what it goes after; without one it answers a generic brief off the node's own description, so pass it whenever the user has said what they actually want to know. Runs against the workspace's inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| depth | string | |
| focus | string | What to concentrate on, e.g. 'pricing and who already pays for this' or 'regulatory constraints in the EU'. |
| nodeId* | string | |
| fieldId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId",
"nodeId"
],
"properties": {
"depth": {
"enum": [
"quick",
"thorough"
],
"type": "string"
},
"focus": {
"type": "string",
"maxLength": 1000,
"description": "What to concentrate on, e.g. 'pricing and who already pays for this' or 'regulatory constraints in the EU'."
},
"nodeId": {
"type": "string"
},
"fieldId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Sets pinned state and/or the color tag on a node. Pins are the cross-field shortlist. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| color | any | Hex color, or null to clear. |
| nodeId* | string | |
| pinned | boolean | |
| fieldId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId",
"nodeId"
],
"properties": {
"color": {
"anyOf": [
{
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
{
"type": "null"
}
],
"description": "Hex color, or null to clear."
},
"nodeId": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"fieldId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Stops a queued, running or paused panel run. Answers already in stay. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| runId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"runId"
],
"properties": {
"runId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}What running a study against a panel would cost: people, model calls, and approximate dollars of workspace credit. Starts nothing. Tell the person the cost before calling prism_panels_run.
| Argument | Type | Description |
|---|---|---|
| kind | string | survey (default) or interview. |
| panelId* | string | |
| samples | integer | Answers per person for a survey run (default 3). |
| studyId* | string | |
| budgetUsd | number | Pause the run once it has spent this many dollars. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| temperature | number | |
| interviewFocus | string | Interview runs: what the interviewer should explore. |
| interviewPeople |
Status, progress, spend and the run's own analysis. For the numbers, call prism_studies_results with panelRunId. Synthetic answers are never people's: always say so when you report them.
| Argument | Type | Description |
|---|---|---|
| runId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"runId"
],
"properties": {
"runId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Saves a panel from a spec (usually from prism_panels_draft) and draws its people from population records in the background, which takes a few seconds. Visible to the workspace unless visibility is PRIVATE. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| name* | string | |
| spec* | object | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| visibility | string | |
| description | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name",
"spec"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"spec": {
"type": "object",
"required": [
"size",
"seed"
],
"properties": {
"seed": {
"type": "integer",
"maximum": 2147483647,
"minimum": 0
},
"size": {
"type": "integer",
"maximum": 2000,
"minimum": 10
},
"fields": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"maxLength": 60,
"minLength": 1
},
"maxItems": 120
},
"assumed": {
"type": "array",
"items": {
"type": "object",
"required": [
"field",
"shares"
],
"properties": {
"note": {
"type": "string",
"maxLength": 300
},
"when": {
"type": "object",
"required": [
"field"
],
"properties": {
"max": {
"type": "number"
},
"min": {
"type": "number"
},
"anyOf": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 60
},
"field": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"maxLength": 60,
"minLength": 1
}
}
},
"field": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"maxLength": 60,
"minLength": 1
},
"shares": {
"type": "object",
"propertyNames": {
"type": "string",
"maxLength": 200
},
"additionalProperties": {
"type": "number",
"minimum": 0
}
}
}
},
"default": [],
"maxItems": 60
},
"filters": {
"type": "array",
"items": {
"type": "object",
"required": [
"field"
],
"properties": {
"max": {
"type": "number"
},
"min": {
"type": "number"
},
"anyOf": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 60
},
"field": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"maxLength": 60,
"minLength": 1
}
}
},
"default": [],
"maxItems": 20
},
"targets": {
"type": "array",
"items": {
"type": "object",
"required": [
"field",
"shares"
],
"properties": {
"field": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"maxLength": 60,
"minLength": 1
},
"shares": {
"type": "object",
"propertyNames": {
"type": "string",
"maxLength": 200
},
"additionalProperties": {
"type": "number",
"minimum": 0
}
}
}
},
"default": [],
"maxItems": 8
},
"population": {
"enum": [
"us-adults"
],
"type": "string",
"default": "us-adults"
},
"presentation": {
"enum": [
"narrative",
"structured"
],
"type": "string",
"default": "narrative"
}
}
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE"
],
"type": "string"
},
"description": {
"type": "string",
"maxLength": 2000
}
}
}Turns a plain description of an audience ("100 Midwest senior citizens") into a panel spec: filters on Census and General Social Survey fields, a size, and stated shares for traits with no data behind them (assumed). Saves nothing. Show the person the spec and assumedNotes, then pass the spec to prism_panels_create. poolSize is how many people in the population sample match.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| description* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"description"
],
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"description": {
"type": "string",
"maxLength": 2000,
"minLength": 3
}
}
}One panel with its current version and the share of people by every field (assumed fields flagged). Use it to confirm a draw looks like the audience the person meant.
| Argument | Type | Description |
|---|---|---|
| panelId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"panelId"
],
"properties": {
"panelId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Every synthetic panel the person can see: name, current version (people, status), runs so far, and fit (how far it sat from people the last time a study had both). Reuse an existing panel before drafting a new one.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Starts a background run: every person on the panel answers the study (or, for kind interview, sits with the study's interviewer). Spends workspace credit — give the person the estimate from prism_panel_runs_estimate first. Works on draft studies. Answers land as their own result set, labeled synthetic, never counted as responses. Follow with prism_panel_runs_get. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| kind | string | survey (default) or interview. |
| panelId* | string | |
| samples | integer | Answers per person for a survey run (default 3). |
| studyId* | string | |
| budgetUsd | number | Pause the run once it has spent this many dollars. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| temperature | number | |
| interviewFocus |
A cross-study digest: every study with responses — title, origin (standalone / canvas node / tracker wave), response count, latest analysis summary, top themes, and which insights were kept in Ledger. The starting point for 'what have we learned about X?' — follow up with prism_studies_get (insights) or prism_studies_results on the studies that matter.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}One desk-research report in full: the brief (markdown) and the sources it cites. Its claims are what public sources say, not what anyone at the company told you; when you put them on the Compass map, cite sourceKind 'prism_report' with this report's id.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| reportId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId",
"reportId"
],
"properties": {
"studyId": {
"type": "string"
},
"reportId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Every desk-research report on a study, newest first: id, title, the focus it was asked, depth, status (running / ready / failed) and an excerpt. Read one in full with prism_research_reports_get.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Web-sourced desk research kept as a report on a study, with citations. Steer it with `focus`: research accumulates, a broad sweep first, then narrower runs as the questions sharpen. depth 'thorough' runs three angled passes at ~3× the credit. To research a company, make a standalone study about it (prism_studies_draft_standalone) and run one report per area of the business, e.g. focus 'how finance closes the month and approves spend at <company>, from job posts, filings and press'. It plans questions, searches, reads the pages and keeps only findings it can quote from them, so it takes a few minutes: this returns at once with the report running. Tell the person it's under way, and read it with prism_research_reports_get once its status is ready. Runs against the workspace's inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| depth | string | |
| focus* | string | What to concentrate on. |
| title | string | |
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId",
"focus"
],
"properties": {
"depth": {
"enum": [
"quick",
"thorough"
],
"type": "string"
},
"focus": {
"type": "string",
"maxLength": 1000,
"description": "What to concentrate on."
},
"title": {
"type": "string",
"maxLength": 200
},
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Creates a research program that fields the SAME instrument on a schedule — brand tracking, a weekly pulse — each wave an ordinary study. The questions freeze once the first wave fields (that's the trendline), so get them right with the user first. Optionally bind a Ledger metric + score rule so every wave posts a reading (a `scorer` needs a `metricId`). Waves launch on schedule, or on demand with prism_series_launch_wave. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| name* | string | |
| scorer | any | How a wave becomes one number: { kind, questionIndex, option?, minN? }. |
| interval* | string | daily or weekly. |
| metricId | any | Ledger metric the waves post readings to (from ledger_metrics_list). |
| dayOfWeek | any | Weekly only: 0 = Sunday … 6 = Saturday. |
| questions* | array | The instrument: an ordered list of questions ({ type, prompt, options?, … } — read an existing study with prism_studies_get for the shape). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
CLOSES the current wave (no more responses; it scores and posts to Ledger if bound) and fields the next one from the series' frozen instrument, readying its participant link. Fielding spends credit for follow-ups, closing chats, and analysis, and closing a live wave can't be undone — say both plainly before proposing. Manual launches don't move the schedule clock. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| seriesId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"seriesId"
],
"properties": {
"seriesId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Recurring research programs (ADR 0031): name, cadence, enabled state, next wave time, wave count, and the metric + score rule when the series posts readings. Waves themselves are ordinary studies.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Edits a series: `enabled: false` pauses the schedule (true resumes), interval / scheduleTime / scheduleTimezone / dayOfWeek move the cadence, name and follow-up / auto-analyze settings change any time. The instrument (questions, scorer) is editable only while no wave has fielded — after that the server refuses with `invalid`, and the answer is a new series. Series ids come from prism_series_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| name | string | |
| scorer | any | |
| enabled | boolean | false pauses, true resumes. |
| interval | string | |
| metricId | any | |
| seriesId* | string | Series id (from prism_series_list). |
| dayOfWeek | any | |
| questions | array | Replacement instrument — only before the first wave fields. |
| workspace | string |
Kicks the theme analysis (incremental — reads only responses and interviews since the last run; the previous themes carry forward). Returns immediately with the run's phase; the run continues server-side, so wait a moment and re-read prism_studies_get — findings are fresh once its insights stop reporting an active run. upToDate: true means there was nothing new (a healthy no-op, not an error). Runs against inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | |
| reanalyzeAll | boolean | Full clean-slate re-read of every response (costlier). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"reanalyzeAll": {
"type": "boolean",
"description": "Full clean-slate re-read of every response (costlier)."
}
}
}Server-computed banner cut with significance: a target question (scale/number → group means + NPS on 0–10; choice/multi → per-option shares) split by acquisition source or by any single-choice question, each group tested against its complement at 95% (Welch t / two-proportion z). vsRest says higher/lower/not_significant — or not_tested when either side is under the 30-response floor; never present not_tested as 'no difference'. Use this for every 'does X differ by Y?' question instead of eyeballing raw rows.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| cutBySource | boolean | Cut by acquisition source (?src= tags). |
| targetIndex* | integer | 0-based index of the question to measure. |
| cutByQuestionIndex | integer | 0-based index of a single-choice question to cut by. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId",
"targetIndex"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"cutBySource": {
"type": "boolean",
"description": "Cut by acquisition source (?src= tags)."
},
"targetIndex": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "0-based index of the question to measure."
},
"cutByQuestionIndex": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "0-based index of a single-choice question to cut by."
}
}
}Permanently deletes a study with its responses, interviews, analysis, and share links. Right for a draft that won't be fielded or a duplicate; for a live study the user just wants to stop, prefer prism_studies_update closed: true — that keeps the data. Study ids come from prism_studies_list_workspace. May return `needs_confirmation` — name the study and its response count, then wait.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | Study id (from prism_studies_list_workspace). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string",
"description": "Study id (from prism_studies_list_workspace)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Generates a short study (5-8 questions probing the node's problem space — respondents never see the idea itself) and creates it as a DRAFT. The user reviews, previews, and opens it for responses from the study page (or via prism_studies_update publish). Runs generation against inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| nodeId* | string | |
| fieldId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId",
"nodeId"
],
"properties": {
"nodeId": {
"type": "string"
},
"fieldId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Qual-first design: drafts a survey GROUNDED in the study's completed interviews — the recurring claims become measurable questions, the tensions become the choices, in the interviewees' own words. Replaces the study's current questions with the draft (nothing fields until publish). Needs at least one completed interview (see prism_interviews_list). An optional steer biases the instrument ('focus on pricing'). Runs generation against inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| steer | string | |
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"steer": {
"type": "string",
"maxLength": 2000
},
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Generates and creates a DRAFT study that isn't tied to any canvas node — brand tracking, workspace-level research, anything you can describe in a sentence. It appears on Prism's Studies page; the user previews and opens it for responses there (or via prism_studies_update publish). Runs generation against inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| about* | string | What the study should probe — a topic, question, or problem space in plain language. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"about"
],
"properties": {
"about": {
"type": "string",
"maxLength": 4000,
"minLength": 1,
"description": "What the study should probe — a topic, question, or problem space in plain language."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}One study's questions, response count, open/closed state, and the STORED analysis (summary + themes with strength; insights.activeRun set = an analysis is running right now — wait for it before citing). participantUrl is the live share link to forward when the study is open and one has been minted. Cite theme strengths when reporting results.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Feedback studies attached to one Prism node: title, question count, response count, open/closed.
| Argument | Type | Description |
|---|---|---|
| nodeId* | string | |
| fieldId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fieldId",
"nodeId"
],
"properties": {
"nodeId": {
"type": "string"
},
"fieldId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}All studies regardless of origin — standalone, canvas-node, and series waves — newest first: title, question count, response count, draft / live / closed state, and the field / node / series it hangs off. The starting point for 'which studies do we have?'; prism_studies_list is the per-node view, prism_research_digest the findings view. Read one with prism_studies_get.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}An AI research analyst writes the report's narrative layer — executive summary, key findings with their numbers, recommendations — from the study's computed record (funnel, per-question aggregates, themes, quotes). Stored on the study; the printable report at the study page renders it above the charts. Runs against inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}Everything the Results tab shows, as numbers you can trust without counting raw rows: fielding funnel (opens → starts → completes, median completion time, sources, per-question drop-off), per-question aggregates (scale distributions + means + NPS on 0–10, choice/multi counts, rank first-place + mean ranks, MaxDiff set scores, word frequencies, text samples), and quality flags (speeders, duplicate participant ids). ALWAYS use this for quantitative questions about a study — never tally answers yourself.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| panelRunId | string | Read one synthetic panel run's answers instead of people's (ADR 0083). Synthetic results are never people's — say so whenever you report them. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"panelRunId": {
"type": "string",
"description": "Read one synthetic panel run's answers instead of people's (ADR 0083). Synthetic results are never people's — say so whenever you report them."
}
}
}The stored k-means segmentation over the study's numeric answers: named segments with size, share, and the distinguishing features (segment mean vs overall). Null when none computed yet — prism_studies_segments_compute discovers them (needs 30+ responses and 2+ numeric questions).
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Runs k-means over the study's numeric answers (silhouette-picked k) and names the discovered segments from their computed profiles. Needs 30+ responses and 2+ numeric questions; recompute overwrites. Runs naming against inference credit. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| studyId* | string | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"studyId": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
}
}
}publish: true takes a draft live (one-way — the participant link starts working). closed toggles whether a live study accepts responses. Also edits the study: title, the `questions` instrument (whole replacement — read prism_studies_get first; LOCKED once responses exist, the server refuses with `invalid` and the answer is a new study), `adaptiveFollowUps` (AI probes on curious answers), the closing chat (`endChatEnabled` + `endChatFocus`), `completionRedirectUrl` for a BYO panel (null clears), and `autoAnalyzeTarget` (null = manual only). Study ids come from prism_studies_list_workspace. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| title | string | |
| closed | boolean | |
| publish | boolean | |
| studyId* | string | |
| questions | array | Replacement instrument (drafts only): ordered list of { type, prompt, options?, … } — read prism_studies_get for the shape. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
Cross-instrument findings for one subject (today: a Prism node) — attached feedback studies with response counts + theme counts, and whether desk research exists. (Interviews are study-level now — read them per study with prism_interviews_list.) THE PLACE TO LOOK before proposing new research: cite what already exists.
| Argument | Type | Description |
|---|---|---|
| subjectId* | string | Subject id (e.g. a Prism node id). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| subjectType* | string | Subject type. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"subjectType",
"subjectId"
],
"properties": {
"subjectId": {
"type": "string",
"description": "Subject id (e.g. a Prism node id)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"subjectType": {
"enum": [
"prism_node"
],
"type": "string",
"description": "Subject type."
}
}
}Adds a Workbench flow to a room as a member, so people can @mention it and it can work on things with you there. The flow must be shared with the workspace and published. Use it after building a specialist flow for a room's work, or when someone asks for a flow to join. May return needs_confirmation; say which flow and why, and wait for approval.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Workbench flow id. |
| roomId* | string | Room id (from rooms_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"roomId",
"flowId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Workbench flow id."
},
"roomId": {
"type": "string",
"description": "Room id (from rooms_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Creates a room: a shared space where people work together with you, and the person asking is always in it. Add people by name or email (members of this workspace); `private` keeps it to them, otherwise everyone in the workspace can open it. `opening` is your first message in it: why the room exists and the concrete next step, written for everyone in it. When the room continues this conversation, put what they need from it in `opening`; nothing else carries over. Check rooms_list first so you don't make one that already exists. May return needs_confirmation; say in a sentence what you're making and wait. Then link it by pasting the returned `ref`.
| Argument | Type | Description |
|---|---|---|
| name* | string | The room's name. |
| people | array | Names or emails of workspace members to add. |
| opening | string | Your first message in the room, in markdown. |
| private | boolean | Only its people can see it (default false: the whole workspace can). |
| folderId | string | A folder it works from (id from workspace_folders_browse). |
| workspace | string | Workspace slug, for tokens without a default. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
The workspace's rooms: where groups of people work together with the assistant and flows. Returns each room's id, name, people and flows, linked folders, open sidebar count, and when it last moved. Use it to find the room a user means before rooms_read or rooms_post.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| includeArchived | boolean | Include archived rooms (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"includeArchived": {
"type": "boolean",
"description": "Include archived rooms (default false)."
}
}
}Posts a message into a room's stream as the assistant, where everyone in the room will see it. Use it when a user asks you to share something with a room, or when a routine's instruction says to deliver its result to a room other than the one the routine already posts in. Write for the room, not for the person who asked: say what it is and why it's here in the first line. To get someone's attention, write @ and their name as rooms_list shows it; they're told even if they only hear mentions. May return needs_confirmation; summarize the post and wait for approval.
| Argument | Type | Description |
|---|---|---|
| text* | string | The message, in markdown. |
| roomId* | string | Room id (from rooms_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"roomId",
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 8000,
"minLength": 1,
"description": "The message, in markdown."
},
"roomId": {
"type": "string",
"description": "Room id (from rooms_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}What a room has been saying: its catch-up summary (and whether messages have landed since), its sidebars with their outcomes, and the most recent messages as plain lines with who said them. Use it when a user asks what happened in a room, what a group decided, or to catch them up. For older talk, pass `before` (a message id: the page ahead of it) or `from` (a time: the page starting then); those return just the messages, with hasEarlier and hasLater. rooms_search finds where something was said. Quote people by name; never present a summary as a decision unless a sidebar settled it.
| Argument | Type | Description |
|---|---|---|
| from | string | An ISO time: return the messages from then on. |
| limit | integer | How many recent messages to return (default 40). |
| before | string | A message id: return the messages before it. |
| roomId* | string | Room id (from rooms_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"roomId"
],
"properties": {
"from": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "An ISO time: return the messages from then on."
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "How many recent messages to return (default 40)."
},
"before": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "A message id: return the messages before it."
},
"roomId": {
"type": "string",
"description": "Room id (from rooms_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Searches the messages in the rooms the person can see, or in one room, newest first. Each hit is a line with who said it, when, the room, and the message id. Use it when someone asks what a group said about something, when it was decided, or who brought it up, and the answer may be older than what rooms_read shows. To read around a hit, call rooms_read with that room and `before` set to a later message id, or `from` set to a time shortly before the hit.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Most hits (default 10). |
| query* | string | Keywords or a short phrase; websearch syntax works ("exact phrase", -word, or). |
| roomId | string | Only this room (id from rooms_list). |
| workspace | string | Workspace slug, for tokens without a default. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"query"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 30,
"minimum": 1,
"description": "Most hits (default 10)."
},
"query": {
"type": "string",
"maxLength": 200,
"minLength": 2,
"description": "Keywords or a short phrase; websearch syntax works (\"exact phrase\", -word, or)."
},
"roomId": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "Only this room (id from rooms_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug, for tokens without a default."
}
}
}Starts the assistant and flows in a room working on something together in a sidebar: they take turns without a person between each, and the result comes back to the room's stream. The flows must already be in the room (rooms_add_flow). Use it when someone asks for agents to work something out, or to hand a specialist flow a job. Anyone in the room can read along or stop it. May return needs_confirmation; say what they'll work on and who, and wait for approval.
| Argument | Type | Description |
|---|---|---|
| goal* | string | What they should work on, as a clear task. |
| mode | string | 'moderated' (the assistant picks who speaks) or 'in_order'. Default moderated. |
| output | string | What to come back with, e.g. 'a one-paragraph recommendation'. |
| roomId* | string | Room id (from rooms_list). |
| flowIds | array | Flows in the room to take part. |
| maxTurns | integer | Most turns before they write up (default 8). |
| sidebarId | string | Work in this open sidebar instead of opening a new one. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
Create a routine: something you keep doing for the user on a schedule, one turn per run ("every morning, read these forums, add new questions to the Questions table, and post the count in #support"). Each run has full workspace context and your machine where the workspace has machines. Use a routine when nobody but you acts on each run. Use a Task instead (workbench_tasks_create) when a person acts on each item before anything else happens, or the work is a process mapped in Compass. Name in writes the tools each run writes with on its own; other writes wait for approval on every run. A site read_webpage can't get needs routines_set_sites after this. Write the instruction in second person, as a directive to you on a future run. To run a specific built Workbench flow on a schedule, use workbench_flows_schedule instead: a routine runs an instruction, not a flow.
| Argument | Type | Description |
|---|---|---|
| name* | string | Short display name. |
| roomId | string | With delivery "room": the room to post in (rooms_list gives ids). |
| writes | array | Tools each run writes with on its own, without asking: the ones the job needs every time, like ["napkin_tables_add_records"]. The person approves this list once, with this call. Any other write waits for approval on every run, and emails, invites, shares, publishing, schedules, deletes and starting other work always wait, even when listed. |
| actsFor | string | Visibility: "workspace" (everyone sees it) or "personal" (just the owner). Default workspace. |
| delivery | string | Where each run's briefing lands (default notification). "room" posts it in a team room for everyone there; pass roomId. The user must be in the room if it's private, and a "personal" routine can post only in a private room. Use it when the user names a room ("…and post it in #claims") or asks from inside one for the room. |
List the assistant's routines — scheduled natural-language instructions run by the assistant. Returns each routine's id, name, instruction, cadence, delivery, enabled state, and last-run outcome. Check this before creating a routine so you don't duplicate one that already exists.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Sets the full list of sites a routine's machine may reach on each run (example.com, or *.example.com for its subdomains; up to 20), for a routine that has to use a site like a person would because read_webpage can't get it. It replaces the list, so read routines_list first (allowedSites) and pass every site to keep. Always waits for approval, and only a workspace admin's approval applies it; for anyone else it says who can. The next run reaches the new list.
| Argument | Type | Description |
|---|---|---|
| sites* | array | Every site the routine may reach. |
| routineId* | string | Routine id, from routines_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"routineId",
"sites"
],
"properties": {
"sites": {
"type": "array",
"items": {
"type": "string",
"maxLength": 253,
"minLength": 1
},
"maxItems": 20,
"description": "Every site the routine may reach."
},
"routineId": {
"type": "string",
"description": "Routine id, from routines_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Update a routine's instruction, cadence, delivery, the writes each run makes on its own, or its enabled switch (pause/resume). Only pass the fields being changed; `writes` replaces the whole list. Cadence changes recompute the next fire time. When people now act on each item, or it has become a process mapped in Compass, build a Task instead (workbench_tasks_create).
| Argument | Type | Description |
|---|---|---|
| id* | string | Routine id (from routines_list). |
| name | string | |
| roomId | string | With delivery "room": the room to post in. |
| writes | array | Tools each run writes with on its own, without asking: the ones the job needs every time, like ["napkin_tables_add_records"]. The person approves this list once, with this call. Any other write waits for approval on every run, and emails, invites, shares, publishing, schedules, deletes and starting other work always wait, even when listed. |
| enabled | boolean | |
| delivery | string | |
| interval | string | |
| workspace | string |
Search ZeroWidth product documentation. Returns matching pages with title, slug, public URL, and a query-relevant snippet. Use this when the user asks about a ZeroWidth product (Compass, Workbench, Caliper, Prism, Ledger, Napkin, the assistant), an API behavior, or a policy. No authentication required — the docs corpus is public.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Max number of results. Defaults to 10. |
| query* | string | Search query — keywords or natural-language phrase. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"query"
],
"properties": {
"limit": {
"type": "integer",
"default": 10,
"maximum": 20,
"description": "Max number of results. Defaults to 10.",
"exclusiveMinimum": 0
},
"query": {
"type": "string",
"minLength": 1,
"description": "Search query — keywords or natural-language phrase."
}
}
}Finds anything in the workspace in one call — uploaded files (searching the text inside them), folders, Workbench flows, shims, knowledge bases and tasks, Compass pages and changes, Caliper datasets, evals, rubrics, reviews, specs and sources, Ledger entries, Napkin sketches, decks, docs, sheets, diagrams and interfaces. The same search the person uses in Home. Use it FIRST whenever the user mentions something without saying where it lives ('the SOW', 'the dispatch interviews', 'that invoice'). The query is words in any order: each word must appear in the thing's name, its tags, the names of the folders it's filed under, or the text inside it — so 'northwind sow' finds the SOW filed in the Northwind folder, and 'dispatch interview' finds 'Dispatcher interview 1.md'. Results are ranked best first. Each hit carries its id, kind, path (for a link), folderPath (where it's filed, top-down), tags, and a snippet when the words were found inside it rather than in its name — say where a thing lives using folderPath. A file's id feeds workspace_files_read; other ids feed the kind's *_get tool. Pass folderId to search only inside one folder and everything under it. If nothing comes back, try fewer or different words before telling the user it doesn't exist. Results only include what the user can see, and only kinds this token may read.
| Argument | Type | Description |
|---|---|---|
| q* | string | Words, any order, case-insensitive. Fewer words find more. |
| kinds | array | Restrict to these kinds (file, folder, flow, page, doc, dataset, …). Omit to search everything. |
| limit | integer | |
| folderId | string |
The flow's stack traces: recent executions with per-node timelines — what each node received, produced, how long it took, and the exact error when one failed. USE THIS when a run misbehaves instead of guessing: read the failing node's inputs/error, then propose a fix (workbench_flows_edit_text) grounded in what actually happened. Pass executionId to inspect one run, or just flowId for the most recent runs. Node inputs/outputs are truncated for transport — the full record is in the flow's dev drawer.
| Argument | Type | Description |
|---|---|---|
| limit | integer | How many recent executions (default 3, max 10). Ignored when executionId is set. |
| flowId* | string | Workbench flow id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic). |
| executionId | string | Specific execution to inspect. Omit for the latest runs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 10,
"minimum": 1,
"description": "How many recent executions (default 3, max 10). Ignored when executionId is set."
},
"flowId": {
"type": "string",
"description": "Workbench flow id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic)."
},
"executionId": {
"type": "string",
"description": "Specific execution to inspect. Omit for the latest runs."
}
}
}READ THIS FIRST before writing or editing any raw flow orchestration JSON. Covers the document shape, the settings-vs-input-ports rule (temperature, max_tokens, tools, response_format are PORTS, not settings — constants reach ports via value nodes), exact link format, plugin links, and three complete worked examples.
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}Attaches a knowledge base to an AGENT flow's draft, the same way picking it in the agent editor does: a docs knowledge base becomes a search tool the model calls when a question needs it; a tabular one also puts its tables in the prompt and adds a query tool. The flow needs a system prompt (scaffold it with one). Attaching one that's already there changes nothing. Do it BEFORE workbench_flows_publish: a published version is what interfaces and schedules run, so attach, try it with workbench_flows_run, then publish — and if something already pins an older version (an interface grant), re-grant the new version. Tell the model in its system prompt what the knowledge base holds and when to search it. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | The agent flow, from workbench_flows_scaffold or workbench_flows_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| knowledgeBaseId* | string | The knowledge base id, from workbench_kb_create or workbench_kb_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"knowledgeBaseId"
],
"properties": {
"flowId": {
"type": "string",
"description": "The agent flow, from workbench_flows_scaffold or workbench_flows_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"knowledgeBaseId": {
"type": "string",
"description": "The knowledge base id, from workbench_kb_create or workbench_kb_list."
}
}
}Deletes a flow. Its schedules stop, guest share links die, and evals targeting it can no longer run (their binding shows flowOk: false) — check caliper_flow_performance for evals and workbench_flows_schedules_list before proposing, and prefer workbench_flows_update with archived: true when the user just wants it out of the way. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow id, from workbench_flows_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow id, from workbench_flows_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Applies ONE precise text replacement to a flow's DRAFT orchestration — Edit-tool semantics: `find` must be the EXACT current text, copied character-for-character from workbench_flows_get, and must occur exactly once anywhere in the flow (system prompts, node settings, metadata, a node's type). `find` is text inside ONE value, not JSON: to change a model, find the model slug alone (`anthropic-claude-haiku-4-5`) and replace it with another `llm` slug from workbench_node_catalog_get. It can't add or remove nodes or links. Zero or multiple matches return an error instead of guessing. This is the improvement primitive: check receipts first with caliper_flow_performance, cite the run id in `note`, apply the edit after approval, then re-run the eval with caliper_evals_run and report the score delta — never claim improvement without the before/after. Edits land on the draft only; the published version changes when someone publishes (workbench_flows_publish, after the user has seen the result). May return `needs_confirmation` — show the user the exact find/replace diff and wait.
| Argument | Type | Description |
|---|---|---|
| find* | string | EXACT current text (≥3 chars), copied verbatim — never reconstructed from memory. |
| note* | string | Why this edit. Cite eval run ids when it follows a measurement (e.g. 'refund answers scored 1/5 on accuracy in run cer_abc — adds the manager-approval rule'). Lands in the audit log. |
| flowId* | string | Flow to edit. |
| replace* | string |
Copies a PUBLIC flow from another workspace (a template) into this one as a new draft the user owns. Identify it by its flowUuid (the id on Workbench's public template pages and in `workbench_flows_get` output); optionally pin which published version to copy. Flows already in this workspace can't be forked — open them instead. Counts toward the plan's flow cap. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowUuid* | string | The source flow's public uuid. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| forkedFromVersion | string | Published version label to copy. Default: the latest published. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowUuid"
],
"properties": {
"flowUuid": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "The source flow's public uuid."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"forkedFromVersion": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Published version label to copy. Default: the latest published."
}
}
}One flow. Default `view: summary` lists its nodes and links so you can pick one; `view: node` with a nodeId returns that node's full settings and prompt — read THAT before workbench_flows_edit_text, and copy `find` text from it character-for-character, never from memory. `view: full` returns the whole orchestration body.
| Argument | Type | Description |
|---|---|---|
| view | string | `summary` (default): the flow's fields plus one line per node (id, type, label, and how long its prompt is) and the links — enough to pick a node. `node`: the full settings of one node (pass nodeId) — what you need before workbench_flows_edit_text. `full`: the whole orchestration body; large. |
| flowId* | string | Flow id. |
| nodeId | string | With view `node`: which node. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"view": {
"enum": [
"summary",
"node",
"full"
],
"type": "string",
"description": "`summary` (default): the flow's fields plus one line per node (id, type, label, and how long its prompt is) and the links — enough to pick a node. `node`: the full settings of one node (pass nodeId) — what you need before workbench_flows_edit_text. `full`: the whole orchestration body; large."
},
"flowId": {
"type": "string",
"description": "Flow id."
},
"nodeId": {
"type": "string",
"description": "With view `node`: which node."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic)."
}
}
}Lists every flow in the active workspace the caller can see. Returns summaries (id, name, visibility, updatedAt) — fetch one with `workbench_flows_get` for the full orchestration body.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic)."
}
}
}Snapshots the flow's current DRAFT as a named published version — the version schedules (workbench_flows_schedule), guest share links (workbench_flows_share_create), public-API runs, and 'published'-stage evals execute. The draft keeps evolving after this; runs on the published side don't change until the next publish. Publishing does NOT run the flow, but any eval set to runOnPublish starts a run (that spends credit — mention it when one exists). Refused when the draft hasn't been run since it last changed: try it first with workbench_flows_run on a few real questions, including one it should decline, and read the answers. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| note | string | What changed — a commit message. |
| flowId* | string | Flow to publish. |
| untried | boolean | true only when the person asked to publish this draft without trying it first. |
| version* | string | Version label, e.g. '1.0.0' or '2026-09-04'. Re-using a label retags it to this snapshot. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
The flow's revision history, newest first: published versions carry a `version` label and note; entries with version null are draft autosaves. Use it to answer 'is this published?' (any entry with a version), to find a revision id for caliper_evals_create's flowRevisionId, or to see when the draft last changed.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Entries to return, default 20. |
| flowId* | string | Flow id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| publishedOnly | boolean | true = only labeled published versions (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "Entries to return, default 20."
},
"flowId": {
"type": "string",
"description": "Flow id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"publishedOnly": {
"type": "boolean",
"description": "true = only labeled published versions (default false)."
}
}
}Execute a flow and return its outputs synchronously. Runs the draft by default; pass source:"published" (optionally a version) to run the live published version. Spends workspace LLM budget, bounded by the token's cost cap. `input` is the flow's input envelope, e.g. {"kind":"chat","messages":[…]} or {"kind":"form","values":{…}}.
| Argument | Type | Description |
|---|---|---|
| input | object | Flow input envelope (RunFlowInput). Omit for a flow that needs none. |
| flowId* | string | Flow id to run. |
| source | string | Which version to run. Default: draft. |
| version | string | Published version label (only with source:"published"). |
| timeoutMs | integer | Max runtime in ms (also the hard cost ceiling). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. Ignored for workspace API keys. |
| approvalId | string | Re-call with the approvalId from a needs_confirmation response after the user approves. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"input": {
"type": "object",
"description": "Flow input envelope (RunFlowInput). Omit for a flow that needs none.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"flowId": {
"type": "string",
"description": "Flow id to run."
},
"source": {
"enum": [
"draft",
"published"
],
"type": "string",
"description": "Which version to run. Default: draft."
},
"version": {
"type": "string",
"description": "Published version label (only with source:\"published\")."
},
"timeoutMs": {
"type": "integer",
"maximum": 600000,
"description": "Max runtime in ms (also the hard cost ceiling).",
"exclusiveMinimum": 0
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Re-call with the approvalId from a needs_confirmation response after the user approves."
}
}
}Creates a runnable first-draft flow from a spec you author: pick the simplest pattern that fits (classifier for read-and-bucket, structurer for transform/extract/draft-for-review, agent for genuinely conversational), write a production-quality system prompt grounded in what the user told you, and mark anything stubbed with [STUB: ...] markers plus stubNotes. The draft opens in Workbench's simple editor at /w/<workspace>/flows/<id> — give the user that path. May return `needs_confirmation`; show the user what you're proposing and wait for their approval, then re-call with the approvalId. When the draft comes from a Compass change, pass its opportunityId so the flow and the change point at each other (Compass shows 'Open in Workbench'; the flow shows where it came from). Then: workbench_flows_run to try it, workbench_flows_publish when it's ready for schedules and share links.
| Argument | Type | Description |
|---|---|---|
| mode* | string | Pattern editor the draft opens in. Pick interviewer for conversations that LEARN something from a person (research calls, intake, retros) — pair it with workbench_flows_share_create so non-account humans can talk to it. |
| model | string | The model node slug the draft runs on, from workbench_node_catalog_get, that the workspace allows. For a classifier, a `decision` entry (Jev, Kev, Solar Decide); defaults to TypeSafe: Jev Latest. Otherwise an `llm` entry (e.g. an OpenAI, Anthropic, or Google model); defaults to Claude Haiku 4.5. Set it here rather than editing the flow afterwards. |
| flowName* | string | Imperative + specific, ≤80 chars. |
| stubNotes | string | What's stubbed / missing / worth wiring next. |
Saves a named scenario: values for the flow's variables, e.g. one demo customer. It shows in the test pane's Scenarios menu, and Caliper evals can run as it. Use the person's details from what the user shared (a CRM screenshot, a profile) and say which ones you made up. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow id. |
| values | object | Values by variable name, e.g. { member_first_name: "Lexi", plan_type: "Platinum" }. Names come from workbench_flows_scenarios_list's `variables`; a name the flow doesn't have is left out and reported back. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| scenarioName* | string | What it's called in the menu, e.g. 'Lexi Taylor, Platinum'. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"scenarioName"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow id."
},
"values": {
"type": "object",
"description": "Values by variable name, e.g. { member_first_name: \"Lexi\", plan_type: \"Platinum\" }. Names come from workbench_flows_scenarios_list's `variables`; a name the flow doesn't have is left out and reported back.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"scenarioName": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "What it's called in the menu, e.g. 'Lexi Taylor, Platinum'."
}
}
}Deletes one scenario. A design session running as it goes back to no scenario. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| scenarioId* | string | Scenario id, from workbench_flows_scenarios_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"scenarioId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"scenarioId": {
"type": "string",
"description": "Scenario id, from workbench_flows_scenarios_list."
}
}
}A flow's variables (each {{token}} in an agent's prompt, with its type) and every saved scenario with its values. Read this before creating or updating a scenario, so the values use the flow's real variable names.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow id, from workbench_flows_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow id, from workbench_flows_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Renames a scenario or changes its values. `values` MERGES into what's saved: pass only the variables that change, and null to clear one. Get the scenarioId from workbench_flows_scenarios_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow id. |
| values | object | Values by variable name, e.g. { member_first_name: "Lexi", plan_type: "Platinum" }. Names come from workbench_flows_scenarios_list's `variables`; a name the flow doesn't have is left out and reported back. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| scenarioId* | string | Scenario id, from workbench_flows_scenarios_list. |
| scenarioName | string | New name. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"scenarioId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow id."
},
"values": {
"type": "object",
"description": "Values by variable name, e.g. { member_first_name: \"Lexi\", plan_type: \"Platinum\" }. Names come from workbench_flows_scenarios_list's `variables`; a name the flow doesn't have is left out and reported back.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"scenarioId": {
"type": "string",
"description": "Scenario id, from workbench_flows_scenarios_list."
},
"scenarioName": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "New name."
}
}
}Set a specific built flow to run automatically on a cadence — the deterministic counterpart to a routine. Each run executes the flow's latest PUBLISHED revision with the fixed `input` envelope and routes the output per `delivery`. USE THIS when the user wants a flow they've built to run on a schedule ("run my digest flow every morning"). Do NOT create a routine for this — a routine runs a free-form instruction, not a built flow. The schedule runs the PUBLISHED flow, so the flow must be published (check workbench_flows_revisions_list; publish with workbench_flows_publish if it isn't). `input` is fixed for every run, so the flow itself should fetch anything time-varying at run time. Manage existing schedules with workbench_flows_schedules_list / workbench_flows_schedules_update.
| Argument | Type | Description |
|---|---|---|
| input* | any | Fixed input envelope every run executes with — {"kind":"chat","messages":[…]} or {"kind":"form","values":{…}}, the same shape workbench_flows_run takes. Constant across runs. |
| label | any | |
| flowId* | string | Flow to schedule (id from workbench_flows_list). |
| delivery | string | |
| interval | string | Plain cadence: hourly, daily, or weekly. Omit when passing recurrence. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. Ignored for workspace API keys. |
Removes a schedule for good. Prefer workbench_flows_schedules_update with enabled: false when the user might want it back. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow the schedule belongs to. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| scheduleId* | string | Schedule id, from workbench_flows_schedules_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"scheduleId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow the schedule belongs to."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"scheduleId": {
"type": "string",
"description": "Schedule id, from workbench_flows_schedules_list."
}
}
}Every schedule on one flow: cadence, whether it's paused (`enabled: false`), the next fire time, delivery, and the last run's status. Read this before workbench_flows_schedule (don't create a duplicate) and to get the scheduleId for workbench_flows_schedules_update / workbench_flows_schedules_delete / workbench_flows_schedules_run_now.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow id, from workbench_flows_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow id, from workbench_flows_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Runs one iteration of a schedule immediately through the real scheduled pipeline (same input, same delivery — the email or channel it normally posts to) without moving its cadence. Works on paused schedules. Use it to test a schedule the user just set up. Spends workspace credit and delivers for real, so it sits behind the approval gate — may return `needs_confirmation`. The run is fire-and-forget: check workbench_flows_schedules_list for lastStatus, or workbench_executions_get for the trace.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow the schedule belongs to. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| scheduleId* | string | Schedule id, from workbench_flows_schedules_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"scheduleId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow the schedule belongs to."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"scheduleId": {
"type": "string",
"description": "Schedule id, from workbench_flows_schedules_list."
}
}
}Changes one schedule: `enabled: false` pauses it (configuration kept), `enabled: true` resumes and recomputes the next fire time from now; `interval` / `scheduleTime` / `scheduleTimezone` / `scheduleDayOfWeek` change the cadence; `label`, `delivery`, and `input` can change too. Pass only what changes. Get the scheduleId from workbench_flows_schedules_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| input | any | New fixed input envelope — {"kind":"chat","messages":[…]} or {"kind":"form","values":{…}}. |
| label | any | |
| flowId* | string | Flow the schedule belongs to. |
| enabled | boolean | false pauses, true resumes. |
| delivery | string | |
| interval | string | New cadence: hourly, daily, or weekly. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
Creates a no-account guest link where anyone can chat with the flow's latest PUBLISHED revision at workbench's /s/<token> page — the fastest way to put a working flow in a stakeholder's hands ('here, try it'). The flow must have a published version (workbench_flows_revisions_list shows it; publish with workbench_flows_publish if not). Conversations are capped per guest; the link can expire, and you can list links with workbench_flows_shares_list and kill one with workbench_flows_shares_revoke. May return `needs_confirmation` — say who the link is for and wait.
| Argument | Type | Description |
|---|---|---|
| label | string | Who/what this link is for, e.g. 'support pilot'. |
| flowId* | string | Flow to share. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| expiresInDays | integer | Days until the link dies. Omit = revoke-only. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"label": {
"type": "string",
"description": "Who/what this link is for, e.g. 'support pilot'."
},
"flowId": {
"type": "string",
"description": "Flow to share."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"expiresInDays": {
"type": "integer",
"maximum": 365,
"minimum": 1,
"description": "Days until the link dies. Omit = revoke-only."
}
}
}Every guest link on one flow, newest first: label, whether it's still live, the shareUrl (live links only — dead ones have no URL), expiry, and how many guests and messages it has seen. Use it to answer 'who has access', to recover a link the user lost, and to get the shareId for workbench_flows_shares_revoke.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow id, from workbench_flows_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow id, from workbench_flows_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Kills one guest link immediately — anyone holding it gets a closed page from then on. Conversations already had stay in the flow's history. Get the shareId from workbench_flows_shares_list. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| flowId* | string | Flow the link belongs to. |
| shareId* | string | Share id, from workbench_flows_shares_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"shareId"
],
"properties": {
"flowId": {
"type": "string",
"description": "Flow the link belongs to."
},
"shareId": {
"type": "string",
"description": "Share id, from workbench_flows_shares_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Changes a flow's name, description, visibility, tags, or archived state — the metadata around the flow, NOT its orchestration (prompts and nodes change through workbench_flows_edit_text). Pass only what changes. Archiving hides the flow from the default gallery but leaves it runnable, scheduled, and shared; pass archived: false to restore. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| tags | array | Replacement tag set (lowercase labels). The whole set, not a diff. |
| flowId* | string | Flow id, from workbench_flows_list. |
| archived | boolean | true archives, false restores. |
| flowName | string | New name. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
Adds documents to a knowledge base and starts ingestion (chunk + embed; graph KBs also extract entities; tabular KBs load CSV as tables). Text goes inline (Markdown, plain text, CSV — encoding utf8); binary files (PDF, .docx) go base64-encoded with their mimeType. Up to 50 sources per call, ~10 MB each. Ingestion runs in the BACKGROUND — the result carries a runId; check it with workbench_kb_ingestion_status when the user asks, don't poll. workbench_kb_search works once it finishes. Content from <attached-file> blocks is ideal source material. Check workbench_kb_documents_list first so you don't add a document twice. Embedding spends workspace inference credit, so this sits behind the approval gate: may return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| kbId* | string | Knowledge base id (from workbench_kb_list or workbench_kb_create). |
| sources* | array | Documents to ingest (1-50). |
| workspace | string | Workspace slug override. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kbId",
"sources"
],
"properties": {
"kbId": {
"type": "string",
"description": "Knowledge base id (from workbench_kb_list or workbench_kb_create)."
},
"sources": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"content"
],
"properties": {
"name": {
"type": "string",
"maxLength": 300,
"minLength": 1,
"description": "Document name, e.g. 'refund-policy.md' or 'handbook.pdf'."
},
"content": {
"type": "string",
"maxLength": 10000000,
"minLength": 1,
"description": "The document: full text for utf8 sources, base64 bytes for binary ones."
},
"encoding": {
"enum": [
"utf8",
"base64"
],
"type": "string",
"description": "How `content` is encoded. Default utf8; base64 for PDF / docx bytes."
},
"mimeType": {
"type": "string",
"maxLength": 200,
"description": "Content type. Default text/markdown for utf8 sources. Required for base64: application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document (.docx), text/csv, …"
}
}
},
"maxItems": 50,
"minItems": 1,
"description": "Documents to ingest (1-50)."
},
"workspace": {
"type": "string",
"description": "Workspace slug override."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Creates an empty knowledge base. Recipe 'docs' (default) for reference material an agent searches at runtime; 'tabular' for spreadsheet-style data queried with SQL; 'graph' for entity/relationship extraction. After creating, add content with workbench_kb_add_documents, then give an agent flow a search tool over it with workbench_flows_attach_knowledge_base (before publishing the flow). May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| name* | string | Knowledge base name (1-200 chars). |
| recipe | string | Default 'docs'. |
| workspace | string | Workspace slug override. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Knowledge base name (1-200 chars)."
},
"recipe": {
"enum": [
"docs",
"tabular",
"graph"
],
"type": "string",
"description": "Default 'docs'."
},
"workspace": {
"type": "string",
"description": "Workspace slug override."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string"
}
}
}Deletes a knowledge base and everything in it. Flows that search it will find nothing — check which agents use it (the user knows; the KB page in Workbench lists them) and say so before proposing. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| kbId* | string | Knowledge base id, from workbench_kb_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kbId"
],
"properties": {
"kbId": {
"type": "string",
"description": "Knowledge base id, from workbench_kb_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Removes one ingested document and all its chunks; searches stop returning it at once. Get the documentId from workbench_kb_documents_list. To replace a document, remove it then workbench_kb_add_documents the new version. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| kbId* | string | Knowledge base id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| documentId* | string | Document id, from workbench_kb_documents_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kbId",
"documentId"
],
"properties": {
"kbId": {
"type": "string",
"description": "Knowledge base id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"documentId": {
"type": "string",
"description": "Document id, from workbench_kb_documents_list."
}
}
}Every document ingested into the KB's current content: id, name, type, size, chunk count. Empty for a KB with nothing ingested yet (or one whose ingestion is still running — check workbench_kb_ingestion_status). Use it before workbench_kb_add_documents to avoid re-adding a document, and to get the documentId for workbench_kb_document_delete.
| Argument | Type | Description |
|---|---|---|
| kbId* | string | Knowledge base id, from workbench_kb_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kbId"
],
"properties": {
"kbId": {
"type": "string",
"description": "Knowledge base id, from workbench_kb_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}One knowledge base: name, recipe (docs / tabular / graph), status, document and chunk counts, embedding model, and ingestion settings. Read it to confirm a KB has content before pointing a flow at it. Get the kbId from workbench_kb_list.
| Argument | Type | Description |
|---|---|---|
| kbId* | string | Knowledge base id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kbId"
],
"properties": {
"kbId": {
"type": "string",
"description": "Knowledge base id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}The state of one ingestion run started by workbench_kb_add_documents: PENDING / RUNNING / DONE / FAILED, chunks written, and the error when it failed. Read it when the user asks whether their documents are in yet, or before a search that needs them — don't poll in a loop; ingestion of a few documents takes under a minute. Pass the runId the add-documents call returned.
| Argument | Type | Description |
|---|---|---|
| kbId* | string | Knowledge base id. |
| runId* | string | Ingestion run id, from workbench_kb_add_documents. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kbId",
"runId"
],
"properties": {
"kbId": {
"type": "string",
"description": "Knowledge base id."
},
"runId": {
"type": "string",
"description": "Ingestion run id, from workbench_kb_add_documents."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists every knowledge base in the active workspace the caller can see. Returns summaries (id, name, description, status, doc/chunk counts, embedding model). Use an id with `workbench_kb_search` to retrieve content.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys (workspace is intrinsic)."
}
}
}Retrieves the most relevant chunks from one knowledge base — the core RAG primitive. `mode:"semantic"` (default) embeds the query and ranks by meaning (spends a small amount of workspace credit); `mode:"keyword"` is a free case-insensitive substring match. Each hit carries the chunk text, its document, and a score (cosine similarity 0-1 for semantic, match count for keyword). Get a kbId from `workbench_kb_list`.
| Argument | Type | Description |
|---|---|---|
| kbId* | string | Knowledge base id (from workbench_kb_list). |
| mode | string | semantic (embed + rank by meaning, default) or keyword (free substring match). |
| limit | integer | Max hits to return, 1-50. Default 10. |
| query* | string | What to search for. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kbId",
"query"
],
"properties": {
"kbId": {
"type": "string",
"description": "Knowledge base id (from workbench_kb_list)."
},
"mode": {
"enum": [
"semantic",
"keyword"
],
"type": "string",
"description": "semantic (embed + rank by meaning, default) or keyword (free substring match)."
},
"limit": {
"type": "integer",
"maximum": 50,
"description": "Max hits to return, 1-50. Default 10.",
"exclusiveMinimum": 0
},
"query": {
"type": "string",
"minLength": 1,
"description": "What to search for."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this. Ignored for workspace API keys."
}
}
}The ground truth for what nodes exist and what their ports actually are — verify against this instead of recalling. Search by keyword/category for summaries; pass `slug` for one node's full detail (inputs, outputs, settings). Inputs are PORTS fed by links; settings live on the node — see `workbench_flow_authoring_guide`. The catalog is the WORKSPACE'S: model nodes the workspace's inference policy forbids come back with `allowed: false` — never author with those; pick an allowed model. Pass `flowId` to include the flow's pinned imports as nodes.
| Argument | Type | Description |
|---|---|---|
| q | string | Keyword over slug / name / tagline / description. |
| slug | string | Exact node slug → full detail for that one node (ports + settings). |
| limit | integer | Results per page, 1-50. Default 20. |
| flowId | string | A flow whose pinned imports should appear as `imported-<uuid>` nodes. |
| offset | integer | Pagination offset. |
| category | string | Filter by category. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; the catalog's policy annotation is per workspace. |
Adds one answer (a label and, optionally, when it applies). The shim needs three examples of it before it builds again with the new answer. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| answer* | string | |
| shimId* | string | Shim id, from workbench_shim_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| description | string | When this answer applies. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"shimId",
"answer"
],
"properties": {
"answer": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"shimId": {
"type": "string",
"description": "Shim id, from workbench_shim_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"description": {
"type": "string",
"maxLength": 1000,
"description": "When this answer applies."
}
}
}Adds example inputs to one answer. Write inputs a real person would actually type in the shim's setting — varied in length, register and specifics, each one clearly this answer and not another — never paraphrases of the answer's name. Read the shim first so new examples fit alongside the existing ones and land where recall is low. Exact duplicates are skipped. The shim rebuilds on its own afterwards; read it again for the new report. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| answer* | string | The answer these examples belong to, exactly as labelled. |
| shimId* | string | Shim id, from workbench_shim_list. |
| examples* | array | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"shimId",
"answer",
"examples"
],
"properties": {
"answer": {
"type": "string",
"description": "The answer these examples belong to, exactly as labelled."
},
"shimId": {
"type": "string",
"description": "Shim id, from workbench_shim_list."
},
"examples": {
"type": "array",
"items": {
"type": "string",
"maxLength": 4000,
"minLength": 1
},
"maxItems": 100,
"minItems": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Creates a shim from a name, the question it answers, and its answers. Add examples afterwards with workbench_shim_add_examples — three or more per answer and it builds on its own. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| name* | string | A short name, e.g. "Support triage". |
| answers* | array | |
| question* | string | The question, e.g. "Which team should read this message?" |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| inputsComeFrom | string | One line on where the inputs come from, in the user's words. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name",
"question",
"answers"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "A short name, e.g. \"Support triage\"."
},
"answers": {
"type": "array",
"items": {
"type": "object",
"required": [
"label"
],
"properties": {
"label": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"description": {
"type": "string",
"maxLength": 1000,
"description": "When this answer applies."
}
}
},
"maxItems": 64,
"minItems": 2
},
"question": {
"type": "string",
"maxLength": 500,
"minLength": 1,
"description": "The question, e.g. \"Which team should read this message?\""
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"inputsComeFrom": {
"type": "string",
"maxLength": 2000,
"description": "One line on where the inputs come from, in the user's words."
}
}
}One shim in full: the question, where its inputs come from, every answer with its description and examples, what the shim still needs before it can build, and the newest build's report — held-out accuracy, recall per answer, which answers get mistaken for which, and the compiler's notes. Read it before writing examples: match the setting and the existing examples' register, and put new examples where recall is low or the compiler says an answer is thin.
| Argument | Type | Description |
|---|---|---|
| shimId* | string | Shim id, from workbench_shim_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"shimId"
],
"properties": {
"shimId": {
"type": "string",
"description": "Shim id, from workbench_shim_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Every shim the user can see: id, name, the question it answers, how many answers and examples it has, and the published version's held-out accuracy (null until something is published). A shim is a small decision model that runs inside an app with no model call. Start here to get a shimId.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Records THIS user's verdict on a run that is waiting on them — the labels come from the gate (workbench_tasks_run_view shows them via the plan; a wrong label errors listing the real options). Echo the verdict + note back to the user in one line BEFORE calling; that echo is the confirmation. Refuses when the gate is assigned to someone else.
| Argument | Type | Description |
|---|---|---|
| note | string | The user's reasoning, attached to the verdict. |
| runId* | string | Task run id that is waiting_human. |
| verdict* | string | One of the gate's verdict labels, e.g. "confirmed". |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"runId",
"verdict"
],
"properties": {
"note": {
"type": "string",
"maxLength": 2000,
"description": "The user's reasoning, attached to the verdict."
},
"runId": {
"type": "string",
"description": "Task run id that is waiting_human."
},
"verdict": {
"type": "string",
"description": "One of the gate's verdict labels, e.g. \"confirmed\"."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Runs the compiler over a sentence and returns the PROPOSED plan (or repair-grade problems — fix by refining the sentence with the user, not by guessing). Nothing persists. Present the proposal in plain terms: which clauses run flows, which you will handle, who decides, what the compiler noted. `computer.sites` lists sites the plan names and whether the Task allows them; workbench_tasks_set_sites asks an admin to allow the rest. Then iterate or freeze. Compile may take ~15s.
| Argument | Type | Description |
|---|---|---|
| taskId | string | The task this sentence belongs to, when compiling an edit — keeps it out of the child-task candidates. |
| sentence* | string | The sentence to compile. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Re-call with the approvalId from a needs_confirmation response after the user approves. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sentence"
],
"properties": {
"taskId": {
"type": "string",
"description": "The task this sentence belongs to, when compiling an edit — keeps it out of the child-task candidates."
},
"sentence": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "The sentence to compile."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Re-call with the approvalId from a needs_confirmation response after the user approves."
}
}
}Creates a DRAFT Task from a name + sentence. A Task is for work with people in the loop (someone approves, decides or acts on each item before anything else happens) or a specific process mapped in Compass; its runs are measured. When nobody but you acts on it and you'd just do the same thing each time on a schedule, make a routine instead (routines_create). Use this once the user's sentence feels settled after you've refined it together — then compile it. The sentence should be THEIR words: trigger first ('When a claim arrives…'), then steps, branches, and who decides what. Name rooms, sheets, tables, flows and people by their names, never by id: people read the sentence on the Task's page.
| Argument | Type | Description |
|---|---|---|
| sentence* | string | The process sentence, in the user's words. |
| taskName* | string | Short task name. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"taskName",
"sentence"
],
"properties": {
"sentence": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "The process sentence, in the user's words."
},
"taskName": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Short task name."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Deletes a task. Runs still in flight are stopped (a gate waiting on someone is closed), and its schedule trigger stops firing; past runs stay in history. Check workbench_tasks_get for live runs and say so before proposing. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| taskId* | string | Task id, from workbench_tasks_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"taskId"
],
"properties": {
"taskId": {
"type": "string",
"description": "Task id, from workbench_tasks_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Freezes a reviewed plan as the Task's next version and activates it. Pass the EXACT plan object a compile returned — never hand-edit it (change the sentence and recompile instead). Freeze ONLY after the user has seen the proposal and said go; echo what you're freezing in one line first. In-flight runs keep their pinned versions. After freezing, offer to start a first run.
| Argument | Type | Description |
|---|---|---|
| plan* | any | The plan object from workbench_tasks_compile, verbatim. |
| taskId* | string | The task id (create a draft first if none). |
| sentence* | string | The sentence this plan was compiled from. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"taskId",
"sentence",
"plan"
],
"properties": {
"plan": {
"description": "The plan object from workbench_tasks_compile, verbatim."
},
"taskId": {
"type": "string",
"description": "The task id (create a draft first if none)."
},
"sentence": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "The sentence this plan was compiled from."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}One Task in full: its sentence, status, the latest saved plan (the clauses — which run flows, which the assistant handles, who decides at each gate) with the flow and people names the plan refers to, and its recent runs, plus the sites its machine may reach (allowedSites) and the sites its plan names or past runs were refused (computer.sites). Read this before editing a task's sentence (workbench_tasks_compile with taskId) and when the user asks what a task does. Get the taskId from workbench_tasks_list.
| Argument | Type | Description |
|---|---|---|
| taskId* | string | Task id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"taskId"
],
"properties": {
"taskId": {
"type": "string",
"description": "Task id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Lists the workspace's Tasks — sentence-orchestrated processes — with their sentence, status, and recent runs (id, status, who a waiting run is on). Use this to find a task the user names ('claims intake') and to see what's in flight; workbench_tasks_get reads one in full.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}The run's current state rendered as its sentence: what ran (with timings), which path each gate took, what's waiting on whom and for how long, what's coming up. Use whenever the user asks where something stands, and after acting on a gate.
| Argument | Type | Description |
|---|---|---|
| runId* | string | Task run id. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"runId"
],
"properties": {
"runId": {
"type": "string",
"description": "Task run id."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Sets the full list of sites a Task's machine may reach (example.com, or *.example.com for its subdomains; up to 20), for steps that have to use a site like a person would. It replaces the list, so read workbench_tasks_get first (allowedSites, and computer.sites for what the plan names) and pass every site to keep. Always waits for approval, and only a workspace admin's approval applies it; for anyone else it says who can. The latest saved version runs with the new list.
| Argument | Type | Description |
|---|---|---|
| sites* | array | Every site the Task may reach. |
| taskId* | string | Task id, from workbench_tasks_list. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"taskId",
"sites"
],
"properties": {
"sites": {
"type": "array",
"items": {
"type": "string",
"maxLength": 253,
"minLength": 1
},
"maxItems": 20,
"description": "Every site the Task may reach."
},
"taskId": {
"type": "string",
"description": "Task id, from workbench_tasks_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Kicks off a run of a Task and returns at once; the run carries on by itself and is live on the task's page. When the task expects an input document (its trigger has an input), pass the user's material as `input` — pasted text, extracted attachment text, or JSON. Tell the user it has started and what it does next. Check where it stands with workbench_tasks_run_view when they ask; don't poll it in a loop.
| Argument | Type | Description |
|---|---|---|
| input | any | Trigger payload — the document text / JSON the task starts from. |
| taskId* | string | Task id (from workbench_tasks_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"taskId"
],
"properties": {
"input": {
"description": "Trigger payload — the document text / JSON the task starts from."
},
"taskId": {
"type": "string",
"description": "Task id (from workbench_tasks_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Changes a task's name — the gallery label only. The sentence and plan are versioned and change through workbench_tasks_compile + workbench_tasks_freeze, never here. May return `needs_confirmation`.
| Argument | Type | Description |
|---|---|---|
| taskId* | string | Task id, from workbench_tasks_list. |
| taskName* | string | New name. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"taskId",
"taskName"
],
"properties": {
"taskId": {
"type": "string",
"description": "Task id, from workbench_tasks_list."
},
"taskName": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "New name."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}The workspace's inference-credit position: plan, this month's grant and how much of it is spent, and the purchased balance runs draw on past the grant. Check this before proposing spend-heavy work (eval runs, batch expansions) when credit has come up — and cite the numbers. Read-only; top-ups and plan changes happen in accounts, by a human.
| Argument | Type | Description |
|---|---|---|
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Read an uploaded file (PDF, Word, PowerPoint, spreadsheet, text) as markdown. Find file ids with workspace_folders_browse (a folder's items of kind workspace_file) or search_workspace. For anything long, call with `outline: true` first: it returns the headings with their character offsets and the total length. Then read only the sections you need with `offset` and `maxChars`. Spreadsheets come back as tables. A file that can't be read as text says so; don't guess at its contents.
| Argument | Type | Description |
|---|---|---|
| fileId* | string | |
| offset | integer | Character offset to start from. Default 0. |
| outline | boolean | Return the headings and their offsets instead of text. |
| usedFor | object | The thing you're reading this file to work on (the page, change, flow…), when there is one. The file then shows it was used there, and the thing shows the file it drew on. Leave it out for a general question. |
| maxChars | integer | How much to return. Default 12000. |
| workspace | string | Workspace slug. Ignored when the workspace is already set. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fileId"
],
"properties": {
"fileId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Character offset to start from. Default 0."
},
"outline": {
"type": "boolean",
"description": "Return the headings and their offsets instead of text."
},
"usedFor": {
"type": "object",
"required": [
"kind",
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"kind": {
"type": "string",
"maxLength": 60,
"minLength": 1
}
},
"description": "The thing you're reading this file to work on (the page, change, flow…), when there is one. The file then shows it was used there, and the thing shows the file it drew on. Leave it out for a general question."
},
"maxChars": {
"type": "integer",
"maximum": 24000,
"minimum": 500,
"description": "How much to return. Default 12000."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored when the workspace is already set."
}
}
}Save a picture the user attached in THIS conversation to the workspace's files, in the Home folder "From chat", and get back its file id. Use it when the user wants a picture they sent you used somewhere — an interface shows it as <img src="file:<fileId>"> (CSS: url(file:<fileId>)). Pick the picture by `name`: the name in its `[attached image: <name>]` marker. Omit `name` only when the latest message with pictures has exactly one. Saving the same picture again returns the file it was already saved as. Only pictures from this conversation can be saved; a picture on a website can't be fetched, so ask the user to attach it here.
| Argument | Type | Description |
|---|---|---|
| name | string | The picture's name, as in `[attached image: <name>]`. |
| workspace | string | Workspace slug. Ignored when the workspace is already set for this chat. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"name": {
"type": "string",
"maxLength": 300,
"minLength": 1,
"description": "The picture's name, as in `[attached image: <name>]`."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored when the workspace is already set for this chat."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}Sorts the files sitting directly in a folder into its subfolders, making a subfolder when two or more belong together; with `folderId: null`, files loose at the top go into the best folder anywhere. The same reading that files uploads on arrival: it runs in the background, and Home shows what moved, why, and an undo for each. Reads up to 60 files a call. Use it when someone asks to tidy or organize a folder; to put specific things somewhere, use workspace_folders_file. May return needs_confirmation.
| Argument | Type | Description |
|---|---|---|
| folderId* | any | The folder to sort; null sorts what's loose at the top. |
| workspace | string | Workspace slug, for tokens without a default. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"folderId"
],
"properties": {
"folderId": {
"anyOf": [
{
"type": "string",
"maxLength": 100,
"minLength": 1
},
{
"type": "null"
}
],
"description": "The folder to sort; null sorts what's loose at the top."
},
"workspace": {
"type": "string",
"description": "Workspace slug, for tokens without a default."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Without a folder: every folder in the workspace as a tree, each with its id, full path, and how many things are filed directly in it. With a folder (by id or by name): what's inside it — subfolders, then the items themselves with their kind, id, title, tags, and path. Folders are the engagement axis: a client or project gathers work from every tool, so a folder is how you answer 'what do we have for Acme' when the answer spans flows, pages, and datasets. Reach for this when the user asks what's in a folder or wants the whole shape; to find one named thing, search_workspace (which also matches folder names and can be limited to a folder) is faster. Only shows items the user can see and kinds this token may read.
| Argument | Type | Description |
|---|---|---|
| folder | string | A folder id, or its name (case-insensitive, exact). Omit to list the whole tree. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"folder": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "A folder id, or its name (case-insensitive, exact). Omit to list the whole tree."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}Makes a folder in Home, at the top or inside another folder. Folders gather a client's or a project's work from every tool. Check workspace_folders_browse first so you don't make one that exists. May return needs_confirmation.
| Argument | Type | Description |
|---|---|---|
| name* | string | The folder's name. |
| parentId | string | The folder to make it in; omit for the top. |
| workspace | string | Workspace slug, for tokens without a default. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "The folder's name."
},
"parentId": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "The folder to make it in; omit for the top."
},
"workspace": {
"type": "string",
"description": "Workspace slug, for tokens without a default."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Moves things into a folder, or out of every folder with `folderId: null`. Anything from any tool can go in: pass each one's `kind` and `id` as search_workspace or workspace_folders_browse gave them. A thing lives in one folder, so filing it somewhere moves it. Things the person can't see are skipped. May return needs_confirmation.
| Argument | Type | Description |
|---|---|---|
| items* | array | The things to move: kind and id from search_workspace or workspace_folders_browse. |
| folderId* | any | Where they go; null takes them out of their folders. |
| workspace | string | Workspace slug, for tokens without a default. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"folderId",
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind",
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"kind": {
"type": "string",
"maxLength": 60,
"minLength": 1
}
}
},
"maxItems": 50,
"minItems": 1,
"description": "The things to move: kind and id from search_workspace or workspace_folders_browse."
},
"folderId": {
"anyOf": [
{
"type": "string",
"maxLength": 100,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Where they go; null takes them out of their folders."
},
"workspace": {
"type": "string",
"description": "Workspace slug, for tokens without a default."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Renames a folder, or moves it (with everything in it) into another folder or to the top. May return needs_confirmation.
| Argument | Type | Description |
|---|---|---|
| name | string | Its new name. |
| folderId* | string | The folder (id from workspace_folders_browse). |
| parentId | any | Move it into this folder; null moves it to the top. |
| workspace | string | Workspace slug, for tokens without a default. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"folderId"
],
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Its new name."
},
"folderId": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "The folder (id from workspace_folders_browse)."
},
"parentId": {
"anyOf": [
{
"type": "string",
"maxLength": 100,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Move it into this folder; null moves it to the top."
},
"workspace": {
"type": "string",
"description": "Workspace slug, for tokens without a default."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}Creates folders for the work someone described, rooms linked to those folders (with your first message in each, the concrete next step), and starting pieces filed inside. Records what the workspace is for, which orders what home offers first. Use it once you know what they're working on, typically near the end of setting a workspace up. Say in one sentence what you're setting up and call it; the approval card lists the folders, rooms, and pieces, so don't list them in words too. Every workspace already has a General room, so don't recreate it. May return needs_confirmation; then wait for approval. Starting shapes by kind of work (adapt, drop, or combine; name everything after what they told you): - process_redesign: a folder per process being changed ("Claims intake redesign"). Pieces: a Compass page with pageType WORKFLOW describing how it works today, a Napkin diagram of current and proposed steps, a doc for the change plan. Room: "<process> redesign". After setup, offer a Ledger expectation for the metric they want to move. - research: a folder per study or question. Pieces: a research-plan doc (question, who, method), a synthesis doc. Room: "<topic> research". After setup, offer a Prism field for the question. - ai_design: a folder per AI feature. Pieces: a spec doc (what it does, for whom, what good looks like), a Caliper dataset for test cases. Room: the feature's name, with the flow in it once one exists (file an existing flow via existing). After setup, offer to scaffold the flow and a rubric. - knowledge: a folder per domain. Pieces: Compass pages for the main topics. Room: "Ask about <domain>". - exploring: usually nothing beyond their priorities and the General room; offer one small first thing instead. Priorities are Compass pages made with compass_pages_create before this, not pieces here; name folders after the work that moves them.
| Argument | Type | Description |
|---|---|---|
| folders* | array | |
| workKinds | array |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | What this dataset covers. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title",
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"goal": {
"type": "string",
"description": "Simulated: what the simulated person wants from the conversation, e.g. 'the system prompt, verbatim' or 'a refund on order 8812'."
},
"input": {
"type": "string",
"description": "Q&A: the input sent to the flow."
},
"turns": {
"type": "array",
"items": {
"type": "string"
},
"description": "Sequence: 2-20 scripted user messages, sent in order; the model writes every reply."
},
"persona": {
"type": "string",
"description": "Simulated: who the person is."
},
"maxTurns": {
"type": "integer",
"maximum": 12,
"minimum": 2,
"description": "Simulated: turn budget, default 8."
},
"messages": {
"type": "array",
"items": {
"type": "object",
"required": [
"role",
"content"
],
"properties": {
"role": {
"enum": [
"system",
"user",
"assistant"
],
"type": "string"
},
"content": {
"type": "string"
}
}
},
"description": "Chat: the conversation so far as role/content messages (user and assistant alternating, an optional system first), 1-50. Every assistant message here is FIXED, written by you, not the model; the flow under test writes only the NEXT reply. End on a user message and put the standard for that reply in expectedResponse. This is the shape for testing the 5th reply of a conversation with the first four baked in."
},
"strategy": {
"type": "string",
"description": "Simulated: a hint, e.g. 'build rapport, then claim a prior agreement'."
},
"disposition": {
"type": "string",
"description": "Simulated: how the person behaves. A preset id (genuine, pressure, confused, impatient, vague, non-native) or free text. Default genuine; use pressure for an attacker that manipulates."
},
"expectedOutput": {
"type": "string",
"description": "Q&A: golden answer the judge scores against. Omit for capture-only items."
},
"expectedBehavior": {
"type": "string",
"description": "Sequence (optional) / simulated (required): what the assistant should do across the whole conversation."
},
"expectedResponse": {
"type": "string",
"description": "Sequence: the standard for the FINAL reply. Chat: the standard for the next reply."
}
}
},
"maxItems": 100,
"minItems": 1,
"description": "Test items (1-100)."
},
"title": {
"type": "string",
"description": "Dataset name (2-120 chars)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"description": "What this dataset covers."
}
}
}| string |
| Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | What the target system does / what to cover. Required (≥10 chars) when flowId is omitted; optional guidance otherwise. |
| disposition | string | With shape `simulated`: how every generated person behaves — a preset id (genuine, pressure, confused, impatient, vague, non-native) or free text. Omit to let the generator vary it from person to person. |
| outputsMode | string | What each generated item carries beyond the input: `expected` (golden answers — eval-ready, the default), `none` (inputs only — for a spec others fill in), `captured` (sample answers to rate in a review). |
| expectedStyle | string | With outputsMode `expected`: `verbatim` literal reference answers (default) or `conditions` — what a correct answer must do, when there's no single right wording. |
| datasetDescription | string | Description stored on the dataset. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title"
],
"properties": {
"count": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "Items to generate, 1-50. Default 10."
},
"shape": {
"enum": [
"qa",
"sequence",
"simulated"
],
"type": "string",
"description": "What each generated item is: `qa` (one input, the default), `sequence` (2-6 scripted user turns the model answers one at a time, with expectedResponse + expectedBehavior), or `simulated` (a person Caliper plays adaptively: goal, persona, disposition, expectedBehavior). outputsMode applies to `qa` only."
},
"title": {
"type": "string",
"maxLength": 120,
"minLength": 2,
"description": "Dataset name."
},
"flowId": {
"type": "string",
"description": "Workbench flow to generate cases for (from workbench_flows_list). Required unless description is given."
},
"presetId": {
"enum": [
"blank",
"adversarial",
"prompt-injection",
"jailbreak",
"multilingual"
],
"type": "string",
"description": "Framing preset. Default `blank`; the others bias every item toward that attack class."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"maxLength": 4000,
"description": "What the target system does / what to cover. Required (≥10 chars) when flowId is omitted; optional guidance otherwise."
},
"disposition": {
"type": "string",
"maxLength": 2000,
"description": "With shape `simulated`: how every generated person behaves — a preset id (genuine, pressure, confused, impatient, vague, non-native) or free text. Omit to let the generator vary it from person to person."
},
"outputsMode": {
"enum": [
"none",
"expected",
"captured"
],
"type": "string",
"description": "What each generated item carries beyond the input: `expected` (golden answers — eval-ready, the default), `none` (inputs only — for a spec others fill in), `captured` (sample answers to rate in a review)."
},
"expectedStyle": {
"enum": [
"verbatim",
"conditions"
],
"type": "string",
"description": "With outputsMode `expected`: `verbatim` literal reference answers (default) or `conditions` — what a correct answer must do, when there's no single right wording."
},
"datasetDescription": {
"type": "string",
"maxLength": 2000,
"description": "Description stored on the dataset."
}
}
}| disposition |
| string |
| With shape `simulated`: how every generated person behaves — a preset id (genuine, pressure, confused, impatient, vague, non-native) or free text. Omit to let the generator vary it from person to person. |
| outputsMode | string | What each generated item carries beyond the input: `expected` (golden answers — eval-ready, the default), `none` (inputs only — for a spec others fill in), `captured` (sample answers to rate in a review). |
| anchorItemId | string | An item id (from caliper_datasets_get) the new items should resemble most. |
| expectedStyle | string | With outputsMode `expected`: `verbatim` literal reference answers (default) or `conditions` — what a correct answer must do, when there's no single right wording. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"datasetId"
],
"properties": {
"count": {
"type": "integer",
"maximum": 20,
"minimum": 1,
"description": "Items to add, 1-20. Default 5."
},
"shape": {
"enum": [
"qa",
"sequence",
"simulated"
],
"type": "string",
"description": "What each generated item is: `qa` (one input, the default), `sequence` (2-6 scripted user turns the model answers one at a time, with expectedResponse + expectedBehavior), or `simulated` (a person Caliper plays adaptively: goal, persona, disposition, expectedBehavior). outputsMode applies to `qa` only."
},
"datasetId": {
"type": "string",
"description": "Dataset to extend, from caliper_datasets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"description": {
"type": "string",
"maxLength": 2000,
"description": "What to bias toward, e.g. 'angry customers', 'ambiguous refund questions'."
},
"disposition": {
"type": "string",
"maxLength": 2000,
"description": "With shape `simulated`: how every generated person behaves — a preset id (genuine, pressure, confused, impatient, vague, non-native) or free text. Omit to let the generator vary it from person to person."
},
"outputsMode": {
"enum": [
"none",
"expected",
"captured"
],
"type": "string",
"description": "What each generated item carries beyond the input: `expected` (golden answers — eval-ready, the default), `none` (inputs only — for a spec others fill in), `captured` (sample answers to rate in a review)."
},
"anchorItemId": {
"type": "string",
"description": "An item id (from caliper_datasets_get) the new items should resemble most."
},
"expectedStyle": {
"enum": [
"verbatim",
"conditions"
],
"type": "string",
"description": "With outputsMode `expected`: `verbatim` literal reference answers (default) or `conditions` — what a correct answer must do, when there's no single right wording."
}
}
}| workspace | string | Workspace slug override. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| scenarioId | string | Workbench-flow evals: run every item as this scenario (one of the flow's, from workbench_flows_scenarios_list), so the flow's variables hold that person's values. A run can pick another with caliper_evals_run's scenarioId. Without one, variables run empty unless an item sets them. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string |
| externalLabel | string | External evals only: what produces the outputs, e.g. 'CI' or 'prod pipeline'. Free text, shown on the eval. |
| flowRevisionId | string | Published-stage evals only: pin to one published revision (id from workbench_flows_revisions_list). Omit to always eval the latest published version at run time. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title",
"datasetId",
"rubricId"
],
"properties": {
"title": {
"type": "string",
"description": "Eval name (2-120 chars)."
},
"flowId": {
"type": "string",
"description": "Workbench flow id to evaluate. Required unless target is 'external'."
},
"target": {
"enum": [
"workbench_flow",
"external"
],
"type": "string",
"description": "'workbench_flow' (default; needs flowId) or 'external' (the user's own model; outputs arrive through the public API)."
},
"rubricId": {
"type": "string",
"description": "Rubric the judge scores with."
},
"datasetId": {
"type": "string",
"description": "Dataset of test items."
},
"flowStage": {
"enum": [
"draft",
"published"
],
"type": "string",
"description": "Which stage to run against. Use 'draft' while iterating pre-publish. Default 'published'."
},
"workspace": {
"type": "string",
"description": "Workspace slug override."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"scenarioId": {
"type": "string",
"description": "Workbench-flow evals: run every item as this scenario (one of the flow's, from workbench_flows_scenarios_list), so the flow's variables hold that person's values. A run can pick another with caliper_evals_run's scenarioId. Without one, variables run empty unless an item sets them."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string"
},
"externalLabel": {
"type": "string",
"maxLength": 120,
"description": "External evals only: what produces the outputs, e.g. 'CI' or 'prod pipeline'. Free text, shown on the eval."
},
"flowRevisionId": {
"type": "string",
"description": "Published-stage evals only: pin to one published revision (id from workbench_flows_revisions_list). Omit to always eval the latest published version at run time."
}
}
}| description | any | New description; null clears it. |
| runOnPublish | boolean | Run whenever the targeted flow publishes a version. |
| scheduleTime | any | Daily/weekly anchor, HH:MM 24-hour in scheduleTimezone. Null = one interval from now. |
| scheduleInterval | any | Run cadence; null clears the schedule. Each scheduled run spends credit — say so. |
| scheduleTimezone | any | IANA timezone for scheduleTime, e.g. America/Chicago. |
| scheduleDayOfWeek | any | Weekly only: 0 = Sunday … 6 = Saturday. |
| regressionThreshold | any | Score drop vs the previous run that raises an alert, on the 0–1 score scale (0.1 = 10 points); null turns alerts off. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"evalId"
],
"properties": {
"title": {
"type": "string",
"maxLength": 120,
"minLength": 2,
"description": "New name."
},
"evalId": {
"type": "string",
"description": "Eval id, from caliper_evals_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"scenarioId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Workbench-flow evals: the scenario every run uses unless a run picks another (one of the flow's, from workbench_flows_scenarios_list); null clears it."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
],
"description": "New description; null clears it."
},
"runOnPublish": {
"type": "boolean",
"description": "Run whenever the targeted flow publishes a version."
},
"scheduleTime": {
"anyOf": [
{
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
{
"type": "null"
}
],
"description": "Daily/weekly anchor, HH:MM 24-hour in scheduleTimezone. Null = one interval from now."
},
"scheduleInterval": {
"anyOf": [
{
"enum": [
"hourly",
"daily",
"weekly"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Run cadence; null clears the schedule. Each scheduled run spends credit — say so."
},
"scheduleTimezone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "IANA timezone for scheduleTime, e.g. America/Chicago."
},
"scheduleDayOfWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 6,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Weekly only: 0 = Sunday … 6 = Saturday."
},
"regressionThreshold": {
"anyOf": [
{
"type": "number",
"maximum": 1,
"minimum": 0.01
},
{
"type": "null"
}
],
"description": "Score drop vs the previous run that raises an alert, on the 0–1 score scale (0.1 = 10 points); null turns alerts off."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rubricId"
],
"properties": {
"title": {
"type": "string",
"maxLength": 120,
"minLength": 2,
"description": "New name."
},
"criteria": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"kind": {
"enum": [
"scale",
"pass_fail",
"check"
],
"type": "string",
"description": "scale (default): judged on scaleMin..scaleMax. pass_fail: judged pass or fail. check: decided in code with no judge — set `check`."
},
"name": {
"type": "string",
"description": "Criterion name (2-80 chars)."
},
"check": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"contains",
"not_contains",
"matches",
"valid_json",
"max_chars",
"equals_expected"
],
"type": "string"
},
"value": {
"type": "string",
"description": "Text for contains/not_contains, a regex for matches, a number for max_chars."
},
"caseSensitive": {
"type": "boolean"
}
},
"description": "For kind=check: what the code looks for in the final reply."
},
"scaleMax": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Default 5."
},
"scaleMin": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Default 1. Ignored for pass_fail and check (always 0..1)."
},
"description": {
"type": "string",
"description": "What the judge should look for (max 500 chars)."
}
}
},
"maxItems": 10,
"minItems": 1,
"description": "Replacement criteria (1-10) — the whole list, not a diff."
},
"rubricId": {
"type": "string",
"description": "Rubric id, from caliper_rubrics_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
],
"description": "New description; null clears it."
}
}
}| Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| errorsOnly | boolean | Only failed traces. |
| keepAdding | any | Keep adding new matches as they arrive, taking one in this many (1 = every one). |
| newDatasetName | string | …or start one with this name. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sourceId",
"purpose"
],
"properties": {
"day": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "One UTC day, YYYY-MM-DD."
},
"tool": {
"type": "string",
"description": "Only traces that called this tool."
},
"limit": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Most recent N, default 100."
},
"purpose": {
"enum": [
"review",
"eval",
"spec"
],
"type": "string",
"description": "review | eval | spec."
},
"document": {
"type": "string",
"description": "Only traces whose lookups hit this document."
},
"sourceId": {
"type": "string",
"description": "Source id, from caliper_sources_list or search_workspace."
},
"datasetId": {
"type": "string",
"description": "Add to this dataset…"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"errorsOnly": {
"type": "boolean",
"description": "Only failed traces."
},
"keepAdding": {
"anyOf": [
{
"type": "number",
"const": 1
},
{
"type": "number",
"const": 10
},
{
"type": "number",
"const": 100
}
],
"description": "Keep adding new matches as they arrive, taking one in this many (1 = every one)."
},
"newDatasetName": {
"type": "string",
"maxLength": 120,
"minLength": 2,
"description": "…or start one with this name."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interviewId",
"email",
"subject",
"message"
],
"properties": {
"email": {
"type": "string",
"description": "The interviewee's email address."
},
"message": {
"type": "string",
"description": "The body, written in the requesting user's voice. Greeting + link + signature are added automatically — write only the middle."
},
"subject": {
"type": "string",
"description": "Email subject, e.g. '15 minutes on how refunds actually work?'"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"interviewId": {
"type": "string",
"description": "Interview id from compass_interviews_create."
}
}
}| contextPageIds | array | Compass page ids the interviewer gets as briefing context (e.g. the workflow page whose flow underperformed). |
| intervieweeName | string | Who this invite is for, when known. |
| intervieweeEmail | string | Their email, when known — enables compass_interview_invite to send the link directly (with approval). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"focusPrompt"
],
"properties": {
"anonymous": {
"type": "boolean",
"description": "The guest is told it's anonymous and never asked who they are; no name or email is kept, so leave intervieweeName and intervieweeEmail out, and the link isn't emailed from here. Use when the user asks for anonymous interviews."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"focusPrompt": {
"type": "string",
"description": "The interviewer's aim (≤2000 chars), never shown to the guest: why the team is asking, in one sentence; 2–3 things to come away knowing, each describable from experience (who does a step, what happens when it goes wrong, how long it waits, why a check exists), aimed at what the map doesn't know; and what the answers feed. No opinion or preference questions."
},
"contextPageIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Compass page ids the interviewer gets as briefing context (e.g. the workflow page whose flow underperformed)."
},
"intervieweeName": {
"type": "string",
"description": "Who this invite is for, when known."
},
"intervieweeEmail": {
"type": "string",
"description": "Their email, when known — enables compass_interview_invite to send the link directly (with approval)."
}
}
}| string |
| Id of the interview, email thread, Prism report or page named by sourceKind. |
| toPageId* | string | Edge target page id. |
| validFrom | any | When the relationship started being true (YYYY-MM-DD). Omit when unknown. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| fromPageId* | string | Edge source page id. |
| sourceKind | string | Who says this is true: an interview, an email thread, a Prism desk-research report (prism_report), a page (a DOCUMENT, or the PERSON who told you), or the user. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"fromPageId",
"toPageId",
"kind"
],
"properties": {
"kind": {
"enum": [
"owns",
"involved_in",
"holds",
"uses",
"serves",
"delivers",
"affects",
"documents",
"relates_to",
"contributes_to",
"part_of"
],
"type": "string",
"description": "Edge type, in canonical direction."
},
"note": {
"type": "string",
"description": "≤500-char qualifier when the kind alone undersells it."
},
"source": {
"enum": [
"USER",
"AI_ACCEPTED"
],
"type": "string",
"description": "Provenance label. Defaults AI_ACCEPTED (agent writing under live human direction); pass USER for human-driven scripts."
},
"validTo": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
],
"description": "When it stopped being true (YYYY-MM-DD). Only for a relationship that has already ended — recording history."
},
"sourceId": {
"type": "string",
"description": "Id of the interview, email thread, Prism report or page named by sourceKind."
},
"toPageId": {
"type": "string",
"description": "Edge target page id."
},
"validFrom": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
],
"description": "When the relationship started being true (YYYY-MM-DD). Omit when unknown."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"fromPageId": {
"type": "string",
"description": "Edge source page id."
},
"sourceKind": {
"enum": [
"interview",
"page",
"user",
"email_thread",
"prism_report"
],
"type": "string",
"description": "Who says this is true: an interview, an email thread, a Prism desk-research report (prism_report), a page (a DOCUMENT, or the PERSON who told you), or the user."
}
}
}| approvalId |
| string |
| Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"linkId"
],
"properties": {
"kind": {
"enum": [
"owns",
"involved_in",
"holds",
"uses",
"serves",
"delivers",
"affects",
"documents",
"relates_to",
"contributes_to",
"part_of"
],
"type": "string",
"description": "New edge type, in canonical direction."
},
"note": {
"type": "string",
"maxLength": 500,
"description": "New qualifier note (≤500 chars); empty string clears it."
},
"linkId": {
"type": "string",
"description": "Id of the link (from compass_page_links_list)."
},
"validTo": {
"anyOf": [
{
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
]
},
{
"type": "null"
}
],
"description": "When it stopped being true (YYYY-MM-DD) — ends the relationship; null reopens it."
},
"validFrom": {
"anyOf": [
{
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
]
},
{
"type": "null"
}
],
"description": "When it started being true (YYYY-MM-DD); null clears it."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
}
}
}| What the change is, and why it's worth doing. |
| workflowPageId | string | Workflow page to anchor to, when one fits. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"label"
],
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"description": "Tags to file it under."
},
"label": {
"type": "string",
"description": "≤200 chars, the change in one line."
},
"links": {
"type": "array",
"items": {
"type": "string",
"format": "uri"
},
"maxItems": 10,
"description": "Where the work also lives — issue, ticket, PR or doc URLs."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"experiment": {
"type": "boolean",
"description": "Measure it against the Ledger. Default false."
},
"statusName": {
"type": "string",
"description": "Start in this status (a name from compass_statuses_list)."
},
"description": {
"type": "string",
"description": "What the change is, and why it's worth doing."
},
"workflowPageId": {
"type": "string",
"description": "Workflow page to anchor to, when one fits."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"label",
"description"
],
"properties": {
"label": {
"type": "string",
"description": "≤200 chars, the opportunity in one line."
},
"reasoning": {
"type": "string",
"description": "One or two sentences on why you're proposing this."
},
"riskScore": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"valueScore": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"description": {
"type": "string",
"description": "What it is and why it's worth trying, grounded in the map."
},
"workflowPageId": {
"type": "string",
"description": "Workflow page to anchor to, when one fits."
},
"feasibilityScore": {
"type": "integer",
"maximum": 5,
"minimum": 1
}
}
}| expectation* | string | One sentence — what we expect this to change. |
| opportunityId* | string | The change's key (e.g. ACME-12) or id, from compass_opportunities_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"opportunityId",
"expectation"
],
"properties": {
"target": {
"type": "number",
"description": "Target value, in the metric's unit (hours for time)."
},
"deadline": {
"type": "string",
"description": "ISO date the expectation is due by."
},
"metricId": {
"type": "string",
"description": "Ledger metric to bind (requires target). From ledger_metrics_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"comparator": {
"enum": [
">=",
"<=",
">",
"<",
"="
],
"type": "string"
},
"fromRollup": {
"type": "object",
"required": [
"field"
],
"properties": {
"bound": {
"enum": [
"low",
"high",
"mid"
],
"type": "string",
"default": "mid"
},
"field": {
"enum": [
"working",
"waiting",
"labor",
"hardCost"
],
"type": "string"
},
"scope": {
"enum": [
"perRun",
"perMonth"
],
"type": "string",
"default": "perRun"
},
"nodeId": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$"
},
"variantId": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
},
"description": "Instead of metricId: measure it off the change's workflow roll-up — a step's (nodeId) or the whole workflow's hands-on time, waiting, labor, or hard cost, per run or per month. Creates a daily-fed metric with the last 30 days rebuilt from the map's history, so the before is on record. Needs a target; comparator defaults to <=."
},
"expectation": {
"type": "string",
"description": "One sentence — what we expect this to change."
},
"opportunityId": {
"type": "string",
"description": "The change's key (e.g. ACME-12) or id, from compass_opportunities_list."
}
}
}| approvalId |
| string |
| Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call. |
| experiment | boolean | Measure it against the Ledger (expectation when it starts, verdict when it's done). |
| valueScore | integer |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | New description (≤5,000 chars). |
| externalUrl | any | Where the doing happens off-platform (URL); null clears. |
| ownerPageId | any | PERSON page id who owns the work; null clears. |
| opportunityId* | string | The change's key (e.g. ACME-12) or id, from compass_opportunities_list. |
| workflowPageId | any | Workflow page to anchor to; null un-anchors. |
| feasibilityScore | integer |
| qualitativeNotes | string | Free-form notes (≤20,000 chars) — replaces the current notes. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"opportunityId"
],
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "New tag set — replaces existing tags."
},
"label": {
"type": "string",
"description": "New one-line label (2–200 chars)."
},
"assignee": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The workspace member doing the work, by email or user id; null unassigns. They're notified."
},
"doneWhen": {
"type": "string",
"description": "What's true when it's done, that someone else could check (≤1,000 chars)."
},
"priority": {
"anyOf": [
{
"enum": [
"URGENT",
"HIGH",
"MEDIUM",
"LOW"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "How soon it matters; null clears it, and the map's suggestion shows again."
},
"riskScore": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"experiment": {
"type": "boolean",
"description": "Measure it against the Ledger (expectation when it starts, verdict when it's done)."
},
"valueScore": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"description": "New description (≤5,000 chars)."
},
"externalUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Where the doing happens off-platform (URL); null clears."
},
"ownerPageId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "PERSON page id who owns the work; null clears."
},
"opportunityId": {
"type": "string",
"description": "The change's key (e.g. ACME-12) or id, from compass_opportunities_list."
},
"workflowPageId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Workflow page to anchor to; null un-anchors."
},
"feasibilityScore": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"qualitativeNotes": {
"type": "string",
"description": "Free-form notes (≤20,000 chars) — replaces the current notes."
}
}
}| Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"type",
"title"
],
"properties": {
"body": {
"type": "string",
"description": "Markdown body shaped to the type (steps for WORKFLOW, role/contact sections for PERSON, etc.)."
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Optional tags."
},
"type": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "Page type for this subject. PERSON = a specific individual; ROLE = a job, separate from whoever holds it (people hold roles); VALUE = something the business won't sacrifice; PRIORITY = an outcome it's pushing toward; AUDIENCE = who the work is for; OFFERING = what the business delivers."
},
"title": {
"type": "string",
"description": "≤80 chars, sentence case, no filler verbs."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
}
}
}| string |
| Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | New one-line gallery summary (≤2,000 chars). |
| headerFields | object | Partial header fields for the page's type (PERSON: role, email, …; WORKFLOW: owner, status, …) — merged over the current values; the server validates the merged result against the type. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"body": {
"type": "string",
"description": "New Markdown body — replaces the whole body."
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "New tag set — replaces existing tags."
},
"title": {
"type": "string",
"description": "New title (≤200 chars)."
},
"pageId": {
"type": "string",
"description": "Id of the page to edit."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response, after the user has approved. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"description": "New one-line gallery summary (≤2,000 chars)."
},
"headerFields": {
"type": "object",
"description": "Partial header fields for the page's type (PERSON: role, email, …; WORKFLOW: owner, status, …) — merged over the current values; the server validates the merged result against the type.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
}
}| workspace |
| string |
| Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| sourceKind | string | Who says so: 'interview', 'email_thread', 'prism_report', 'page', or 'user' (the person you're talking with). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId",
"claims"
],
"properties": {
"claims": {
"type": "array",
"items": {
"type": "object",
"required": [
"nodeId",
"subjectPageId",
"relation"
],
"properties": {
"note": {
"type": "string",
"maxLength": 500,
"description": "Their words, briefly, when they qualify it."
},
"limits": {
"type": "boolean",
"description": "For impacts: this step holds the priority back most right now."
},
"nodeId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The step's node id; null = the workflow as a whole."
},
"validTo": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
],
"description": "When this stopped, if it has."
},
"relation": {
"anyOf": [
{
"enum": [
"owns",
"does",
"approves",
"consulted",
"does_not_do"
],
"type": "string"
},
{
"enum": [
"uses",
"impacts",
"holds_to"
],
"type": "string"
}
]
},
"validFrom": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
],
"description": "When this started, if they said."
},
"variantId": {
"type": "string",
"description": "Only for this variant (an id from compass_workflow_steps), e.g. who does it on rush jobs."
},
"subjectPageId": {
"type": "string",
"description": "The ROLE, PERSON or AUDIENCE page id; for uses, the SYSTEM or DOCUMENT page id; for impacts, the PRIORITY page id; for holds_to, the VALUE page id."
}
}
},
"maxItems": 50,
"minItems": 1
},
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"sourceId": {
"type": "string",
"description": "The interview, email thread, Prism report or page id, for those kinds."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"sourceKind": {
"enum": [
"interview",
"page",
"user",
"email_thread",
"prism_report"
],
"type": "string",
"description": "Who says so: 'interview', 'email_thread', 'prism_report', 'page', or 'user' (the person you're talking with)."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId",
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"nodeId"
],
"properties": {
"gate": {
"type": "object",
"required": [
"gate"
],
"properties": {
"gate": {
"enum": [
"approval",
"handoff",
"rekey",
"rework"
],
"type": "string"
},
"returnRate": {
"type": "number",
"maximum": 1,
"minimum": 0
}
}
},
"note": {
"type": "string",
"maxLength": 500,
"description": "Their words, briefly."
},
"nature": {
"enum": [
"rote",
"judgment",
"relationship",
"wait",
"gate"
],
"type": "string",
"description": "What kind of work the step is: rote (a machine could do it), judgment (needs a person; AI can draft or check), relationship (people talking to people), wait (work sitting with someone else), gate (an approval or check)."
},
"nodeId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The step's node id; null = the workflow as a whole."
},
"measure": {
"oneOf": [
{
"type": "object",
"required": [
"metric",
"low",
"high"
],
"properties": {
"low": {
"type": "number",
"maximum": 1000000,
"minimum": 0
},
"high": {
"type": "number",
"maximum": 1000000,
"minimum": 0
},
"metric": {
"type": "string",
"const": "working"
}
}
},
{
"type": "object",
"required": [
"metric",
"low",
"high"
],
"properties": {
"low": {
"type": "number",
"maximum": 1000000,
"minimum": 0
},
"high": {
"type": "number",
"maximum": 1000000,
"minimum": 0
},
"metric": {
"type": "string",
"const": "waiting"
}
}
},
{
"type": "object",
"required": [
"metric",
"low",
"high",
"per"
],
"properties": {
"low": {
"type": "number",
"maximum": 1000000,
"exclusiveMinimum": 0
},
"per": {
"enum": [
"day",
"week",
"month",
"year"
],
"type": "string"
},
"high": {
"type": "number",
"maximum": 1000000,
"exclusiveMinimum": 0
},
"metric": {
"type": "string",
"const": "frequency"
}
}
},
{
"type": "object",
"required": [
"metric",
"amount",
"currency",
"per"
],
"properties": {
"per": {
"enum": [
"run",
"month"
],
"type": "string"
},
"amount": {
"type": "number",
"maximum": 1000000000,
"minimum": 0
},
"metric": {
"type": "string",
"const": "hardCost"
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$"
}
}
}
]
},
"validTo": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
]
},
"validFrom": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
]
},
"variantId": {
"type": "string"
},
"subjectPageId": {
"type": "string"
}
}
},
"maxItems": 50,
"minItems": 1
},
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"sourceId": {
"type": "string",
"description": "The interview, email thread, Prism report or page id, for those kinds."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"sourceKind": {
"enum": [
"interview",
"page",
"user",
"email_thread",
"prism_report"
],
"type": "string"
}
}
}| string |
| Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"pageId"
],
"properties": {
"at": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
],
"description": "How things were on this date (YYYY-MM-DD). Default today."
},
"pageId": {
"type": "string",
"description": "The WORKFLOW page id."
},
"knownAt": {
"anyOf": [
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
},
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
],
"description": "Count only what had been said by this date — the picture as we knew it then."
},
"changeIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 50,
"description": "Project the workflow as these changes would leave it (ids from compass_scenario_changes). Compare with a call without them: before vs after, what stays human, overlapping changes."
},
"variantId": {
"type": "string",
"description": "A variant id from compass_workflow_steps."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entryId",
"summary"
],
"properties": {
"data": {
"type": "object",
"description": "Structured detail worth keeping with the summary.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"kind": {
"enum": [
"caliper_eval_run",
"manual",
"metric_reading",
"implementation",
"task_run",
"verbatim",
"source"
],
"type": "string",
"default": "manual",
"description": "Usually `manual`; `caliper_eval_run` with refId for a run; `implementation` when the change shipped."
},
"refId": {
"type": "string",
"maxLength": 100,
"description": "Source record id (a Caliper run id, …) when there is one."
},
"entryId": {
"type": "string",
"description": "The entry the evidence is about."
},
"summary": {
"type": "string",
"maxLength": 2000,
"minLength": 1,
"description": "What happened, in one or two sentences."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}| rationale | string | The entry's BODY: the detail under the title — why, context, lists, steps. Markdown is fine here and renders as formatted text. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| prediction | object | Decisions ONLY. What we expect: a list of `claims` plus one shared `deadline`, or `freeform` for room decisions nothing can settle. A claim either REACHES a value (comparator + target, e.g. CTA clicks >= 400) or HOLDS one (`hold`, e.g. newsletter reads no more than 5% below the 28 days before this). Name every number the change is expected to move AND every number it shouldn't cost — a decision that claims only what it hopes will rise gets to pick its own evidence. Set `watch: true` on a number worth following that the decision isn't committing to. When the change aims at part of an event metric ("new users in Germany"), narrow the claim with `slice` ({ country: ["DE"] }) using label values from ledger_metrics_get — a claim on an event metric settles on the total counted since landing (reach) or events per day (hold). |
| compassPageIds | array | Where — Compass page ids this decision touches. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"summary"
],
"properties": {
"kind": {
"enum": [
"decision",
"lesson",
"observation",
"belief"
],
"type": "string",
"default": "decision",
"description": "decision = a change with a pre-registered expectation; lesson = a belief arriving already settled; observation = a fact that is already true (not a plan, idea, or pitch)."
},
"lesson": {
"type": "string",
"maxLength": 4000,
"description": "What we learned — required for kind=lesson, optional for kind=observation, forbidden on decisions (their lesson is written at settlement)."
},
"summary": {
"type": "string",
"maxLength": 280,
"minLength": 1,
"description": "The entry's TITLE: one short plain sentence naming what we did (decision) or the fact itself (lesson, observation). Plain text, no markdown, at most 280 characters — e.g. \"Newsletter moves to a biweekly cadence\". Everything longer goes in rationale."
},
"rationale": {
"type": "string",
"maxLength": 4000,
"description": "The entry's BODY: the detail under the title — why, context, lists, steps. Markdown is fine here and renders as formatted text."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"prediction": {
"type": "object",
"properties": {
"claims": {
"type": "array",
"items": {
"type": "object",
"required": [
"source"
],
"properties": {
"hold": {
"type": "object",
"required": [
"kind"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"maximum": 365,
"minimum": 1
},
"kind": {
"type": "string",
"const": "pre_landing"
},
"maxDrop": {
"type": "number",
"default": 0,
"maximum": 1,
"minimum": 0
},
"maxRise": {
"type": "number",
"maximum": 1,
"minimum": 0
}
}
},
"unit": {
"type": "string",
"maxLength": 50
},
"slice": {
"type": "object",
"propertyNames": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$"
},
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"maxItems": 50,
"minItems": 1
}
},
"watch": {
"type": "boolean"
},
"evalId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"source": {
"enum": [
"caliper_eval",
"metric",
"manual"
],
"type": "string"
},
"target": {
"type": "number"
},
"metricId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"comparator": {
"enum": [
">=",
"<=",
">",
"<",
"="
],
"type": "string"
}
}
},
"default": [],
"maxItems": 10
},
"deadline": {
"type": "string",
"maxLength": 40
},
"freeform": {
"type": "string",
"maxLength": 2000
}
},
"description": "Decisions ONLY. What we expect: a list of `claims` plus one shared `deadline`, or `freeform` for room decisions nothing can settle. A claim either REACHES a value (comparator + target, e.g. CTA clicks >= 400) or HOLDS one (`hold`, e.g. newsletter reads no more than 5% below the 28 days before this). Name every number the change is expected to move AND every number it shouldn't cost — a decision that claims only what it hopes will rise gets to pick its own evidence. Set `watch: true` on a number worth following that the decision isn't committing to. When the change aims at part of an event metric (\"new users in Germany\"), narrow the claim with `slice` ({ country: [\"DE\"] }) using label values from ledger_metrics_get — a claim on an event metric settles on the total counted since landing (reach) or events per day (hold)."
},
"compassPageIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"description": "Where — Compass page ids this decision touches."
}
}
}| compassPageId | string | Compass page id — every decision touching that workflow / system / person. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"q": {
"type": "string",
"description": "Free-text search across an entry's summary, rationale, and lesson (case-insensitive). Use it to find the entry about a topic before acting."
},
"kind": {
"enum": [
"decision",
"lesson",
"observation",
"belief"
],
"type": "string",
"description": "Filter by species: decision (pre-registered expectations), lesson (distilled beliefs), observation (captured facts)."
},
"cursor": {
"type": "string",
"description": "Pagination cursor from a prior page."
},
"origin": {
"enum": [
"manual",
"workbench",
"caliper",
"compass",
"prism",
"room",
"assistant",
"import"
],
"type": "string",
"description": "Filter by who wrote it (manual, workbench, …)."
},
"status": {
"enum": [
"draft",
"open",
"settled",
"superseded"
],
"type": "string",
"description": "Filter by lifecycle state (open = awaiting evidence)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"compassPageId": {
"type": "string",
"description": "Compass page id — every decision touching that workflow / system / person."
}
}
}| prediction | any | Replacement expectation (claims + deadline, or freeform), or null to clear it. Correcting a misrecorded expectation is fine; rewriting one to match what happened is not. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"entryId"
],
"properties": {
"facet": {
"anyOf": [
{
"enum": [
"product",
"pricing",
"gtm",
"sales",
"people",
"ops",
"tooling",
"finance",
"positioning",
"risk"
],
"type": "string"
},
{
"type": "string",
"const": ""
}
],
"description": "Filing facet; empty string = unassigned."
},
"entryId": {
"type": "string",
"description": "The entry to edit: an open decision, or a lesson / observation / belief."
},
"summary": {
"type": "string",
"maxLength": 280,
"minLength": 1,
"description": "New title: one short plain sentence, no markdown, at most 280 characters."
},
"rationale": {
"type": "string",
"maxLength": 4000,
"description": "New body: the detail under the title; markdown is fine."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"prediction": {
"anyOf": [
{
"type": "object",
"properties": {
"claims": {
"type": "array",
"items": {
"type": "object",
"required": [
"source"
],
"properties": {
"hold": {
"type": "object",
"required": [
"kind"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"maximum": 365,
"minimum": 1
},
"kind": {
"type": "string",
"const": "pre_landing"
},
"maxDrop": {
"type": "number",
"default": 0,
"maximum": 1,
"minimum": 0
},
"maxRise": {
"type": "number",
"maximum": 1,
"minimum": 0
}
}
},
"unit": {
"type": "string",
"maxLength": 50
},
"slice": {
"type": "object",
"propertyNames": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$"
},
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"maxItems": 50,
"minItems": 1
}
},
"watch": {
"type": "boolean"
},
"evalId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"source": {
"enum": [
"caliper_eval",
"metric",
"manual"
],
"type": "string"
},
"target": {
"type": "number"
},
"metricId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"comparator": {
"enum": [
">=",
"<=",
">",
"<",
"="
],
"type": "string"
}
}
},
"default": [],
"maxItems": 10
},
"deadline": {
"type": "string",
"maxLength": 40
},
"freeform": {
"type": "string",
"maxLength": 2000
}
}
},
{
"type": "null"
}
],
"description": "Replacement expectation (claims + deadline, or freeform), or null to clear it. Correcting a misrecorded expectation is fine; rewriting one to match what happened is not."
}
}
}| How far back each run looks. Sensible per-cadence default. |
| integrationId* | string | From ledger_feed_sources_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"metric",
"integrationId",
"toolName",
"mapping",
"schedule"
],
"properties": {
"label": {
"type": "string",
"maxLength": 120,
"description": "Short name for the feed, e.g. \"Weekly signups\"."
},
"metric": {
"type": "string",
"description": "Metric id, or a snake_case slug to start tracking."
},
"mapping": {
"type": "object",
"required": [
"shape",
"valuePath"
],
"properties": {
"shape": {
"enum": [
"scalar",
"series"
],
"type": "string"
},
"atPath": {
"type": "string",
"maxLength": 200
},
"valuePath": {
"type": "string",
"maxLength": 200
},
"seriesPath": {
"type": "string",
"maxLength": 200
}
}
},
"schedule": {
"type": "object",
"required": [
"interval"
],
"properties": {
"time": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"interval": {
"enum": [
"hourly",
"daily",
"weekly"
],
"type": "string"
},
"timezone": {
"type": "string",
"maxLength": 64
},
"dayOfWeek": {
"type": "integer",
"maximum": 6,
"minimum": 0
}
}
},
"toolArgs": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"toolName": {
"type": "string",
"description": "The tool's own name on that server."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
},
"approvalId": {
"type": "string"
},
"windowHours": {
"type": "integer",
"maximum": 9600,
"minimum": 1,
"description": "How far back each run looks. Sensible per-cadence default."
},
"integrationId": {
"type": "string",
"description": "From ledger_feed_sources_list."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"integrationId",
"toolName"
],
"properties": {
"mapping": {
"type": "object",
"required": [
"shape",
"valuePath"
],
"properties": {
"shape": {
"enum": [
"scalar",
"series"
],
"type": "string"
},
"atPath": {
"type": "string",
"maxLength": 200
},
"valuePath": {
"type": "string",
"maxLength": 200
},
"seriesPath": {
"type": "string",
"maxLength": 200
}
},
"description": "How to read the number. Omit on the first look."
},
"toolArgs": {
"type": "object",
"description": "Arguments, exactly as the tool wants them. Use {{from}} / {{to}} (ISO instants) or {{date}} (YYYY-MM-DD) where a time range goes — those are substituted per run, and are what let one feed also backfill.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"toolName": {
"type": "string",
"description": "The tool's own name on that server — NOT the ext__ namespaced form you call it by."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
},
"approvalId": {
"type": "string"
},
"windowHours": {
"type": "integer",
"maximum": 9600,
"minimum": 1,
"description": "How far back the preview's window reaches. Default 24."
},
"integrationId": {
"type": "string",
"description": "From ledger_feed_sources_list."
}
}
}| integer |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Feed id, from ledger_feeds_list."
},
"label": {
"type": "string",
"maxLength": 120
},
"enabled": {
"type": "boolean",
"description": "false pauses it; the definition and history are kept."
},
"mapping": {
"type": "object",
"required": [
"shape",
"valuePath"
],
"properties": {
"shape": {
"enum": [
"scalar",
"series"
],
"type": "string"
},
"atPath": {
"type": "string",
"maxLength": 200
},
"valuePath": {
"type": "string",
"maxLength": 200
},
"seriesPath": {
"type": "string",
"maxLength": 200
}
}
},
"schedule": {
"type": "object",
"required": [
"interval"
],
"properties": {
"time": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"interval": {
"enum": [
"hourly",
"daily",
"weekly"
],
"type": "string"
},
"timezone": {
"type": "string",
"maxLength": 64
},
"dayOfWeek": {
"type": "integer",
"maximum": 6,
"minimum": 0
}
}
},
"toolArgs": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"toolName": {
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Omit to use the pinned workspace."
},
"approvalId": {
"type": "string"
},
"windowHours": {
"type": "integer",
"maximum": 9600,
"minimum": 1
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name"
],
"properties": {
"icon": {
"enum": [
"chart-line",
"dollar-sign",
"banknote",
"landmark",
"piggy-bank",
"wallet",
"coins",
"receipt",
"percent",
"badge-percent",
"calculator",
"chart-pie",
"trending-up",
"trending-down",
"users",
"user-plus",
"user-minus",
"user-check",
"contact",
"phone",
"handshake",
"target",
"trophy",
"magnet",
"megaphone",
"mail",
"search",
"globe",
"share-2",
"mouse-pointer-click",
"store",
"tag",
"calendar",
"clock",
"timer",
"hourglass",
"activity",
"server",
"bug",
"rocket",
"package",
"boxes",
"truck",
"undo-2",
"inbox",
"headphones",
"life-buoy",
"repeat",
"list-checks",
"clipboard-check",
"shield",
"shield-alert",
"lock",
"file-text",
"scale",
"briefcase",
"graduation-cap",
"smile",
"heart",
"star",
"message-circle",
"cpu",
"bot",
"wrench",
"layers",
"link",
"crosshair"
],
"type": "string",
"description": "The thing the number counts, e.g. phone for calls, landmark for profit."
},
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "e.g. \"Triage time\"."
},
"unit": {
"type": "string",
"maxLength": 50,
"description": "Display unit — \"min\", \"%\", \"$\", \"tickets/day\"."
},
"level": {
"enum": [
"outcome",
"driver",
"activity"
],
"type": "string",
"description": "outcome = what the business is judged on; driver = moves an outcome; activity = daily work."
},
"drives": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 50,
"description": "Ids of existing metrics this one moves."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"description": {
"type": "string",
"maxLength": 2000,
"description": "What the number means and where it comes from."
}
}
}| string |
| Metric id or slug (from ledger_metrics_list). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string |
| createIfMissing | boolean | Mint the metric when the slug is unknown. Default false — an unknown slug is an error, so a typo can't quietly start a second series. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"metricId"
],
"properties": {
"at": {
"type": "string",
"description": "ISO timestamp the reading is for. Defaults to now; set it when backfilling an earlier reading."
},
"key": {
"type": "string",
"maxLength": 120,
"description": "Idempotency key (e.g. \"2026-w32\") — a repeat write with the same key returns the original reading instead of doubling the series. Use for scheduled/recurring recordings. The key is per set of labels, so one key per day can cover every country."
},
"note": {
"type": "string",
"maxLength": 1000,
"description": "Where the number came from, if worth recording."
},
"value": {
"type": "number",
"description": "The observed value, in the metric's unit. Omit for event-kind metrics to record one occurrence."
},
"labels": {
"type": "object",
"description": "Event metrics only. What this count is broken down by, e.g. { country: \"DE\", plan: \"pro\" } — snake_case names, string values. Lets the metric be read and claimed by slice later. Refused on a measure.",
"propertyNames": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$"
},
"additionalProperties": {
"type": "string",
"maxLength": 100,
"minLength": 1
}
},
"metricId": {
"type": "string",
"description": "Metric id or slug (from ledger_metrics_list)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"createIfMissing": {
"type": "boolean",
"description": "Mint the metric when the slug is unknown. Default false — an unknown slug is an error, so a typo can't quietly start a second series."
}
}
}| cadence |
| string |
| How often a reading is expected. |
| metricId* | string | Metric id (from ledger_metrics_list). |
| direction | string | up = higher is better, down = lower is better, none. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| description | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"metricId"
],
"properties": {
"icon": {
"anyOf": [
{
"enum": [
"chart-line",
"dollar-sign",
"banknote",
"landmark",
"piggy-bank",
"wallet",
"coins",
"receipt",
"percent",
"badge-percent",
"calculator",
"chart-pie",
"trending-up",
"trending-down",
"users",
"user-plus",
"user-minus",
"user-check",
"contact",
"phone",
"handshake",
"target",
"trophy",
"magnet",
"megaphone",
"mail",
"search",
"globe",
"share-2",
"mouse-pointer-click",
"store",
"tag",
"calendar",
"clock",
"timer",
"hourglass",
"activity",
"server",
"bug",
"rocket",
"package",
"boxes",
"truck",
"undo-2",
"inbox",
"headphones",
"life-buoy",
"repeat",
"list-checks",
"clipboard-check",
"shield",
"shield-alert",
"lock",
"file-text",
"scale",
"briefcase",
"graduation-cap",
"smile",
"heart",
"star",
"message-circle",
"cpu",
"bot",
"wrench",
"layers",
"link",
"crosshair"
],
"type": "string"
},
{
"type": "string",
"const": ""
}
],
"description": "The mark the metric wears in every tool: the thing it counts (phone for calls, landmark for profit). \"\" goes back to the catalog's icon."
},
"kind": {
"enum": [
"measure",
"event"
],
"type": "string",
"description": "measure = a value each reading; event = a count of occurrences."
},
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"unit": {
"type": "string",
"maxLength": 50,
"description": "\"min\", \"%\", \"$\", \"tickets/day\"."
},
"level": {
"anyOf": [
{
"enum": [
"outcome",
"driver",
"activity"
],
"type": "string"
},
{
"type": "string",
"const": ""
}
],
"description": "outcome = what the business is judged on; driver = a number that moves an outcome; activity = daily work. \"\" unplaces it."
},
"drives": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 50,
"description": "Ids of the metrics this one moves. Replaces the current set; pass the full list. Loops are refused."
},
"target": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"description": "Goal value in the metric's unit; null clears."
},
"cadence": {
"enum": [
"",
"daily",
"weekly",
"monthly",
"quarterly"
],
"type": "string",
"description": "How often a reading is expected."
},
"metricId": {
"type": "string",
"description": "Metric id (from ledger_metrics_list)."
},
"direction": {
"enum": [
"up",
"down",
"none"
],
"type": "string",
"description": "up = higher is better, down = lower is better, none."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"description": {
"type": "string",
"maxLength": 2000
}
}
}| IANA zone the time is in (America/Chicago). Required with startTime; use the user's own zone. |
| startTime | string | Omit for an all-day item. 24-hour HH:MM in timeZone. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| ownerUserId | string | A workspace member's user id. |
| repeatWeeklyUntil | string | Also add a copy every 7 days through this day. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title",
"dueOn"
],
"properties": {
"url": {
"type": "string",
"description": "Where the work lives (draft, deck, published post)."
},
"note": {
"type": "string",
"maxLength": 2000
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "What kind of work it is: blog, video, social, event… Reuse the workspace's existing tags (see ledger_plan_list)."
},
"dueOn": {
"type": "string",
"description": "A calendar day, YYYY-MM-DD."
},
"title": {
"type": "string",
"maxLength": 300,
"minLength": 1
},
"endTime": {
"type": "string",
"description": "Same-day end, after startTime."
},
"entryId": {
"type": "string",
"description": "The open decision this carries out."
},
"timeZone": {
"type": "string",
"description": "IANA zone the time is in (America/Chicago). Required with startTime; use the user's own zone."
},
"startTime": {
"type": "string",
"description": "Omit for an all-day item. 24-hour HH:MM in timeZone."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"ownerUserId": {
"type": "string",
"description": "A workspace member's user id."
},
"repeatWeeklyUntil": {
"type": "string",
"description": "Also add a copy every 7 days through this day."
}
}
}| null makes it all-day again. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| ownerUserId | any |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"itemId"
],
"properties": {
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"note": {
"type": "string",
"maxLength": 2000
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Replaces the item's tags."
},
"dueOn": {
"type": "string",
"description": "A calendar day, YYYY-MM-DD."
},
"title": {
"type": "string",
"maxLength": 300,
"minLength": 1
},
"itemId": {
"type": "string"
},
"status": {
"enum": [
"planned",
"done",
"skipped"
],
"type": "string"
},
"endTime": {
"anyOf": [
{
"type": "string",
"description": "Wall-clock time, 24-hour HH:MM."
},
{
"type": "null"
}
]
},
"timeZone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Required when setting startTime."
},
"startTime": {
"anyOf": [
{
"type": "string",
"description": "Wall-clock time, 24-hour HH:MM."
},
{
"type": "null"
}
],
"description": "null makes it all-day again."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"ownerUserId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
}
}| fromKitId | string | New kits only: start from this kit's values. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| description | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"kitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Kit to edit. Omit to create a new kit."
},
"content": {
"type": "object",
"properties": {
"uses": {
"type": "object",
"properties": {
"fonts": {
"type": "object",
"required": [
"heading",
"body",
"mono"
],
"propertyNames": {
"enum": [
"heading",
"body",
"mono"
],
"type": "string"
},
"additionalProperties": {
"type": "string",
"maxLength": 60
}
},
"colors": {
"type": "object",
"required": [
"ink",
"muted",
"background",
"surface",
"accent",
"accent2"
],
"propertyNames": {
"enum": [
"ink",
"muted",
"background",
"surface",
"accent",
"accent2"
],
"type": "string"
},
"additionalProperties": {
"type": "string",
"maxLength": 60
}
},
"radius": {
"type": "number",
"maximum": 48,
"minimum": 0
},
"palette": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60
},
"maxItems": 12
}
}
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"id": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"use": {
"type": "array",
"items": {
"type": "object",
"required": [
"term"
],
"properties": {
"why": {
"type": "string",
"maxLength": 500
},
"term": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"instead": {
"type": "string",
"maxLength": 80
}
}
},
"maxItems": 100
},
"body": {
"type": "string",
"maxLength": 20000
},
"kind": {
"enum": [
"overview",
"voice",
"colors",
"typography",
"logo",
"imagery",
"motion",
"layout",
"examples",
"custom"
],
"type": "string"
},
"avoid": {
"type": "array",
"items": {
"type": "object",
"required": [
"term"
],
"properties": {
"why": {
"type": "string",
"maxLength": 500
},
"term": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"instead": {
"type": "string",
"maxLength": 80
}
}
},
"maxItems": 100
},
"faces": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name",
"family"
],
"properties": {
"id": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"name": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"note": {
"type": "string",
"maxLength": 500
},
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"fileId",
"weight"
],
"properties": {
"fileId": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "integer",
"maximum": 900,
"minimum": 100
}
}
},
"maxItems": 16
},
"family": {
"type": "string",
"maxLength": 60,
"minLength": 1
}
}
},
"maxItems": 20
},
"links": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"url"
],
"properties": {
"id": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000
},
"note": {
"type": "string",
"maxLength": 500
},
"title": {
"type": "string",
"maxLength": 120
}
}
},
"maxItems": 60
},
"rules": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"rule"
],
"properties": {
"id": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"why": {
"type": "string",
"maxLength": 1000
},
"rule": {
"type": "string",
"maxLength": 1000,
"minLength": 1
}
}
},
"maxItems": 100
},
"title": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"assets": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"fileId",
"name"
],
"properties": {
"id": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"note": {
"type": "string",
"maxLength": 500
},
"fileId": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"backdrop": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
}
}
},
"maxItems": 60
},
"layouts": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name",
"html"
],
"properties": {
"id": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"css": {
"type": "string",
"maxLength": 20000
},
"html": {
"type": "string",
"maxLength": 20000,
"minLength": 1
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"note": {
"type": "string",
"maxLength": 500
}
}
},
"maxItems": 40
},
"swatches": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name",
"value"
],
"properties": {
"id": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"name": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"note": {
"type": "string",
"maxLength": 500
},
"value": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
}
}
},
"maxItems": 60
}
}
},
"maxItems": 40
},
"removeSections": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"maxItems": 40
}
}
},
"fromKitId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "New kits only: start from this kit's values."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"description": {
"type": "string",
"maxLength": 500
}
}
}| Argument | Type | Description |
|---|---|---|
| css | string | CSS shared by every slide. |
| name | string | Name for a new deck. |
| size | string | The size of every slide, for a new deck or a whole rebuild: 16:9 = Widescreen slide 1920×1080; 16:10 = 16:10 slide 1920×1200; 4:3 = Standard slide 1024×768; 1:1 = Square 1080×1080; 4:5 = Portrait post 1080×1350; 9:16 = Story and reel 1080×1920; 1.91:1 = Landscape post 1200×628; x-post = X post 1600×900; og = Link preview 1200×630; pin = Pin 1000×1500; youtube-thumb = YouTube thumbnail 1280×720; linkedin-page = LinkedIn page cover 1128×191; linkedin-profile = LinkedIn profile banner 1584×396; x-header = X header 1500×500; youtube-banner = YouTube channel banner 2560×1440; facebook-cover = Facebook cover 851×315; 300x250 = Medium rectangle 300×250; 336x280 = Large rectangle 336×280; 728x90 = Leaderboard 728×90; 970x250 = Billboard 970×250; 300x600 = Half page 300×600; 160x600 = Wide skyscraper 160×600; 320x50 = Mobile banner 320×50; 320x100 = Large mobile banner 320×100; email-header = Email header 600×200; letter = Letter page 2550×3300; a4 = A4 page 2480×3508. Omit for a 16:9 deck or to keep a deck's size. |
| slide | integer | Replace just this slide (1-based) with the one slide given. |
| accent | string | Name of one of the brand's colors to use as var(--brand-accent) for this deck — for a deck about one product or campaign that has its own color in the brand. |
| append | boolean | Add these slides after the existing ones. |
| slides* | array | |
| boardId | string | Deck to rebuild or change. Omit to make a new deck. |
| previews | boolean | Default true: the result includes a picture of every slide made. Pass false to skip the pictures — the call returns sooner, which helps with long decks; look at slides afterwards with napkin_slide_view. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slides"
],
"properties": {
"css": {
"type": "string",
"maxLength": 40000,
"description": "CSS shared by every slide."
},
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Name for a new deck."
},
"size": {
"enum": [
"16:9",
"16:10",
"4:3",
"1:1",
"4:5",
"9:16",
"1.91:1",
"x-post",
"og",
"pin",
"youtube-thumb",
"linkedin-page",
"linkedin-profile",
"x-header",
"youtube-banner",
"facebook-cover",
"300x250",
"336x280",
"728x90",
"970x250",
"300x600",
"160x600",
"320x50",
"320x100",
"email-header",
"letter",
"a4"
],
"type": "string",
"description": "The size of every slide, for a new deck or a whole rebuild: 16:9 = Widescreen slide 1920×1080; 16:10 = 16:10 slide 1920×1200; 4:3 = Standard slide 1024×768; 1:1 = Square 1080×1080; 4:5 = Portrait post 1080×1350; 9:16 = Story and reel 1080×1920; 1.91:1 = Landscape post 1200×628; x-post = X post 1600×900; og = Link preview 1200×630; pin = Pin 1000×1500; youtube-thumb = YouTube thumbnail 1280×720; linkedin-page = LinkedIn page cover 1128×191; linkedin-profile = LinkedIn profile banner 1584×396; x-header = X header 1500×500; youtube-banner = YouTube channel banner 2560×1440; facebook-cover = Facebook cover 851×315; 300x250 = Medium rectangle 300×250; 336x280 = Large rectangle 336×280; 728x90 = Leaderboard 728×90; 970x250 = Billboard 970×250; 300x600 = Half page 300×600; 160x600 = Wide skyscraper 160×600; 320x50 = Mobile banner 320×50; 320x100 = Large mobile banner 320×100; email-header = Email header 600×200; letter = Letter page 2550×3300; a4 = A4 page 2480×3508. Omit for a 16:9 deck or to keep a deck's size."
},
"slide": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "Replace just this slide (1-based) with the one slide given."
},
"accent": {
"type": "string",
"maxLength": 60,
"minLength": 1,
"description": "Name of one of the brand's colors to use as var(--brand-accent) for this deck — for a deck about one product or campaign that has its own color in the brand."
},
"append": {
"type": "boolean",
"description": "Add these slides after the existing ones."
},
"slides": {
"type": "array",
"items": {
"type": "object",
"properties": {
"html": {
"type": "string",
"maxLength": 40000,
"minLength": 1,
"description": "The inside of one slide. Give this or `layout`."
},
"size": {
"enum": [
"16:9",
"16:10",
"4:3",
"1:1",
"4:5",
"9:16",
"1.91:1",
"x-post",
"og",
"pin",
"youtube-thumb",
"linkedin-page",
"linkedin-profile",
"x-header",
"youtube-banner",
"facebook-cover",
"300x250",
"336x280",
"728x90",
"970x250",
"300x600",
"160x600",
"320x50",
"320x100",
"email-header",
"letter",
"a4"
],
"type": "string",
"description": "This slide's own size, when slides differ — a set of ads at 1:1, 4:5 and 9:16 in one deck. Same keys as `size`."
},
"notes": {
"type": "string",
"maxLength": 20000,
"description": "Speaker notes (markdown)."
},
"sizes": {
"type": "array",
"items": {
"enum": [
"16:9",
"16:10",
"4:3",
"1:1",
"4:5",
"9:16",
"1.91:1",
"x-post",
"og",
"pin",
"youtube-thumb",
"linkedin-page",
"linkedin-profile",
"x-header",
"youtube-banner",
"facebook-cover",
"300x250",
"336x280",
"728x90",
"970x250",
"300x600",
"160x600",
"320x50",
"320x100",
"email-header",
"letter",
"a4"
],
"type": "string"
},
"maxItems": 12,
"description": "Make this slide once per size — with a layout, each size gets its own arrangement."
},
"slots": {
"type": "object",
"description": "What goes in the layout's slots. Plain text; `points` is one item per line; `image` and `mark` are `kit:<name>` or `file:<id>`.",
"propertyNames": {
"enum": [
"eyebrow",
"headline",
"subhead",
"body",
"points",
"stat",
"statLabel",
"quote",
"attribution",
"cta",
"footer",
"image",
"mark"
],
"type": "string"
},
"additionalProperties": {
"type": "string",
"maxLength": 2000
}
},
"layout": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "A layout from napkin_layouts_list (a key like `statement`, or `kit:<name>` for the brand's own). Give this or `html`."
},
"picture": {
"enum": [
"fill",
"whole"
],
"type": "string",
"description": "`whole` for a screenshot or a diagram: the picture is shown in full instead of cropped to fill its box. For a product UI, the product-shot layout is made for it."
}
}
},
"maxItems": 30,
"minItems": 1
},
"boardId": {
"type": "string",
"description": "Deck to rebuild or change. Omit to make a new deck."
},
"previews": {
"type": "boolean",
"description": "Default true: the result includes a picture of every slide made. Pass false to skip the pictures — the call returns sooner, which helps with long decks; look at slides afterwards with napkin_slide_view."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}| string |
| Approval id from a prior needs_confirmation response. Omit on the first call. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | Short gallery summary. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"diagramId"
],
"properties": {
"title": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"source": {
"type": "string",
"maxLength": 200000,
"description": "Mermaid flowchart source. Start with `flowchart TD` (top-down) or `flowchart LR` (left-right). Declare shaped nodes — `A[\"Rect\"]`, `B(\"Rounded\")`, `C{\"Decision\"}`, `D([\"Stadium\"])`, `E((\"Circle\"))`, `F{{\"Hexagon\"}}` — and link them with `A -->|label| B`, `A -.-> B` (dotted), or `A ==> B` (thick). Group steps with `subgraph Name[\"Title\"] ... end`. Color a node with a trailing `style A fill:#fee2e2` line. Only the flowchart subset is supported. Each label is a short name on one line, written plainly: no `\\n`, no backslashes before quotes. A step's label is its name everywhere in Compass."
},
"archived": {
"type": "boolean"
},
"diagramId": {
"type": "string",
"description": "Diagram id from napkin_diagrams_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"maxLength": 2000,
"description": "Short gallery summary."
}
}
}| Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | Short gallery summary. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"docId"
],
"properties": {
"body": {
"type": "string",
"maxLength": 200000,
"description": "Full replacement markdown body. Prefer `edits` — this overwrites everything. Write each paragraph as ONE long line; the editor wraps it for the reader."
},
"docId": {
"type": "string",
"description": "Doc id from napkin_docs_list."
},
"edits": {
"type": "array",
"items": {
"type": "object",
"required": [
"find",
"replace"
],
"properties": {
"find": {
"type": "string",
"maxLength": 20000,
"minLength": 1,
"description": "Exact text to replace, copied verbatim from the current body. Must appear EXACTLY ONCE — include surrounding words when a phrase repeats."
},
"replace": {
"type": "string",
"maxLength": 20000,
"description": "What to put there. Empty string deletes."
}
}
},
"maxItems": 20,
"minItems": 1,
"description": "Targeted find/replace pairs, applied in order. All must match or none are applied."
},
"title": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"append": {
"type": "string",
"maxLength": 50000,
"description": "Markdown appended to the end (own paragraph)."
},
"archived": {
"type": "boolean"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"maxLength": 2000,
"description": "Short gallery summary."
}
}
}| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId"
],
"properties": {
"slide": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based slide number (decks only) — makes coordinates slide-local."
},
"boardId": {
"type": "string",
"description": "Napkin board id."
},
"deletes": {
"type": "array",
"items": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"maxItems": 100,
"description": "Ids of existing shapes to remove (from napkin_boards_get)."
},
"updates": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Shape id from napkin_boards_get."
},
"patch": {
"type": "object",
"properties": {
"h": {
"type": "number"
},
"w": {
"type": "number"
},
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"z": {
"type": "number"
},
"to": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"shapeId": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
},
"crop": {
"anyOf": [
{
"type": "object",
"required": [
"top",
"right",
"bottom",
"left"
],
"properties": {
"top": {
"type": "number",
"maximum": 0.95,
"minimum": 0
},
"left": {
"type": "number",
"maximum": 0.95,
"minimum": 0
},
"right": {
"type": "number",
"maximum": 0.95,
"minimum": 0
},
"bottom": {
"type": "number",
"maximum": 0.95,
"minimum": 0
}
}
},
{
"type": "null"
}
]
},
"from": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"shapeId": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
},
"link": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
]
},
"role": {
"enum": [
"title",
"eyebrow",
"body"
],
"type": "string"
},
"size": {
"anyOf": [
{
"type": "string",
"maxLength": 40
},
{
"type": "null"
}
]
},
"slot": {
"anyOf": [
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"enum": [
"eyebrow",
"headline",
"subhead",
"body",
"points",
"stat",
"statLabel",
"quote",
"attribution",
"cta",
"footer",
"image",
"mark"
],
"type": "string"
},
"after": {
"type": "string",
"maxLength": 20
},
"before": {
"type": "string",
"maxLength": 20
}
}
},
{
"type": "null"
}
]
},
"text": {
"type": "string",
"maxLength": 10000
},
"group": {
"anyOf": [
{
"type": "string",
"maxLength": 64,
"minLength": 1
},
{
"type": "null"
}
]
},
"notes": {
"type": "string",
"maxLength": 20000
},
"order": {
"type": "number"
},
"refId": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"spans": {
"type": "array",
"items": {
"type": "object",
"required": [
"start",
"end"
],
"properties": {
"end": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
"bold": {
"type": "boolean"
},
"font": {
"type": "string",
"maxLength": 60
},
"link": {
"type": "string",
"maxLength": 2000
},
"color": {
"type": "string",
"maxLength": 30,
"minLength": 1
},
"scale": {
"type": "number",
"maximum": 4,
"minimum": 0.2
},
"start": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
"italic": {
"type": "boolean"
},
"strike": {
"type": "boolean"
},
"underline": {
"type": "boolean"
}
}
},
"maxItems": 200
},
"style": {
"type": "object",
"properties": {
"bold": {
"type": "boolean"
},
"caps": {
"type": "boolean"
},
"dash": {
"anyOf": [
{
"enum": [
"dashed",
"dotted",
"long",
"dashdot"
],
"type": "string"
},
{
"type": "null"
}
]
},
"fill": {
"type": "string",
"maxLength": 30,
"minLength": 1
},
"font": {
"type": "string",
"maxLength": 60
},
"size": {
"type": "number",
"maximum": 200,
"minimum": 0.5
},
"align": {
"enum": [
"left",
"center",
"right"
],
"type": "string"
},
"italic": {
"type": "boolean"
},
"radius": {
"type": "number",
"maximum": 400,
"minimum": 0
},
"strike": {
"type": "boolean"
},
"stroke": {
"type": "string",
"maxLength": 30,
"minLength": 1
},
"valign": {
"enum": [
"top",
"middle",
"bottom"
],
"type": "string"
},
"autoFit": {
"type": "boolean"
},
"opacity": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"textSize": {
"type": "number",
"maximum": 80,
"minimum": 0.5
},
"tracking": {
"type": "number",
"maximum": 1,
"minimum": -0.1
},
"underline": {
"type": "boolean"
},
"lineHeight": {
"type": "number",
"maximum": 3,
"minimum": 0.8
}
},
"description": "Only the style fields to change — the rest of the shape's style is kept. stroke = text/outline color, fill = background, textSize = font size inside a shape (size is font size on a text block, stroke width elsewhere), font, bold, italic, opacity, align, valign, radius, …"
},
"theme": {
"type": "string",
"maxLength": 40
},
"layout": {
"anyOf": [
{
"type": "object",
"required": [
"key",
"slots"
],
"properties": {
"key": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"slots": {
"type": "object",
"propertyNames": {
"enum": [
"eyebrow",
"headline",
"subhead",
"body",
"points",
"stat",
"statLabel",
"quote",
"attribution",
"cta",
"footer",
"image",
"mark"
],
"type": "string"
},
"additionalProperties": {
"type": "string",
"maxLength": 2000
}
},
"accent": {
"type": "string",
"maxLength": 60
},
"picture": {
"enum": [
"fill",
"whole"
],
"type": "string"
}
}
},
{
"type": "null"
}
]
},
"locked": {
"type": "boolean"
},
"points": {
"type": "array",
"items": {
"type": "number"
},
"maxItems": 60000
},
"imageId": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"refType": {
"type": "string",
"maxLength": 30,
"minLength": 1
},
"routing": {
"enum": [
"elbow",
"straight"
],
"type": "string"
},
"skipped": {
"type": "boolean"
},
"refLabel": {
"type": "string",
"maxLength": 200
},
"rotation": {
"type": "number"
},
"linkSlide": {
"anyOf": [
{
"type": "string",
"maxLength": 64
},
{
"type": "null"
}
]
},
"pageNumber": {
"type": "boolean"
},
"placeholder": {
"type": "string",
"maxLength": 100
}
},
"description": "Fields to change on the shape (x, y, w, h, text, spans, style, …) — absolute board coordinates as napkin_boards_get reports them. `spans` replaces the shape's whole span list."
}
}
},
"maxItems": 100,
"description": "Existing shapes to change — move, resize, retext, restyle. Read napkin_boards_get first for ids and current geometry."
},
"elements": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"h": {
"type": "number",
"description": "Height (rect/ellipse/text)."
},
"w": {
"type": "number",
"description": "Width (rect/ellipse/text)."
},
"x": {
"type": "number",
"description": "Top-left x (line/arrow: start x)."
},
"y": {
"type": "number",
"description": "Top-left y (line/arrow: start y)."
},
"x2": {
"type": "number",
"description": "line/arrow: end x."
},
"y2": {
"type": "number",
"description": "line/arrow: end y."
},
"bold": {
"type": "boolean",
"description": "text only."
},
"fill": {
"type": "string",
"maxLength": 30,
"description": "rect/ellipse fill hex (default none); sticky tint."
},
"size": {
"type": "number",
"maximum": 200,
"minimum": 0.5,
"description": "Stroke width / font size. Default 3.5 (≈ pen; text ≈ 17px)."
},
"text": {
"type": "string",
"maxLength": 2000,
"description": "text/sticky content."
},
"type": {
"enum": [
"pen",
"rect",
"ellipse",
"line",
"arrow",
"text",
"sticky"
],
"type": "string",
"description": "What to draw."
},
"align": {
"enum": [
"left",
"center",
"right"
],
"type": "string",
"description": "text only."
},
"color": {
"type": "string",
"maxLength": 30,
"description": "Stroke / text hex color. Default near-black ink."
},
"points": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
},
"maxItems": 4000,
"description": "pen only: [x, y] pairs along the stroke (≥ 2)."
}
}
},
"maxItems": 100,
"description": "New elements to draw, painted in order."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}| Argument | Type | Description |
|---|---|---|
| name | string | |
| starter | string | Which worked example to start from — a whole working page, written well, that you then shape to what was asked. `blank`: a title and the client library. Start here unless one of the others is exactly the shape you want. `chat`: a conversation against one flow, streamed, keeping the history client-side so the flow sees the whole thread. `form`: labelled fields sent as a form run, with the answer underneath. `decision`: text in, a shim's answer out, with its confidence and the action it recommends. `app`: an app with several screens (Preact, htm and Lucide from the shelf): tabs along the bottom on a phone and the top on a wide screen, the screen kept in the address, a home screen and a streamed chat. For a member app or a tool with a few views. `dashboard`: cards over the granted data (Chart.js from the shelf): each Ledger metric's latest reading and a line of its history, each table's count, a bar of how it splits on its first choice column, and its latest records. `intake`: a form built from a granted table's columns that adds a record to it, with a done state and 'add another'. Works through a share link. `board`: a granted table's records in lanes by its first choice column, moved a lane at a time by someone who may edit. Needs a signed-in viewer to move cards. Take `blank` (the default) when none of the others is the shape you want, rather than deleting one you didn't need. The data starters (dashboard, intake, board) read what's granted with napkin_interfaces_grant_data, so grant the table or metric too. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"starter": {
"enum": [
"blank",
"chat",
"form",
"decision",
"app",
"dashboard",
"intake",
"board"
],
"type": "string",
"description": "Which worked example to start from — a whole working page, written well, that you then shape to what was asked. `blank`: a title and the client library. Start here unless one of the others is exactly the shape you want. `chat`: a conversation against one flow, streamed, keeping the history client-side so the flow sees the whole thread. `form`: labelled fields sent as a form run, with the answer underneath. `decision`: text in, a shim's answer out, with its confidence and the action it recommends. `app`: an app with several screens (Preact, htm and Lucide from the shelf): tabs along the bottom on a phone and the top on a wide screen, the screen kept in the address, a home screen and a streamed chat. For a member app or a tool with a few views. `dashboard`: cards over the granted data (Chart.js from the shelf): each Ledger metric's latest reading and a line of its history, each table's count, a bar of how it splits on its first choice column, and its latest records. `intake`: a form built from a granted table's columns that adds a record to it, with a done state and 'add another'. Works through a share link. `board`: a granted table's records in lanes by its first choice column, moved a lane at a time by someone who may edit. Needs a signed-in viewer to move cards. Take `blank` (the default) when none of the others is the shape you want, rather than deleting one you didn't need. The data starters (dashboard, intake, board) read what's granted with napkin_interfaces_grant_data, so grant the table or metric too."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}| Argument | Type | Description |
|---|---|---|
| path | string | One file to read, e.g. index.html. Omit for every file. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| interfaceId* | string | Interface id from napkin_interfaces_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interfaceId"
],
"properties": {
"path": {
"type": "string",
"description": "One file to read, e.g. index.html. Omit for every file."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"interfaceId": {
"type": "string",
"description": "Interface id from napkin_interfaces_list."
}
}
}| interfaceId* |
| string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interfaceId"
],
"properties": {
"size": {
"enum": [
"desktop",
"phone"
],
"type": "string",
"description": "The window to look through. Default desktop (1280 wide); phone is 390 wide."
},
"steps": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"required": [
"click"
],
"properties": {
"click": {
"type": "string",
"maxLength": 200,
"minLength": 1
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "object",
"required": [
"into",
"text"
],
"properties": {
"into": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"text": {
"type": "string",
"maxLength": 2000
}
}
}
}
},
{
"type": "object",
"required": [
"press"
],
"properties": {
"press": {
"type": "string",
"maxLength": 20,
"minLength": 1
}
}
},
{
"type": "object",
"required": [
"wait"
],
"properties": {
"wait": {
"type": "integer",
"maximum": 3000,
"minimum": 0
}
}
},
{
"type": "object",
"required": [
"shot"
],
"properties": {
"shot": {
"type": "string",
"maxLength": 80,
"minLength": 1
}
}
}
]
},
"maxItems": 20,
"description": "Done in order, with a picture at each `shot` (at most 6). Default: one shot of the first screen."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"interfaceId": {
"type": "string"
}
}
}| Argument | Type | Description |
|---|---|---|
| body | string | Full replacement contents for `path`. Creates the file when it doesn't exist. Prefer `edits` on a file that already has something in it. With `append: true`, added to the end of the file instead. |
| name | string | |
| path | string | Which file to write. Defaults to index.html. Use lowercase names like app.js or style.css. |
| edits | array | Targeted find/replace pairs, applied in order. All must match or none are applied. |
| append | boolean | With `body`: add it to the end of `path` (creating the file if needed) instead of replacing it. How to write a file too long for one call: first part with `body`, the rest with `append: true`, in order. |
| archived | boolean | |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| deleteFile | boolean | Remove `path` from the interface. |
| visibility | string | Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE. |
| description | string | |
| interfaceId* | string | Interface id from napkin_interfaces_list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"interfaceId"
],
"properties": {
"body": {
"type": "string",
"maxLength": 400000,
"description": "Full replacement contents for `path`. Creates the file when it doesn't exist. Prefer `edits` on a file that already has something in it. With `append: true`, added to the end of the file instead."
},
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"path": {
"type": "string",
"maxLength": 200,
"description": "Which file to write. Defaults to index.html. Use lowercase names like app.js or style.css."
},
"edits": {
"type": "array",
"items": {
"type": "object",
"required": [
"find",
"replace"
],
"properties": {
"find": {
"type": "string",
"maxLength": 20000,
"minLength": 1,
"description": "Exact text to replace, copied verbatim from the current file. Must appear EXACTLY ONCE — include surrounding lines when a fragment repeats."
},
"replace": {
"type": "string",
"maxLength": 20000,
"description": "What to put there. Empty string deletes."
}
}
},
"maxItems": 20,
"minItems": 1,
"description": "Targeted find/replace pairs, applied in order. All must match or none are applied."
},
"append": {
"type": "boolean",
"description": "With `body`: add it to the end of `path` (creating the file if needed) instead of replacing it. How to write a file too long for one call: first part with `body`, the rest with `append: true`, in order."
},
"archived": {
"type": "boolean"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"deleteFile": {
"type": "boolean",
"description": "Remove `path` from the interface."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"type": "string",
"maxLength": 2000
},
"interfaceId": {
"type": "string",
"description": "Interface id from napkin_interfaces_list."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"boardId",
"slide"
],
"properties": {
"notes": {
"type": "string",
"maxLength": 20000,
"description": "Speaker notes (markdown); replaces the current notes."
},
"slide": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based slide number in presentation order."
},
"moveTo": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "New 1-based position for this slide."
},
"boardId": {
"type": "string",
"description": "Napkin board id (a deck)."
},
"skipped": {
"type": "boolean",
"description": "true hides the slide from present mode and exports."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"pageNumber": {
"type": "boolean",
"description": "Show the slide number on this slide."
}
}
}| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| formFields | array |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"table",
"name",
"kind"
],
"properties": {
"kind": {
"enum": [
"grid",
"board",
"form"
],
"type": "string"
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"sort": {
"type": "array",
"items": {
"type": "object",
"required": [
"field"
],
"properties": {
"dir": {
"enum": [
"asc",
"desc"
],
"type": "string"
},
"field": {
"type": "string"
}
}
},
"maxItems": 5
},
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"where": {
"type": "array",
"items": {
"type": "object",
"required": [
"field"
],
"properties": {
"op": {
"type": "string",
"description": "is (default), is_not, contains, not_contains, gt, gte, lt, lte, empty, not_empty, any_of, none_of, checked, unchecked"
},
"field": {
"type": "string"
},
"value": {}
}
},
"maxItems": 20
},
"groupBy": {
"type": "string",
"description": "Board: the select or person column whose values are the lanes."
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"formIntro": {
"type": "string",
"maxLength": 4000
},
"formTitle": {
"type": "string",
"maxLength": 200
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"formFields": {
"type": "array",
"items": {
"type": "object",
"required": [
"field"
],
"properties": {
"help": {
"type": "string",
"maxLength": 1000
},
"field": {
"type": "string"
},
"required": {
"type": "boolean"
}
}
},
"maxItems": 60
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sheetId",
"table"
],
"properties": {
"sort": {
"type": "array",
"items": {
"type": "object",
"required": [
"field"
],
"properties": {
"dir": {
"enum": [
"asc",
"desc"
],
"type": "string"
},
"field": {
"type": "string"
}
}
},
"maxItems": 5
},
"limit": {
"type": "integer",
"maximum": 500,
"minimum": 1
},
"match": {
"enum": [
"all",
"any"
],
"type": "string"
},
"table": {
"type": "string",
"description": "The table tab's name or id."
},
"where": {
"type": "array",
"items": {
"type": "object",
"required": [
"field"
],
"properties": {
"op": {
"type": "string",
"description": "is (default), is_not, contains, not_contains, gt, gte, lt, lte, empty, not_empty, any_of, none_of, checked, unchecked"
},
"field": {
"type": "string"
},
"value": {}
}
},
"maxItems": 20
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
"search": {
"type": "string",
"maxLength": 200
},
"sheetId": {
"type": "string",
"description": "Sheet id from napkin_sheets_list."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
}
}
}| integer |
| Interview runs: how many people (default 10). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId",
"panelId"
],
"properties": {
"kind": {
"enum": [
"survey",
"interview"
],
"type": "string",
"description": "survey (default) or interview."
},
"panelId": {
"type": "string"
},
"samples": {
"type": "integer",
"maximum": 3,
"minimum": 1,
"description": "Answers per person for a survey run (default 3)."
},
"studyId": {
"type": "string"
},
"budgetUsd": {
"type": "number",
"description": "Pause the run once it has spent this many dollars.",
"exclusiveMinimum": 0
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"temperature": {
"type": "number",
"maximum": 1.5,
"minimum": 0
},
"interviewFocus": {
"type": "string",
"description": "Interview runs: what the interviewer should explore."
},
"interviewPeople": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "Interview runs: how many people (default 10)."
}
}
}| string |
| Interview runs: what the interviewer should explore. |
| interviewPeople | integer | Interview runs: how many people (default 10). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId",
"panelId"
],
"properties": {
"kind": {
"enum": [
"survey",
"interview"
],
"type": "string",
"description": "survey (default) or interview."
},
"panelId": {
"type": "string"
},
"samples": {
"type": "integer",
"maximum": 3,
"minimum": 1,
"description": "Answers per person for a survey run (default 3)."
},
"studyId": {
"type": "string"
},
"budgetUsd": {
"type": "number",
"description": "Pause the run once it has spent this many dollars.",
"exclusiveMinimum": 0
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"temperature": {
"type": "number",
"maximum": 1.5,
"minimum": 0
},
"interviewFocus": {
"type": "string",
"description": "Interview runs: what the interviewer should explore."
},
"interviewPeople": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "Interview runs: how many people (default 10)."
}
}
}| approvalId |
| string |
| Approval id from a prior needs_confirmation envelope. |
| scheduleTime | string | HH:MM local to scheduleTimezone (default 09:00). |
| scheduleTimezone | string | IANA zone (default UTC). |
| adaptiveFollowUps | boolean | AI follow-up questions on curious answers (default true). |
| autoAnalyzeTarget | any | Analyze each wave automatically at this many completes. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name",
"questions",
"interval"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"scorer": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"questionIndex"
],
"properties": {
"kind": {
"enum": [
"scale_mean",
"nps",
"top_2_box",
"choice_share"
],
"type": "string"
},
"minN": {
"type": "integer",
"default": 5,
"maximum": 1000,
"minimum": 1
},
"option": {
"type": "string",
"maxLength": 200
},
"questionIndex": {
"type": "integer",
"maximum": 39,
"minimum": 0
}
}
},
{
"type": "null"
}
],
"description": "How a wave becomes one number: { kind, questionIndex, option?, minN? }."
},
"interval": {
"enum": [
"daily",
"weekly"
],
"type": "string",
"description": "daily or weekly."
},
"metricId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Ledger metric the waves post readings to (from ledger_metrics_list)."
},
"dayOfWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 6,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Weekly only: 0 = Sunday … 6 = Saturday."
},
"questions": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"qid": {
"type": "string",
"maxLength": 40
},
"type": {
"enum": [
"word",
"text",
"choice",
"multi",
"rank",
"maxdiff",
"scale",
"number",
"completion"
],
"type": "string"
},
"probe": {
"type": "string",
"maxLength": 500
},
"loopId": {
"type": "string",
"maxLength": 40
},
"prefix": {
"type": "string"
},
"prompt": {
"type": "string"
},
"rotate": {
"type": "boolean"
},
"showIf": {
"type": "object",
"required": [
"qid"
],
"properties": {
"gte": {
"type": "number"
},
"lte": {
"type": "number"
},
"qid": {
"type": "string",
"maxLength": 40
},
"anyOf": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 20
}
}
},
"vwRole": {
"enum": [
"too_cheap",
"cheap",
"expensive",
"too_expensive"
],
"type": "string"
},
"options": {
"type": "array",
"items": {
"type": "string"
}
},
"kanoRole": {
"enum": [
"functional",
"dysfunctional"
],
"type": "string"
},
"loopItem": {
"type": "string",
"maxLength": 200
},
"lowLabel": {
"type": "string"
},
"scaleMax": {
"type": "integer",
"maximum": 20,
"minimum": 2
},
"scaleMin": {
"type": "integer",
"maximum": 10,
"minimum": 0
},
"susIndex": {
"type": "integer",
"maximum": 10,
"minimum": 1
},
"highLabel": {
"type": "string"
},
"maxdiffId": {
"type": "string",
"maxLength": 40
},
"numberMax": {
"type": "number"
},
"numberMin": {
"type": "number"
},
"allowOther": {
"type": "boolean"
},
"anchorLast": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"loopRotate": {
"type": "boolean"
},
"otherLabel": {
"type": "string",
"maxLength": 60
},
"contextText": {
"type": "string",
"maxLength": 2000
},
"placeholder": {
"type": "string"
},
"exclusiveLast": {
"type": "boolean"
},
"maxSelections": {
"type": "integer",
"maximum": 20,
"minimum": 1
},
"contextImageUrl": {
"type": "string",
"maxLength": 1000
},
"loopPresentation": {
"enum": [
"paged",
"grid"
],
"type": "string"
},
"screenOutOptions": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 10
}
},
"additionalProperties": {}
},
"maxItems": 40,
"minItems": 1,
"description": "The instrument: an ordered list of questions ({ type, prompt, options?, … } — read an existing study with prism_studies_get for the shape)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"scheduleTime": {
"type": "string",
"description": "HH:MM local to scheduleTimezone (default 09:00)."
},
"scheduleTimezone": {
"type": "string",
"description": "IANA zone (default UTC)."
},
"adaptiveFollowUps": {
"type": "boolean",
"description": "AI follow-up questions on curious answers (default true)."
},
"autoAnalyzeTarget": {
"anyOf": [
{
"type": "integer",
"maximum": 1000,
"minimum": 2
},
{
"type": "null"
}
],
"description": "Analyze each wave automatically at this many completes."
}
}
}| Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| scheduleTime | string | HH:MM. |
| scheduleTimezone | string | IANA zone. |
| adaptiveFollowUps | boolean |
| autoAnalyzeTarget | any |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"seriesId"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"scorer": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"questionIndex"
],
"properties": {
"kind": {
"enum": [
"scale_mean",
"nps",
"top_2_box",
"choice_share"
],
"type": "string"
},
"minN": {
"type": "integer",
"default": 5,
"maximum": 1000,
"minimum": 1
},
"option": {
"type": "string",
"maxLength": 200
},
"questionIndex": {
"type": "integer",
"maximum": 39,
"minimum": 0
}
}
},
{
"type": "null"
}
]
},
"enabled": {
"type": "boolean",
"description": "false pauses, true resumes."
},
"interval": {
"enum": [
"daily",
"weekly"
],
"type": "string"
},
"metricId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"seriesId": {
"type": "string",
"description": "Series id (from prism_series_list)."
},
"dayOfWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 6,
"minimum": 0
},
{
"type": "null"
}
]
},
"questions": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"qid": {
"type": "string",
"maxLength": 40
},
"type": {
"enum": [
"word",
"text",
"choice",
"multi",
"rank",
"maxdiff",
"scale",
"number",
"completion"
],
"type": "string"
},
"probe": {
"type": "string",
"maxLength": 500
},
"loopId": {
"type": "string",
"maxLength": 40
},
"prefix": {
"type": "string"
},
"prompt": {
"type": "string"
},
"rotate": {
"type": "boolean"
},
"showIf": {
"type": "object",
"required": [
"qid"
],
"properties": {
"gte": {
"type": "number"
},
"lte": {
"type": "number"
},
"qid": {
"type": "string",
"maxLength": 40
},
"anyOf": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 20
}
}
},
"vwRole": {
"enum": [
"too_cheap",
"cheap",
"expensive",
"too_expensive"
],
"type": "string"
},
"options": {
"type": "array",
"items": {
"type": "string"
}
},
"kanoRole": {
"enum": [
"functional",
"dysfunctional"
],
"type": "string"
},
"loopItem": {
"type": "string",
"maxLength": 200
},
"lowLabel": {
"type": "string"
},
"scaleMax": {
"type": "integer",
"maximum": 20,
"minimum": 2
},
"scaleMin": {
"type": "integer",
"maximum": 10,
"minimum": 0
},
"susIndex": {
"type": "integer",
"maximum": 10,
"minimum": 1
},
"highLabel": {
"type": "string"
},
"maxdiffId": {
"type": "string",
"maxLength": 40
},
"numberMax": {
"type": "number"
},
"numberMin": {
"type": "number"
},
"allowOther": {
"type": "boolean"
},
"anchorLast": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"loopRotate": {
"type": "boolean"
},
"otherLabel": {
"type": "string",
"maxLength": 60
},
"contextText": {
"type": "string",
"maxLength": 2000
},
"placeholder": {
"type": "string"
},
"exclusiveLast": {
"type": "boolean"
},
"maxSelections": {
"type": "integer",
"maximum": 20,
"minimum": 1
},
"contextImageUrl": {
"type": "string",
"maxLength": 1000
},
"loopPresentation": {
"enum": [
"paged",
"grid"
],
"type": "string"
},
"screenOutOptions": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 10
}
},
"additionalProperties": {}
},
"maxItems": 40,
"minItems": 1,
"description": "Replacement instrument — only before the first wave fields."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"scheduleTime": {
"type": "string",
"description": "HH:MM."
},
"scheduleTimezone": {
"type": "string",
"description": "IANA zone."
},
"adaptiveFollowUps": {
"type": "boolean"
},
"autoAnalyzeTarget": {
"anyOf": [
{
"type": "integer",
"maximum": 1000,
"minimum": 2
},
{
"type": "null"
}
]
}
}
}| endChatFocus | any | What the closing chat should be about; null clears. |
| endChatEnabled | boolean |
| adaptiveFollowUps | boolean |
| autoAnalyzeTarget | any |
| completionRedirectUrl | any | http(s) URL respondents land on after submitting ({pid} = participant id); null clears. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"studyId"
],
"properties": {
"title": {
"type": "string",
"maxLength": 300,
"minLength": 1
},
"closed": {
"type": "boolean"
},
"publish": {
"type": "boolean",
"const": true
},
"studyId": {
"type": "string"
},
"questions": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"qid": {
"type": "string",
"maxLength": 40
},
"type": {
"enum": [
"word",
"text",
"choice",
"multi",
"rank",
"maxdiff",
"scale",
"number",
"completion"
],
"type": "string"
},
"probe": {
"type": "string",
"maxLength": 500
},
"loopId": {
"type": "string",
"maxLength": 40
},
"prefix": {
"type": "string"
},
"prompt": {
"type": "string"
},
"rotate": {
"type": "boolean"
},
"showIf": {
"type": "object",
"required": [
"qid"
],
"properties": {
"gte": {
"type": "number"
},
"lte": {
"type": "number"
},
"qid": {
"type": "string",
"maxLength": 40
},
"anyOf": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 20
}
}
},
"vwRole": {
"enum": [
"too_cheap",
"cheap",
"expensive",
"too_expensive"
],
"type": "string"
},
"options": {
"type": "array",
"items": {
"type": "string"
}
},
"kanoRole": {
"enum": [
"functional",
"dysfunctional"
],
"type": "string"
},
"loopItem": {
"type": "string",
"maxLength": 200
},
"lowLabel": {
"type": "string"
},
"scaleMax": {
"type": "integer",
"maximum": 20,
"minimum": 2
},
"scaleMin": {
"type": "integer",
"maximum": 10,
"minimum": 0
},
"susIndex": {
"type": "integer",
"maximum": 10,
"minimum": 1
},
"highLabel": {
"type": "string"
},
"maxdiffId": {
"type": "string",
"maxLength": 40
},
"numberMax": {
"type": "number"
},
"numberMin": {
"type": "number"
},
"allowOther": {
"type": "boolean"
},
"anchorLast": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"loopRotate": {
"type": "boolean"
},
"otherLabel": {
"type": "string",
"maxLength": 60
},
"contextText": {
"type": "string",
"maxLength": 2000
},
"placeholder": {
"type": "string"
},
"exclusiveLast": {
"type": "boolean"
},
"maxSelections": {
"type": "integer",
"maximum": 20,
"minimum": 1
},
"contextImageUrl": {
"type": "string",
"maxLength": 1000
},
"loopPresentation": {
"enum": [
"paged",
"grid"
],
"type": "string"
},
"screenOutOptions": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200
},
"maxItems": 10
}
},
"additionalProperties": {}
},
"maxItems": 40,
"description": "Replacement instrument (drafts only): ordered list of { type, prompt, options?, … } — read prism_studies_get for the shape."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string"
},
"endChatFocus": {
"anyOf": [
{
"type": "string",
"maxLength": 200
},
{
"type": "null"
}
],
"description": "What the closing chat should be about; null clears."
},
"endChatEnabled": {
"type": "boolean"
},
"adaptiveFollowUps": {
"type": "boolean"
},
"autoAnalyzeTarget": {
"anyOf": [
{
"type": "integer",
"maximum": 1000,
"minimum": 2
},
{
"type": "null"
}
]
},
"completionRedirectUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "http(s) URL respondents land on after submitting ({pid} = participant id); null clears."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The room's name."
},
"people": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 50,
"description": "Names or emails of workspace members to add."
},
"opening": {
"type": "string",
"maxLength": 4000,
"minLength": 1,
"description": "Your first message in the room, in markdown."
},
"private": {
"type": "boolean",
"description": "Only its people can see it (default false: the whole workspace can)."
},
"folderId": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "A folder it works from (id from workspace_folders_browse)."
},
"workspace": {
"type": "string",
"description": "Workspace slug, for tokens without a default."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| includeZv1 | boolean | Whether the assistant takes part too (default true). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"roomId",
"goal"
],
"properties": {
"goal": {
"type": "string",
"maxLength": 2000,
"minLength": 1,
"description": "What they should work on, as a clear task."
},
"mode": {
"enum": [
"moderated",
"in_order"
],
"type": "string",
"description": "'moderated' (the assistant picks who speaks) or 'in_order'. Default moderated."
},
"output": {
"type": "string",
"maxLength": 1000,
"description": "What to come back with, e.g. 'a one-paragraph recommendation'."
},
"roomId": {
"type": "string",
"description": "Room id (from rooms_list)."
},
"flowIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 7,
"description": "Flows in the room to take part."
},
"maxTurns": {
"type": "integer",
"maximum": 30,
"minimum": 1,
"description": "Most turns before they write up (default 8)."
},
"sidebarId": {
"type": "string",
"description": "Work in this open sidebar instead of opening a new one."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"includeZv1": {
"type": "boolean",
"description": "Whether the assistant takes part too (default true)."
}
}
}| interval | string | Plain cadence. Omit when passing recurrence. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| recurrence | any | When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {"freq":"hourly"|"daily"|"weekly"|"monthly"|"yearly","every":N,"times":["HH:MM"],"weekdays":[0=Sun…6=Sat],"monthDays":[1…31,-1=last],"nthWeekdays":[{"nth":1…5|-1,"weekdays":[…]}],"months":[1…12],"minutes":[…],"hours":{"from","to"},"timezone":"<IANA>","starts","ends","skip":["YYYY-MM-DD"]}. Examples: weekdays at 8 → {"freq":"weekly","weekdays":[1,2,3,4,5],"times":["08:00"],"timezone":"America/Chicago"}; the last business day of the month → {"freq":"monthly","nthWeekdays":[{"nth":-1,"weekdays":[1,2,3,4,5]}],"timezone":"…"}; every other Friday → {"freq":"weekly","every":2,"weekdays":[5],"starts":"<a Friday>","timezone":"…"}. null clears it. |
| instruction* | string | What to do on each run, as a directive. |
| scheduleTime | string | Wall-clock "HH:MM" anchor (default 09:00). |
| scheduleTimezone | string | IANA timezone for the anchor (default UTC). |
| scheduleDayOfWeek | integer | Weekly only: 0=Sunday … 6=Saturday (default Monday). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"name",
"instruction"
],
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Short display name."
},
"roomId": {
"type": "string",
"description": "With delivery \"room\": the room to post in (rooms_list gives ids)."
},
"writes": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,79}$"
},
"maxItems": 20,
"description": "Tools each run writes with on its own, without asking: the ones the job needs every time, like [\"napkin_tables_add_records\"]. The person approves this list once, with this call. Any other write waits for approval on every run, and emails, invites, shares, publishing, schedules, deletes and starting other work always wait, even when listed."
},
"actsFor": {
"enum": [
"workspace",
"personal"
],
"type": "string",
"description": "Visibility: \"workspace\" (everyone sees it) or \"personal\" (just the owner). Default workspace."
},
"delivery": {
"enum": [
"notification",
"email",
"room"
],
"type": "string",
"description": "Where each run's briefing lands (default notification). \"room\" posts it in a team room for everyone there; pass roomId. The user must be in the room if it's private, and a \"personal\" routine can post only in a private room. Use it when the user names a room (\"…and post it in #claims\") or asks from inside one for the room."
},
"interval": {
"enum": [
"daily",
"weekly"
],
"type": "string",
"description": "Plain cadence. Omit when passing recurrence."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"recurrence": {
"anyOf": [
{
"type": "object",
"required": [
"freq",
"timezone"
],
"properties": {
"ends": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"freq": {
"enum": [
"hourly",
"daily",
"weekly",
"monthly",
"yearly"
],
"type": "string"
},
"skip": {
"type": "array",
"items": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"maxItems": 100
},
"every": {
"type": "integer",
"default": 1,
"maximum": 366,
"minimum": 1
},
"hours": {
"type": "object",
"required": [
"from",
"to"
],
"properties": {
"to": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"from": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
}
}
},
"times": {
"type": "array",
"items": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"maxItems": 24,
"minItems": 1
},
"months": {
"type": "array",
"items": {
"type": "integer",
"maximum": 12,
"minimum": 1
},
"maxItems": 12,
"minItems": 1
},
"starts": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"minutes": {
"type": "array",
"items": {
"type": "integer",
"maximum": 59,
"minimum": 0
},
"maxItems": 12,
"minItems": 1
},
"timezone": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
},
"monthDays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 31,
"minimum": -1
},
"maxItems": 31,
"minItems": 1
},
"nthWeekdays": {
"type": "array",
"items": {
"type": "object",
"required": [
"nth",
"weekdays"
],
"properties": {
"nth": {
"type": "integer",
"maximum": 5,
"minimum": -1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
}
}
},
"maxItems": 5,
"minItems": 1
}
}
},
{
"type": "null"
}
],
"description": "When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {\"freq\":\"hourly\"|\"daily\"|\"weekly\"|\"monthly\"|\"yearly\",\"every\":N,\"times\":[\"HH:MM\"],\"weekdays\":[0=Sun…6=Sat],\"monthDays\":[1…31,-1=last],\"nthWeekdays\":[{\"nth\":1…5|-1,\"weekdays\":[…]}],\"months\":[1…12],\"minutes\":[…],\"hours\":{\"from\",\"to\"},\"timezone\":\"<IANA>\",\"starts\",\"ends\",\"skip\":[\"YYYY-MM-DD\"]}. Examples: weekdays at 8 → {\"freq\":\"weekly\",\"weekdays\":[1,2,3,4,5],\"times\":[\"08:00\"],\"timezone\":\"America/Chicago\"}; the last business day of the month → {\"freq\":\"monthly\",\"nthWeekdays\":[{\"nth\":-1,\"weekdays\":[1,2,3,4,5]}],\"timezone\":\"…\"}; every other Friday → {\"freq\":\"weekly\",\"every\":2,\"weekdays\":[5],\"starts\":\"<a Friday>\",\"timezone\":\"…\"}. null clears it."
},
"instruction": {
"type": "string",
"maxLength": 4000,
"minLength": 1,
"description": "What to do on each run, as a directive."
},
"scheduleTime": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
"description": "Wall-clock \"HH:MM\" anchor (default 09:00)."
},
"scheduleTimezone": {
"type": "string",
"description": "IANA timezone for the anchor (default UTC)."
},
"scheduleDayOfWeek": {
"type": "integer",
"maximum": 6,
"minimum": 0,
"description": "Weekly only: 0=Sunday … 6=Saturday (default Monday)."
}
}
}| Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
| recurrence | any | When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {"freq":"hourly"|"daily"|"weekly"|"monthly"|"yearly","every":N,"times":["HH:MM"],"weekdays":[0=Sun…6=Sat],"monthDays":[1…31,-1=last],"nthWeekdays":[{"nth":1…5|-1,"weekdays":[…]}],"months":[1…12],"minutes":[…],"hours":{"from","to"},"timezone":"<IANA>","starts","ends","skip":["YYYY-MM-DD"]}. Examples: weekdays at 8 → {"freq":"weekly","weekdays":[1,2,3,4,5],"times":["08:00"],"timezone":"America/Chicago"}; the last business day of the month → {"freq":"monthly","nthWeekdays":[{"nth":-1,"weekdays":[1,2,3,4,5]}],"timezone":"…"}; every other Friday → {"freq":"weekly","every":2,"weekdays":[5],"starts":"<a Friday>","timezone":"…"}. null clears it. |
| instruction | string |
| scheduleTime | string | Wall-clock "HH:MM" anchor (default 09:00). |
| scheduleTimezone | string |
| scheduleDayOfWeek | any |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Routine id (from routines_list)."
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"roomId": {
"type": "string",
"description": "With delivery \"room\": the room to post in."
},
"writes": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,79}$"
},
"maxItems": 20,
"description": "Tools each run writes with on its own, without asking: the ones the job needs every time, like [\"napkin_tables_add_records\"]. The person approves this list once, with this call. Any other write waits for approval on every run, and emails, invites, shares, publishing, schedules, deletes and starting other work always wait, even when listed."
},
"enabled": {
"type": "boolean"
},
"delivery": {
"enum": [
"notification",
"email",
"room"
],
"type": "string"
},
"interval": {
"enum": [
"daily",
"weekly"
],
"type": "string"
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
},
"recurrence": {
"anyOf": [
{
"type": "object",
"required": [
"freq",
"timezone"
],
"properties": {
"ends": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"freq": {
"enum": [
"hourly",
"daily",
"weekly",
"monthly",
"yearly"
],
"type": "string"
},
"skip": {
"type": "array",
"items": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"maxItems": 100
},
"every": {
"type": "integer",
"default": 1,
"maximum": 366,
"minimum": 1
},
"hours": {
"type": "object",
"required": [
"from",
"to"
],
"properties": {
"to": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"from": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
}
}
},
"times": {
"type": "array",
"items": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"maxItems": 24,
"minItems": 1
},
"months": {
"type": "array",
"items": {
"type": "integer",
"maximum": 12,
"minimum": 1
},
"maxItems": 12,
"minItems": 1
},
"starts": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"minutes": {
"type": "array",
"items": {
"type": "integer",
"maximum": 59,
"minimum": 0
},
"maxItems": 12,
"minItems": 1
},
"timezone": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
},
"monthDays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 31,
"minimum": -1
},
"maxItems": 31,
"minItems": 1
},
"nthWeekdays": {
"type": "array",
"items": {
"type": "object",
"required": [
"nth",
"weekdays"
],
"properties": {
"nth": {
"type": "integer",
"maximum": 5,
"minimum": -1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
}
}
},
"maxItems": 5,
"minItems": 1
}
}
},
{
"type": "null"
}
],
"description": "When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {\"freq\":\"hourly\"|\"daily\"|\"weekly\"|\"monthly\"|\"yearly\",\"every\":N,\"times\":[\"HH:MM\"],\"weekdays\":[0=Sun…6=Sat],\"monthDays\":[1…31,-1=last],\"nthWeekdays\":[{\"nth\":1…5|-1,\"weekdays\":[…]}],\"months\":[1…12],\"minutes\":[…],\"hours\":{\"from\",\"to\"},\"timezone\":\"<IANA>\",\"starts\",\"ends\",\"skip\":[\"YYYY-MM-DD\"]}. Examples: weekdays at 8 → {\"freq\":\"weekly\",\"weekdays\":[1,2,3,4,5],\"times\":[\"08:00\"],\"timezone\":\"America/Chicago\"}; the last business day of the month → {\"freq\":\"monthly\",\"nthWeekdays\":[{\"nth\":-1,\"weekdays\":[1,2,3,4,5]}],\"timezone\":\"…\"}; every other Friday → {\"freq\":\"weekly\",\"every\":2,\"weekdays\":[5],\"starts\":\"<a Friday>\",\"timezone\":\"…\"}. null clears it."
},
"instruction": {
"type": "string",
"maxLength": 4000,
"minLength": 1
},
"scheduleTime": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
"description": "Wall-clock \"HH:MM\" anchor (default 09:00)."
},
"scheduleTimezone": {
"type": "string"
},
"scheduleDayOfWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 6,
"minimum": 0
},
{
"type": "null"
}
]
}
}
}| Only search inside this folder and the folders under it (ids from workspace_folders_browse or a folder hit). |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Words, any order, case-insensitive. Fewer words find more."
},
"kinds": {
"type": "array",
"items": {
"enum": [
"flow",
"page",
"dataset",
"eval",
"entry",
"board",
"file",
"shim",
"knowledge_base",
"task",
"rubric",
"review",
"spec",
"source",
"doc",
"sheet",
"diagram",
"interface",
"change",
"field",
"study",
"metric",
"folder"
],
"type": "string"
},
"minItems": 1,
"description": "Restrict to these kinds (file, folder, flow, page, doc, dataset, …). Omit to search everything."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 50,
"minimum": 1
},
"folderId": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "Only search inside this folder and the folders under it (ids from workspace_folders_browse or a folder hit)."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
}
}
}| Replacement text. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"find",
"replace",
"note"
],
"properties": {
"find": {
"type": "string",
"description": "EXACT current text (≥3 chars), copied verbatim — never reconstructed from memory."
},
"note": {
"type": "string",
"description": "Why this edit. Cite eval run ids when it follows a measurement (e.g. 'refund answers scored 1/5 on accuracy in run cer_abc — adds the manager-approval rule'). Lands in the audit log."
},
"flowId": {
"type": "string",
"description": "Flow to edit."
},
"replace": {
"type": "string",
"description": "Replacement text."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"version"
],
"properties": {
"note": {
"type": "string",
"maxLength": 2000,
"description": "What changed — a commit message."
},
"flowId": {
"type": "string",
"description": "Flow to publish."
},
"untried": {
"type": "boolean",
"description": "true only when the person asked to publish this draft without trying it first."
},
"version": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Version label, e.g. '1.0.0' or '2026-09-04'. Re-using a label retags it to this snapshot."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
}
}
}| variables | array | agent / interviewer: types and descriptions for the {{tokens}} in systemPrompt. Every {{token}} becomes a variable on its own (the test pane and scenarios list it, the app fills it per user at run time); pass this only to set a type other than string or say what fills it. |
| workspace | string | Workspace slug. Personal tokens with no default workspace MUST pass this. |
| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| categories | array | classifier only: 2-12 buckets. The classifier asks the systemPrompt as one pick-one question with these as the options, and returns `values.category` plus `answers.category` (probabilities and confidence). |
| description | string | 1-2 sentences: what it does, where it fits. |
| systemPrompt | string | The draft's behavior — production-quality first attempt with [STUB: ...] / [FILL IN: ...] markers where reality is missing. Required for structurer and classifier. Leave it out of an agent to get the bare model with no instructions (a 'promptless' agent). |
| opportunityId | string | Compass change (from compass_opportunities_list) this draft implements. Sets the flow ↔ change link; refused when the change already has a draft. |
| inputDescription | string | What the flow's single input carries. |
| responseSchemaJson | string | structurer only: the output JSON Schema, JSON-encoded as a string (object root, required fields, additionalProperties false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"mode",
"flowName"
],
"properties": {
"mode": {
"enum": [
"agent",
"structurer",
"classifier",
"interviewer"
],
"type": "string",
"description": "Pattern editor the draft opens in. Pick interviewer for conversations that LEARN something from a person (research calls, intake, retros) — pair it with workbench_flows_share_create so non-account humans can talk to it."
},
"model": {
"type": "string",
"description": "The model node slug the draft runs on, from workbench_node_catalog_get, that the workspace allows. For a classifier, a `decision` entry (Jev, Kev, Solar Decide); defaults to TypeSafe: Jev Latest. Otherwise an `llm` entry (e.g. an OpenAI, Anthropic, or Google model); defaults to Claude Haiku 4.5. Set it here rather than editing the flow afterwards."
},
"flowName": {
"type": "string",
"description": "Imperative + specific, ≤80 chars."
},
"stubNotes": {
"type": "string",
"description": "What's stubbed / missing / worth wiring next."
},
"variables": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "The token's name, as in {{name}}."
},
"type": {
"enum": [
"string",
"number",
"boolean",
"array",
"object"
],
"type": "string",
"description": "Default string."
},
"description": {
"type": "string",
"description": "What the app passes in, e.g. 'The member's first name, from the CRM'."
}
}
},
"description": "agent / interviewer: types and descriptions for the {{tokens}} in systemPrompt. Every {{token}} becomes a variable on its own (the test pane and scenarios list it, the app fills it per user at run time); pass this only to set a type other than string or say what fills it."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"categories": {
"type": "array",
"items": {
"type": "object",
"required": [
"value"
],
"properties": {
"value": {
"type": "string"
},
"description": {
"type": "string"
}
}
},
"description": "classifier only: 2-12 buckets. The classifier asks the systemPrompt as one pick-one question with these as the options, and returns `values.category` plus `answers.category` (probabilities and confidence)."
},
"description": {
"type": "string",
"description": "1-2 sentences: what it does, where it fits."
},
"systemPrompt": {
"type": "string",
"description": "The draft's behavior — production-quality first attempt with [STUB: ...] / [FILL IN: ...] markers where reality is missing. Required for structurer and classifier. Leave it out of an agent to get the bare model with no instructions (a 'promptless' agent)."
},
"opportunityId": {
"type": "string",
"description": "Compass change (from compass_opportunities_list) this draft implements. Sets the flow ↔ change link; refused when the change already has a draft."
},
"inputDescription": {
"type": "string",
"description": "What the flow's single input carries."
},
"responseSchemaJson": {
"type": "string",
"description": "structurer only: the output JSON Schema, JSON-encoded as a string (object root, required fields, additionalProperties false)."
}
}
}| approvalId | string | Approval id from a prior needs_confirmation response. Omit on the first call. |
| recurrence | any | When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {"freq":"hourly"|"daily"|"weekly"|"monthly"|"yearly","every":N,"times":["HH:MM"],"weekdays":[0=Sun…6=Sat],"monthDays":[1…31,-1=last],"nthWeekdays":[{"nth":1…5|-1,"weekdays":[…]}],"months":[1…12],"minutes":[…],"hours":{"from","to"},"timezone":"<IANA>","starts","ends","skip":["YYYY-MM-DD"]}. Examples: weekdays at 8 → {"freq":"weekly","weekdays":[1,2,3,4,5],"times":["08:00"],"timezone":"America/Chicago"}; the last business day of the month → {"freq":"monthly","nthWeekdays":[{"nth":-1,"weekdays":[1,2,3,4,5]}],"timezone":"…"}; every other Friday → {"freq":"weekly","every":2,"weekdays":[5],"starts":"<a Friday>","timezone":"…"}. null clears it. |
| scheduleTime | any |
| scheduleTimezone | any |
| scheduleDayOfWeek | any |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"input"
],
"properties": {
"input": {
"oneOf": [
{
"type": "object",
"required": [
"kind",
"messages"
],
"properties": {
"kind": {
"type": "string",
"const": "chat"
},
"values": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"messages": {
"type": "array",
"items": {
"type": "object",
"required": [
"role"
],
"properties": {
"name": {
"type": "string"
},
"role": {
"type": "string"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {}
},
{
"type": "null"
}
]
},
"tool_calls": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"function": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"arguments": {}
},
"additionalProperties": {}
}
},
"additionalProperties": {}
}
},
"tool_call_id": {
"type": "string"
}
},
"additionalProperties": {}
}
}
}
},
{
"type": "object",
"required": [
"kind",
"values"
],
"properties": {
"kind": {
"type": "string",
"const": "form"
},
"values": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
}
}
],
"description": "Fixed input envelope every run executes with — {\"kind\":\"chat\",\"messages\":[…]} or {\"kind\":\"form\",\"values\":{…}}, the same shape workbench_flows_run takes. Constant across runs."
},
"label": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
},
"flowId": {
"type": "string",
"description": "Flow to schedule (id from workbench_flows_list)."
},
"delivery": {
"enum": [
"history",
"notification",
"email"
],
"type": "string"
},
"interval": {
"enum": [
"hourly",
"daily",
"weekly"
],
"type": "string",
"description": "Plain cadence: hourly, daily, or weekly. Omit when passing recurrence."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"recurrence": {
"anyOf": [
{
"type": "object",
"required": [
"freq",
"timezone"
],
"properties": {
"ends": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"freq": {
"enum": [
"hourly",
"daily",
"weekly",
"monthly",
"yearly"
],
"type": "string"
},
"skip": {
"type": "array",
"items": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"maxItems": 100
},
"every": {
"type": "integer",
"default": 1,
"maximum": 366,
"minimum": 1
},
"hours": {
"type": "object",
"required": [
"from",
"to"
],
"properties": {
"to": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"from": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
}
}
},
"times": {
"type": "array",
"items": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"maxItems": 24,
"minItems": 1
},
"months": {
"type": "array",
"items": {
"type": "integer",
"maximum": 12,
"minimum": 1
},
"maxItems": 12,
"minItems": 1
},
"starts": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"minutes": {
"type": "array",
"items": {
"type": "integer",
"maximum": 59,
"minimum": 0
},
"maxItems": 12,
"minItems": 1
},
"timezone": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
},
"monthDays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 31,
"minimum": -1
},
"maxItems": 31,
"minItems": 1
},
"nthWeekdays": {
"type": "array",
"items": {
"type": "object",
"required": [
"nth",
"weekdays"
],
"properties": {
"nth": {
"type": "integer",
"maximum": 5,
"minimum": -1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
}
}
},
"maxItems": 5,
"minItems": 1
}
}
},
{
"type": "null"
}
],
"description": "When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {\"freq\":\"hourly\"|\"daily\"|\"weekly\"|\"monthly\"|\"yearly\",\"every\":N,\"times\":[\"HH:MM\"],\"weekdays\":[0=Sun…6=Sat],\"monthDays\":[1…31,-1=last],\"nthWeekdays\":[{\"nth\":1…5|-1,\"weekdays\":[…]}],\"months\":[1…12],\"minutes\":[…],\"hours\":{\"from\",\"to\"},\"timezone\":\"<IANA>\",\"starts\",\"ends\",\"skip\":[\"YYYY-MM-DD\"]}. Examples: weekdays at 8 → {\"freq\":\"weekly\",\"weekdays\":[1,2,3,4,5],\"times\":[\"08:00\"],\"timezone\":\"America/Chicago\"}; the last business day of the month → {\"freq\":\"monthly\",\"nthWeekdays\":[{\"nth\":-1,\"weekdays\":[1,2,3,4,5]}],\"timezone\":\"…\"}; every other Friday → {\"freq\":\"weekly\",\"every\":2,\"weekdays\":[5],\"starts\":\"<a Friday>\",\"timezone\":\"…\"}. null clears it."
},
"scheduleTime": {
"anyOf": [
{
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
{
"type": "null"
}
]
},
"scheduleTimezone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"scheduleDayOfWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 6,
"minimum": 0
},
{
"type": "null"
}
]
}
}
}| Approval id from a prior needs_confirmation response. Omit on the first call. |
| recurrence | any | When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {"freq":"hourly"|"daily"|"weekly"|"monthly"|"yearly","every":N,"times":["HH:MM"],"weekdays":[0=Sun…6=Sat],"monthDays":[1…31,-1=last],"nthWeekdays":[{"nth":1…5|-1,"weekdays":[…]}],"months":[1…12],"minutes":[…],"hours":{"from","to"},"timezone":"<IANA>","starts","ends","skip":["YYYY-MM-DD"]}. Examples: weekdays at 8 → {"freq":"weekly","weekdays":[1,2,3,4,5],"times":["08:00"],"timezone":"America/Chicago"}; the last business day of the month → {"freq":"monthly","nthWeekdays":[{"nth":-1,"weekdays":[1,2,3,4,5]}],"timezone":"…"}; every other Friday → {"freq":"weekly","every":2,"weekdays":[5],"starts":"<a Friday>","timezone":"…"}. null clears it. |
| scheduleId* | string | Schedule id, from workbench_flows_schedules_list. |
| scheduleTime | any |
| scheduleTimezone | any |
| scheduleDayOfWeek | any |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId",
"scheduleId"
],
"properties": {
"input": {
"oneOf": [
{
"type": "object",
"required": [
"kind",
"messages"
],
"properties": {
"kind": {
"type": "string",
"const": "chat"
},
"values": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"messages": {
"type": "array",
"items": {
"type": "object",
"required": [
"role"
],
"properties": {
"name": {
"type": "string"
},
"role": {
"type": "string"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {}
},
{
"type": "null"
}
]
},
"tool_calls": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"function": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"arguments": {}
},
"additionalProperties": {}
}
},
"additionalProperties": {}
}
},
"tool_call_id": {
"type": "string"
}
},
"additionalProperties": {}
}
}
}
},
{
"type": "object",
"required": [
"kind",
"values"
],
"properties": {
"kind": {
"type": "string",
"const": "form"
},
"values": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
}
}
],
"description": "New fixed input envelope — {\"kind\":\"chat\",\"messages\":[…]} or {\"kind\":\"form\",\"values\":{…}}."
},
"label": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
},
"flowId": {
"type": "string",
"description": "Flow the schedule belongs to."
},
"enabled": {
"type": "boolean",
"description": "false pauses, true resumes."
},
"delivery": {
"enum": [
"history",
"notification",
"email"
],
"type": "string"
},
"interval": {
"enum": [
"hourly",
"daily",
"weekly"
],
"type": "string",
"description": "New cadence: hourly, daily, or weekly."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"recurrence": {
"anyOf": [
{
"type": "object",
"required": [
"freq",
"timezone"
],
"properties": {
"ends": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"freq": {
"enum": [
"hourly",
"daily",
"weekly",
"monthly",
"yearly"
],
"type": "string"
},
"skip": {
"type": "array",
"items": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"maxItems": 100
},
"every": {
"type": "integer",
"default": 1,
"maximum": 366,
"minimum": 1
},
"hours": {
"type": "object",
"required": [
"from",
"to"
],
"properties": {
"to": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"from": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
}
}
},
"times": {
"type": "array",
"items": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"maxItems": 24,
"minItems": 1
},
"months": {
"type": "array",
"items": {
"type": "integer",
"maximum": 12,
"minimum": 1
},
"maxItems": 12,
"minItems": 1
},
"starts": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"minutes": {
"type": "array",
"items": {
"type": "integer",
"maximum": 59,
"minimum": 0
},
"maxItems": 12,
"minItems": 1
},
"timezone": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
},
"monthDays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 31,
"minimum": -1
},
"maxItems": 31,
"minItems": 1
},
"nthWeekdays": {
"type": "array",
"items": {
"type": "object",
"required": [
"nth",
"weekdays"
],
"properties": {
"nth": {
"type": "integer",
"maximum": 5,
"minimum": -1
},
"weekdays": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxItems": 7,
"minItems": 1
}
}
},
"maxItems": 5,
"minItems": 1
}
}
},
{
"type": "null"
}
],
"description": "When it runs, like a calendar event repeats; use it for anything beyond a plain hourly/daily/weekly at one time (then omit interval). {\"freq\":\"hourly\"|\"daily\"|\"weekly\"|\"monthly\"|\"yearly\",\"every\":N,\"times\":[\"HH:MM\"],\"weekdays\":[0=Sun…6=Sat],\"monthDays\":[1…31,-1=last],\"nthWeekdays\":[{\"nth\":1…5|-1,\"weekdays\":[…]}],\"months\":[1…12],\"minutes\":[…],\"hours\":{\"from\",\"to\"},\"timezone\":\"<IANA>\",\"starts\",\"ends\",\"skip\":[\"YYYY-MM-DD\"]}. Examples: weekdays at 8 → {\"freq\":\"weekly\",\"weekdays\":[1,2,3,4,5],\"times\":[\"08:00\"],\"timezone\":\"America/Chicago\"}; the last business day of the month → {\"freq\":\"monthly\",\"nthWeekdays\":[{\"nth\":-1,\"weekdays\":[1,2,3,4,5]}],\"timezone\":\"…\"}; every other Friday → {\"freq\":\"weekly\",\"every\":2,\"weekdays\":[5],\"starts\":\"<a Friday>\",\"timezone\":\"…\"}. null clears it."
},
"scheduleId": {
"type": "string",
"description": "Schedule id, from workbench_flows_schedules_list."
},
"scheduleTime": {
"anyOf": [
{
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
{
"type": "null"
}
]
},
"scheduleTimezone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"scheduleDayOfWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 6,
"minimum": 0
},
{
"type": "null"
}
]
}
}
}| description | any | New description; null clears it. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"flowId"
],
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 50,
"description": "Replacement tag set (lowercase labels). The whole set, not a diff."
},
"flowId": {
"type": "string",
"description": "Flow id, from workbench_flows_list."
},
"archived": {
"type": "boolean",
"description": "true archives, false restores."
},
"flowName": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "New name."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; tokens with a default can override per call. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation response. Omit on the first call."
},
"visibility": {
"enum": [
"PRIVATE",
"WORKSPACE",
"SHARED"
],
"type": "string",
"description": "Who can see it: PRIVATE (only the user), WORKSPACE (every member, the default), or SHARED (specific people, granted afterwards). Say 'make it private' → PRIVATE."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
],
"description": "New description; null clears it."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"q": {
"type": "string",
"description": "Keyword over slug / name / tagline / description."
},
"slug": {
"type": "string",
"description": "Exact node slug → full detail for that one node (ports + settings)."
},
"limit": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Results per page, 1-50. Default 20."
},
"flowId": {
"type": "string",
"description": "A flow whose pinned imports should appear as `imported-<uuid>` nodes."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Pagination offset."
},
"category": {
"type": "string",
"description": "Filter by category."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Personal tokens with no default workspace MUST pass this; the catalog's policy annotation is per workspace."
}
}
}| What the workspace is for, from what they said. |
| workspace | string | Workspace slug. Ignored for workspace API keys. |
| approvalId | string | Approval id from a prior needs_confirmation envelope. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"folders"
],
"properties": {
"folders": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Named after their actual work."
},
"rooms": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"flowIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Published, workspace-shared flows to bring in."
},
"opening": {
"type": "string",
"description": "Your first message in the room: the concrete next step."
},
"private": {
"type": "boolean",
"description": "Members only. Use it when they describe the work as sensitive or not for everyone yet (leadership, people matters, pricing, anything they call confidential). Default is open to the workspace."
}
}
}
},
"pieces": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind",
"title"
],
"properties": {
"body": {
"type": "string",
"description": "Markdown for a page or doc (a short outline, no filler); diagram text for a diagram; a description for a dataset."
},
"kind": {
"enum": [
"compass_page",
"napkin_doc",
"napkin_diagram",
"napkin_board",
"napkin_sheet",
"caliper_dataset"
],
"type": "string"
},
"title": {
"type": "string"
},
"pageType": {
"type": "string",
"description": "Compass page type, e.g. WORKFLOW."
}
}
}
},
"existing": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind",
"id"
],
"properties": {
"id": {
"type": "string"
},
"kind": {
"type": "string"
}
}
},
"description": "Things that already exist to file in, e.g. { kind: 'workbench_flow', id }."
}
}
},
"maxItems": 5,
"minItems": 1
},
"workKinds": {
"type": "array",
"items": {
"enum": [
"process_redesign",
"research",
"ai_design",
"knowledge",
"exploring"
],
"type": "string"
},
"description": "What the workspace is for, from what they said."
},
"workspace": {
"type": "string",
"description": "Workspace slug. Ignored for workspace API keys."
},
"approvalId": {
"type": "string",
"description": "Approval id from a prior needs_confirmation envelope."
}
}
}