Workflows
Several agents in a fixed order, the designs and the runs
On this page(8 sections)
A workflow is a design: run these conversations, in this order, each handing its result to the next. These routes hold the saved designs and the run history, start a run, stop one in flight, and archive the ones you are done reading.
8 calls. Pick one to open it, or use the list on the right.
GET/workflowsSaved workflows and their runs
Every workflow somebody has designed, each with its own run history, newest first. One answer rather than two, because a workflow that has never been run is the interesting case rather than a mistake.
What you send
Nothing. Call it as it is.
What comes back
| Field | Type |
|---|---|
workflowsEvery saved design with its own… | object[] |
idThe workflow's id | string |
nameWhat to call it | string |
descriptionWhat it is for | string |
stepsThe steps, each with what it… | object[] |
idThis step's own name, which other… | string |
titleWhat to call it on screen | string |
goalWhat done means for this step,… | string |
promptWhat the step is told to… | string |
needsWhich steps must finish first | string[] |
handoffHow it meets what came before:… | "fresh" | "continue" |
outputWhat it has to produce for… | object |
kindIt produces nothing but its work | "none" |
checksWhat has to pass before it… | object[] |
kindRun something and see if it… | "command" |
commandThe command to run in the… | string |
contextHow the step's own repeats meet… | "fresh" | "continue" |
maxSpendUsdA ceiling on what this step… | number |
agentWhich provider runs it | string |
harnessWhich agentic loop runs it | "native" | "claude-code" |
accountWhich account pays for it | string |
modelWhich model runs it | string |
actsAsWhich persona it acts as | string |
gatePresent means a machine can run… | object |
stepWhich step's answer carries the decision | string |
fieldWhich of that step's declared answers… | string |
passWhich values mean ship it | string[] |
tokenThe credential the calling pipeline presents | string |
dailyMaxHow many runs a day, across… | integer |
maxParallelHow many steps may run at… | integer |
runsIts runs, newest first | object[] |
runIdThis run's id | string |
workflowThe design as it stood when… | object |
idThe workflow's id | string |
nameWhat to call it | string |
descriptionWhat it is for | string |
stepsThe steps, each with what it… | object[] |
gatePresent means a machine can run… | object |
maxParallelHow many steps may run at… | integer |
reposThe workspace as this run began,… | object[] |
repo | string |
base | string |
requestWhat this run was asked to… | string |
stateHow the run is going | "running" | "done" | "failed" | "stopped" … (6) |
startedAtWhen it began, in milliseconds | number |
endedAtWhen it ended, in milliseconds | number |
resumedHow many times the sandbox restarted… | integer |
detailWhat went wrong, when something did | string |
stepsOne entry per step, in the… | object[] |
stepIdWhich step this is | string |
stateHow it went | "pending" | "running" | "done" | "failed" … (6) |
conversationIdThe conversation it ran on, and… | string |
startedAtWhen it began, in milliseconds | number |
endedAtWhen it ended, in milliseconds | number |
iterationsHow many rounds it took | integer |
costUsdWhat it cost, in dollars | number |
loopStateHow its repeating ended | "running" | "done" | "exhausted" | "stalled" … (7) |
detailWhat went wrong, when something did | string |
documentWhat it produced, once it has… | object |
reportThe start of its closing words | string |
reportPathWhere the whole answer is, as… | string |
archivedAtWhen it was put away, in… | number |
curl "$SANDBOX/workflows" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.list();POST/workflowsCreate or replace a workflow
Writes a workflow design. Say which of the two you mean, so an id that happens to collide cannot silently overwrite somebody's work. A design that could never run is refused, in the same words the editor shows while you type: a loop in the steps, a step waiting on one that is not there, a step with no way of knowing it is finished.
What you send
| Field | Type | Where |
|---|---|---|
workflowrequiredThe design to write | object | body |
idrequiredThe workflow's id | string | body |
namerequiredWhat to call it | string | body |
descriptionWhat it is for | string | body |
stepsrequiredThe steps, each with what it… | object[] | body |
idrequiredThis step's own name, which other… | string | body |
titlerequiredWhat to call it on screen | string | body |
goalWhat done means for this step,… | string | body |
promptWhat the step is told to… | string | body |
needsrequiredWhich steps must finish first | string[] | body |
handoffrequiredHow it meets what came before:… | "fresh" | "continue" | body |
outputrequiredWhat it has to produce for… | object | body |
kindrequiredIt produces nothing but its work | "none" | body |
checksrequiredWhat has to pass before it… | object[] | body |
kindrequiredRun something and see if it… | "command" | body |
commandrequiredThe command to run in the… | string | body |
contextrequiredHow the step's own repeats meet… | "fresh" | "continue" | body |
maxSpendUsdA ceiling on what this step… | number | body |
agentWhich provider runs it | string | body |
harnessWhich agentic loop runs it | "native" | "claude-code" | body |
accountWhich account pays for it | string | body |
modelWhich model runs it | string | body |
actsAsWhich persona it acts as | string | body |
gatePresent means a machine can run… | object | body |
steprequiredWhich step's answer carries the decision | string | body |
fieldrequiredWhich of that step's declared answers… | string | body |
passrequiredWhich values mean ship it | string[] | body |
tokenThe credential the calling pipeline presents | string | body |
dailyMaxHow many runs a day, across… | integer | body |
maxParallelrequiredHow many steps may run at… | integer | body |
createrequiredWhether you mean to make a… | boolean | body |
What comes back
| Field | Type |
|---|---|
idThe workflow's id | string |
nameWhat to call it | string |
descriptionWhat it is for | string |
stepsThe steps, each with what it… | object[] |
idThis step's own name, which other… | string |
titleWhat to call it on screen | string |
goalWhat done means for this step,… | string |
promptWhat the step is told to… | string |
needsWhich steps must finish first | string[] |
handoffHow it meets what came before:… | "fresh" | "continue" |
outputWhat it has to produce for… | object |
when kind is "none" | shape |
when kind is "claim" | shape |
when kind is "json" | shape |
fieldsThe shape that answer has to… | object[] |
checksWhat has to pass before it… | object[] |
when kind is "command" | shape |
commandThe command to run in the… | string |
when kind is "judge" | shape |
rubricWhat that judge is asked | string |
modelWhich model judges | string |
contextHow the step's own repeats meet… | "fresh" | "continue" |
maxSpendUsdA ceiling on what this step… | number |
agentWhich provider runs it | string |
harnessWhich agentic loop runs it | "native" | "claude-code" |
accountWhich account pays for it | string |
modelWhich model runs it | string |
actsAsWhich persona it acts as | string |
gatePresent means a machine can run… | object |
stepWhich step's answer carries the decision | string |
fieldWhich of that step's declared answers… | string |
passWhich values mean ship it | string[] |
tokenThe credential the calling pipeline presents | string |
dailyMaxHow many runs a day, across… | integer |
maxParallelHow many steps may run at… | integer |
curl -X POST "$SANDBOX/workflows" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"workflow":{"id":"a1b2c3d4","name":"nightly changelog","description":"Runs every night and opens a pull request when anything changed.","steps":[{"id":"a1b2c3d4","title":"Update the changelog","goal":"…","prompt":"Update the changelog for the last five commits.","needs":["…","…"],"handoff":"fresh","output":{},"checks":[],"context":"fresh","maxSpendUsd":1,"agent":"…","harness":"native","account":"work","model":"claude-sonnet-4-6","actsAs":"…"},{"id":"e5f6a7b8","title":"Draft the release notes","goal":"…","prompt":"Update the changelog for the last five commits.","needs":["…","…"],"handoff":"continue","output":{},"checks":[],"context":"continue","maxSpendUsd":1,"agent":"…","harness":"claude-code","account":"work","model":"claude-haiku-4-6","actsAs":"…"}],"gate":{"step":"…","field":"…","pass":["…","…"],"token":"ict_9wQ4rTz8kLmN3pXbV7hJ","dailyMax":1},"maxParallel":1},"create":true}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.save({
"workflow": {
"id": "a1b2c3d4",
"name": "nightly changelog",
"description": "Runs every night and opens a pull request when anything changed.",
"steps": [
{
"id": "a1b2c3d4",
"title": "Update the changelog",
"goal": "…",
"prompt": "Update the changelog for the last five commits.",
"needs": [
"…",
"…"
],
"handoff": "fresh",
"output": {},
"checks": [],
"context": "fresh",
"maxSpendUsd": 1,
"agent": "…",
"harness": "native",
"account": "work",
"model": "claude-sonnet-4-6",
"actsAs": "…"
},
{
"id": "e5f6a7b8",
"title": "Draft the release notes",
"goal": "…",
"prompt": "Update the changelog for the last five commits.",
"needs": [
"…",
"…"
],
"handoff": "continue",
"output": {},
"checks": [],
"context": "continue",
"maxSpendUsd": 1,
"agent": "…",
"harness": "claude-code",
"account": "work",
"model": "claude-haiku-4-6",
"actsAs": "…"
}
],
"gate": {
"step": "…",
"field": "…",
"pass": [
"…",
"…"
],
"token": "ict_9wQ4rTz8kLmN3pXbV7hJ",
"dailyMax": 1
},
"maxParallel": 1
},
"create": true
});DELETE/workflows/{id}Delete a workflow
Removes the design. A run of it that is already going keeps going and stays readable and stoppable, because a run takes its own copy of the design when it starts.
What you send
| Field | Type | Where |
|---|---|---|
idrequiredWhich workflow | string | address |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X DELETE "$SANDBOX/workflows/a1b2c3d4" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.remove({
"id": "a1b2c3d4"
});POST/workflows/{id}/runStart a workflow
Kicks a workflow off and answers immediately with the run as recorded; the work carries on without you. Point it at a question and every step gets that on top of its own instructions. Every step is written down as waiting up front, so the picture is complete from the first frame. Several runs of one design can be in flight at once without colliding.
What you send
| Field | Type | Where |
|---|---|---|
idrequiredWhich workflow | string | address |
requestWhat to point it at | string | body |
What comes back
| Field | Type |
|---|---|
runIdThis run's id | string |
workflowThe design as it stood when… | object |
idThe workflow's id | string |
nameWhat to call it | string |
descriptionWhat it is for | string |
stepsThe steps, each with what it… | object[] |
idThis step's own name, which other… | string |
titleWhat to call it on screen | string |
goalWhat done means for this step,… | string |
promptWhat the step is told to… | string |
needsWhich steps must finish first | string[] |
handoffHow it meets what came before:… | "fresh" | "continue" |
outputWhat it has to produce for… | object |
kindIt produces nothing but its work | "none" |
checksWhat has to pass before it… | object[] |
kindRun something and see if it… | "command" |
commandThe command to run in the… | string |
contextHow the step's own repeats meet… | "fresh" | "continue" |
maxSpendUsdA ceiling on what this step… | number |
agentWhich provider runs it | string |
harnessWhich agentic loop runs it | "native" | "claude-code" |
accountWhich account pays for it | string |
modelWhich model runs it | string |
actsAsWhich persona it acts as | string |
gatePresent means a machine can run… | object |
stepWhich step's answer carries the decision | string |
fieldWhich of that step's declared answers… | string |
passWhich values mean ship it | string[] |
tokenThe credential the calling pipeline presents | string |
dailyMaxHow many runs a day, across… | integer |
maxParallelHow many steps may run at… | integer |
reposThe workspace as this run began,… | object[] |
repo | string |
base | string |
requestWhat this run was asked to… | string |
stateHow the run is going | "running" | "done" | "failed" | "stopped" … (6) |
startedAtWhen it began, in milliseconds | number |
endedAtWhen it ended, in milliseconds | number |
resumedHow many times the sandbox restarted… | integer |
detailWhat went wrong, when something did | string |
stepsOne entry per step, in the… | object[] |
stepIdWhich step this is | string |
stateHow it went | "pending" | "running" | "done" | "failed" … (6) |
conversationIdThe conversation it ran on, and… | string |
startedAtWhen it began, in milliseconds | number |
endedAtWhen it ended, in milliseconds | number |
iterationsHow many rounds it took | integer |
costUsdWhat it cost, in dollars | number |
loopStateHow its repeating ended | "running" | "done" | "exhausted" | "stalled" … (7) |
detailWhat went wrong, when something did | string |
documentWhat it produced, once it has… | object |
doneWhether the goal is met | boolean |
reasonWhy, in one line | string |
evidenceWhat was checked to know that | string |
dataThe declared answer, for a loop… | object |
reportThe start of its closing words | string |
reportPathWhere the whole answer is, as… | string |
archivedAtWhen it was put away, in… | number |
curl -X POST "$SANDBOX/workflows/a1b2c3d4/run" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"request":"…"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.run({
"id": "a1b2c3d4",
"request": "…"
});GET/workflows/runsEvery workflow run
All runs across all workflows, newest first. This is also the only place the runs of a deleted workflow are still reachable.
What you send
Nothing. Call it as it is.
What comes back
| Field | Type |
|---|---|
runsEvery run across every workflow, newest… | object[] |
runIdThis run's id | string |
workflowThe design as it stood when… | object |
idThe workflow's id | string |
nameWhat to call it | string |
descriptionWhat it is for | string |
stepsThe steps, each with what it… | object[] |
idThis step's own name, which other… | string |
titleWhat to call it on screen | string |
goalWhat done means for this step,… | string |
promptWhat the step is told to… | string |
needsWhich steps must finish first | string[] |
handoffHow it meets what came before:… | "fresh" | "continue" |
outputWhat it has to produce for… | object |
checksWhat has to pass before it… | object[] |
contextHow the step's own repeats meet… | "fresh" | "continue" |
maxSpendUsdA ceiling on what this step… | number |
agentWhich provider runs it | string |
harnessWhich agentic loop runs it | "native" | "claude-code" |
accountWhich account pays for it | string |
modelWhich model runs it | string |
actsAsWhich persona it acts as | string |
gatePresent means a machine can run… | object |
stepWhich step's answer carries the decision | string |
fieldWhich of that step's declared answers… | string |
passWhich values mean ship it | string[] |
tokenThe credential the calling pipeline presents | string |
dailyMaxHow many runs a day, across… | integer |
maxParallelHow many steps may run at… | integer |
reposThe workspace as this run began,… | object[] |
repo | string |
base | string |
requestWhat this run was asked to… | string |
stateHow the run is going | "running" | "done" | "failed" | "stopped" … (6) |
startedAtWhen it began, in milliseconds | number |
endedAtWhen it ended, in milliseconds | number |
resumedHow many times the sandbox restarted… | integer |
detailWhat went wrong, when something did | string |
stepsOne entry per step, in the… | object[] |
stepIdWhich step this is | string |
stateHow it went | "pending" | "running" | "done" | "failed" … (6) |
conversationIdThe conversation it ran on, and… | string |
startedAtWhen it began, in milliseconds | number |
endedAtWhen it ended, in milliseconds | number |
iterationsHow many rounds it took | integer |
costUsdWhat it cost, in dollars | number |
loopStateHow its repeating ended | "running" | "done" | "exhausted" | "stalled" … (7) |
detailWhat went wrong, when something did | string |
documentWhat it produced, once it has… | object |
doneWhether the goal is met | boolean |
reasonWhy, in one line | string |
evidenceWhat was checked to know that | string |
dataThe declared answer, for a loop… | object |
reportThe start of its closing words | string |
reportPathWhere the whole answer is, as… | string |
archivedAtWhen it was put away, in… | number |
curl "$SANDBOX/workflows/runs" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.runs();POST/workflows/runs/{runId}/stopStop a run now
Nothing further starts, and the steps already going are cut off where they stand. Whatever they had written stays on their branches. Deliberately abrupt rather than letting the current step finish: a step is a whole agent turn, and a stop that kept spending for minutes afterwards is indistinguishable from a button that does nothing. It always ends the run, including one left stranded by a daemon that was replaced mid-flight.
What you send
| Field | Type | Where |
|---|---|---|
runIdrequiredWhich run | string | address |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X POST "$SANDBOX/workflows/runs/run_8c2f41d9/stop" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.stopRun({
"runId": "run_8c2f41d9"
});POST/workflows/runs/{runId}/archiveTake a finished run off the board
Nothing is lost and the working copies are reclaimed. Every conversation the run started is put away with it, which is what makes this an archive rather than a dismissal: a step has no card of its own, so merely dropping the run would spill its conversations onto the board at the moment somebody said they were done. Refused while the run is still going.
What you send
| Field | Type | Where |
|---|---|---|
runIdrequiredWhich run | string | address |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X POST "$SANDBOX/workflows/runs/run_8c2f41d9/archive" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.archiveRun({
"runId": "run_8c2f41d9"
});POST/workflows/runs/{runId}/unarchiveBring an archived run back
Puts a run and every conversation it started back on the board.
What you send
| Field | Type | Where |
|---|---|---|
runIdrequiredWhich run | string | address |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X POST "$SANDBOX/workflows/runs/run_8c2f41d9/unarchive" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.workflows.unarchiveRun({
"runId": "run_8c2f41d9"
});