One agent
Run a turn in one conversation, then attach to it, answer it, steer it or stop it
On this page(18 sections)
- Say something to an agent
- Watch a turn happen
- Answer a question the agent asked
- Interrupt a running turn
- Stop a turn now
- Reword a waiting message
- Take back a waiting message
- Let waiting messages go
- Move waiting messages to another model
- Reschedule waiting messages
- Book a Continue for later
- Run a refused turn again
- Move a conversation to another account
- Choose how a held turn continues
- Go back to an earlier message
- Shortcut commands the agent knows
- Choose what a new chat opens on
- The last time each provider said no
The surface most callers are here for. Starting a turn answers with a run id and nothing else: the work happens inside the sandbox whether or not anybody stays connected, and attaching is how you watch it, from the beginning or from wherever you had got to. The rest is the things a person does to a turn in flight — answer a question it asked, redirect it, stop it, or put the whole conversation back to an earlier point. Everything here addresses one conversation by id.
18 calls. Pick one to open it, or use the list on the right.
POST/agentSay something to an agent
Answers at once with what became of the message: it starts a turn when the conversation is free, is said into the running turn where that turn takes words mid-way, and otherwise waits in the conversation's queue for the next turn, where every window sees it. The work runs inside the sandbox whether or not anybody stays connected; watch it by attaching. Naming a conversation that does not exist yet opens it. Give the message an id, and sending it again after a lost answer is met with what became of it the first time rather than a second delivery.
What you send
| Field | Type | Where |
|---|---|---|
promptrequiredWhat to say to the agent | string | body |
errandWhat the words are for, when… | "land-conflict" | "verify-nudge" | "land-breakage" | "land-fix" … (10) | body |
messageIdYour id for this message | string | body |
titleA title for a conversation this… | string | body |
attachmentsFiles to hand the agent along… | string[] | body |
mentionsWorkspace paths the prompt mentions with… | string[] | body |
agentWhich model provider serves this turn | string | body |
harnessWhich agentic loop runs the turn | "native" | "claude-code" | "codex" | "opencode" … (7) | body |
accountWhich of that provider's connected accounts… | string | body |
actsAsWhich persona the turn speaks as… | string | body |
sessionIdResume this provider session instead of… | string | body |
conversationIdThe conversation this turn belongs to | string | body |
isolatedWork in this conversation's own private… | boolean | body |
startInWhich folder the conversation opens in,… | string | body |
placementWhere this conversation runs: this sandbox… | object | body |
when kind is "local" | shape | body |
when kind is "runner" | shape | body |
idrequired | string | body |
worktreeBasePin a new private copy to… | object[] | body |
reporequired | string | body |
baserequired | string | body |
autoLandWhether this turn's work merges into… | boolean | body |
runRoleWhat started this turn, when it… | "commit-message" | "session-title" | "safety-judge" | "loop-verdict" … (16) | body |
originSet by the sandbox alone: this… | object | body |
automationIdrequired | string | body |
providerrequired | string | body |
channelId | string | body |
threadId | string | body |
author | string | body |
forkOfWhere this conversation was cut from,… | object | body |
conversationIdrequiredThe conversation this one was cut… | string | body |
keeprequiredHow many of that conversation's messages… | integer | body |
filesrequiredWhich files the fork opens on:… | "then" | "now" | body |
freshOfOpen this conversation on another conversation's… | object | body |
conversationIdrequiredThe conversation whose work this one… | string | body |
kindrequiredWhat it is opened for: a… | "review" | "test" | "ask" | body |
modelWhich model to use | string | body |
unattendedNobody is watching this turn: a… | boolean | body |
outsideWakeContent from outside caused this turn,… | string | body |
permissionModeHow tool calls are gated: ask… | "default" | "plan" | "bypassPermissions" | body |
allowedToolsNarrow the turn to these tools | string[] | body |
effortHow hard the model should think,… | string | body |
thinkingWhether to show the model's reasoning… | boolean | body |
fastAsk for the same work at… | boolean | body |
autoPickedWhether this turn's model was chosen… | boolean | body |
editorContextWhat the user has open in… | object | body |
filerequiredThe file open in the editor,… | string | body |
startLineFirst line of the selection, counting… | integer | body |
endLineLast line of the selection, counting… | integer | body |
selectionThe selected text itself | string | body |
sendAtHold this message until then (epoch… | integer | body |
sendAtReopenSays `sendAt` is the reopen of… | true | body |
sendAfterHold this message until the conversation… | string | body |
conversationAutoLandWhether this conversation's finished work merges… | boolean | body |
draftThe revision of your composer draft… | integer | body |
continuesCarry the conversation on from where… | true | body |
What comes back
| Field | Type |
|---|---|
deliveredWhat became of the message: it… | "started" | "steered" | "queued" |
runThe run the message is in:… | string |
duplicateThe sandbox had already taken a… | true |
curl -X POST "$SANDBOX/agent" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"prompt":"Update the changelog for the last five commits.","errand":"land-conflict","messageId":"a1b2c3d4","title":"Update the changelog","attachments":["…","…"],"mentions":["…","…"],"agent":"…","harness":"native","account":"work","actsAs":"…","sessionId":"a1b2c3d4","conversationId":"nightly-changelog","isolated":true,"startIn":"…","placement":{"kind":"local"},"worktreeBase":[{"repo":"root","base":"…"},{"repo":"site","base":"…"}],"autoLand":true,"runRole":"commit-message","origin":{"automationId":"a1b2c3d4","provider":"claude","channelId":"a1b2c3d4","threadId":"a1b2c3d4","author":"Ada Lovelace"},"forkOf":{"conversationId":"nightly-changelog","keep":0,"files":"then"},"freshOf":{"conversationId":"nightly-changelog","kind":"review"},"model":"claude-sonnet-4-6","unattended":true,"outsideWake":"…","permissionMode":"default","allowedTools":["…","…"],"effort":"…","thinking":true,"fast":true,"autoPicked":true,"editorContext":{"file":"…","startLine":1,"endLine":1,"selection":"…"},"sendAt":1,"sendAtReopen":true,"sendAfter":"…","conversationAutoLand":true,"draft":1,"continues":true}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.run({
"prompt": "Update the changelog for the last five commits.",
"errand": "land-conflict",
"messageId": "a1b2c3d4",
"title": "Update the changelog",
"attachments": [
"…",
"…"
],
"mentions": [
"…",
"…"
],
"agent": "…",
"harness": "native",
"account": "work",
"actsAs": "…",
"sessionId": "a1b2c3d4",
"conversationId": "nightly-changelog",
"isolated": true,
"startIn": "…",
"placement": {
"kind": "local"
},
"worktreeBase": [
{
"repo": "root",
"base": "…"
},
{
"repo": "site",
"base": "…"
}
],
"autoLand": true,
"runRole": "commit-message",
"origin": {
"automationId": "a1b2c3d4",
"provider": "claude",
"channelId": "a1b2c3d4",
"threadId": "a1b2c3d4",
"author": "Ada Lovelace"
},
"forkOf": {
"conversationId": "nightly-changelog",
"keep": 0,
"files": "then"
},
"freshOf": {
"conversationId": "nightly-changelog",
"kind": "review"
},
"model": "claude-sonnet-4-6",
"unattended": true,
"outsideWake": "…",
"permissionMode": "default",
"allowedTools": [
"…",
"…"
],
"effort": "…",
"thinking": true,
"fast": true,
"autoPicked": true,
"editorContext": {
"file": "…",
"startLine": 1,
"endLine": 1,
"selection": "…"
},
"sendAt": 1,
"sendAtReopen": true,
"sendAfter": "…",
"conversationAutoLand": true,
"draft": 1,
"continues": true
});POST/agent/attachWatch a turn happenstream
Streams everything the agent does: its words, the tools it reaches for, and the answers it gets. It opens with the turn's transcript whole as it stands, then sends every change as it lands, so a reload or a dropped connection loses nothing: attaching again hands over the whole transcript again. The window that started the turn holds no special claim, and any number of watchers on any number of devices see the same thing.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich conversation to watch | string | body |
runThe run you were watching | string | body |
afterA run you already watched to… | string | body |
What comes back
| Field | Type |
|---|---|
when event is "message" | shape |
data | object |
when kind is "attached" | shape |
runThe run's id | string |
startedAtWhen it started, in milliseconds, so… | number |
seqHow many frames the run has… | number |
rowsThe turn's rows as they stand:… | object[] |
when kind is "patch" | shape |
seqIts position in the run, counting… | number |
patch | object |
when kind is "fact" | shape |
seqIts position in the run, counting… | number |
fact | object |
when kind is "end" | shape |
id | string |
retry | number |
when event is "done" | shape |
data | unknown |
id | string |
retry | number |
when event is "error" | shape |
data | unknown |
id | string |
retry | number |
curl -N -X POST "$SANDBOX/agent/attach" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","run":"run_8c2f41d9","after":"…"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.attach({
"conversationId": "nightly-changelog",
"run": "run_8c2f41d9",
"after": "…"
});POST/agent/replyAnswer a question the agent asked
Un-parks a turn that is waiting on you: approving a plan, choosing between options, or permitting a tool. The turn picks up where it stopped.
What you send
| Field | Type | Where |
|---|---|---|
when kind is "plan" | shape | body |
requestIdrequiredWhich card you are answering, from… | string | body |
approverequiredWhether to go ahead | boolean | body |
feedbackWhy not, which goes back to… | string | body |
when kind is "question" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
answersWhat you chose, keyed by the… | object | body |
attachmentsFiles that go with your own-words… | object | body |
cancelledDismissing it instead, which tells the… | boolean | body |
when kind is "permission" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
decisionrequiredOnce allows this call alone; always… | "once" | "always" | "everything" | "deny" | body |
feedbackWhy not, which goes back to… | string | body |
childFor a request to start a… | object | body |
providerrequiredWhich provider serves it | string | body |
modelrequiredWhich of that provider's models | string | body |
harnessWhich agentic loop runs it | "native" | "claude-code" | "codex" | "opencode" … (7) | body |
accountWhich of that provider's connected accounts… | string | body |
effortHow hard it thinks, where the… | string | body |
thinkingWhether it reasons before it answers,… | boolean | body |
fastWhether it asks for the faster… | boolean | body |
when kind is "browser_help" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
helpedrequiredWhether you cleared it | boolean | body |
noteAnything the agent should know, which… | string | body |
when kind is "terminal_help" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
helpedrequiredWhether you did it | boolean | body |
noteAnything the agent should know, which… | string | body |
when kind is "capability_offer" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
connectrequiredYes keeps the agent waiting while… | boolean | body |
when kind is "payment_offer" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
approverequiredYes releases exactly one payment | boolean | body |
when kind is "page_ask" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
valueWhat the page sent back, as… | string | body |
cancelledDismissing it instead, which tells the… | boolean | body |
when kind is "credential_offer" | shape | body |
requestIdrequiredWhich card you are answering | string | body |
approverequiredYes releases it, as far as… | boolean | body |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X POST "$SANDBOX/agent/reply" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"kind":"plan","requestId":"a1b2c3d4","approve":true,"feedback":"…"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.reply({
"kind": "plan",
"requestId": "a1b2c3d4",
"approve": true,
"feedback": "…"
});POST/agent/steerInterrupt a running turn
Slips a message into a turn already under way, without stopping it. This is how you redirect an agent mid-thought rather than waiting for it to finish being wrong. Give the message an id, and sending it again after a lost answer is met with what became of it the first time rather than saying it twice.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich running conversation to interrupt | string | body |
textrequiredWhat to say to it | string | body |
messageIdYour id for this message | string | body |
attachmentsFiles to send with it, as… | string[] | body |
mentionsWorkspace paths the message mentions with… | string[] | body |
editorContextWhat you have open, folded in… | object | body |
filerequiredThe file open in the editor,… | string | body |
startLineFirst line of the selection, counting… | integer | body |
endLineLast line of the selection, counting… | integer | body |
selectionThe selected text itself | string | body |
What comes back
| Field | Type |
|---|---|
deliveredWhat became of the message: it… | "started" | "steered" | "queued" |
runThe run the message is in:… | string |
duplicateThe sandbox had already taken a… | true |
curl -X POST "$SANDBOX/agent/steer" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","text":"export const start = () => listen(PORT);\n","messageId":"a1b2c3d4","attachments":["…","…"],"mentions":["…","…"],"editorContext":{"file":"…","startLine":1,"endLine":1,"selection":"…"}}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.steer({
"conversationId": "nightly-changelog",
"text": "export const start = () => listen(PORT);\n",
"messageId": "a1b2c3d4",
"attachments": [
"…",
"…"
],
"mentions": [
"…",
"…"
],
"editorContext": {
"file": "…",
"startLine": 1,
"endLine": 1,
"selection": "…"
}
});POST/agent/stopStop a turn now
Cancels the running turn inside the sandbox. Whatever it had already written to disk stays written, and whatever waits in the conversation's queue is held there, for everyone, until somebody resumes it. Name the run you mean: a stop that arrives after that run has ended cancels nothing, rather than whatever turn started next.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich conversation's running turn to cancel | string | body |
runrequiredThe run you mean to cancel,… | string | body |
What comes back
| Field | Type |
|---|---|
stoppedWhether a turn was cancelled | boolean |
runningThe run that is live instead… | string |
curl -X POST "$SANDBOX/agent/stop" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","run":"run_8c2f41d9"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.stop({
"conversationId": "nightly-changelog",
"run": "run_8c2f41d9"
});POST/agent/queue/editReword a waiting message
Changes what a message waiting in the conversation's queue says, keeping its place. Name the revision you read it at: if somebody changed it since, on this device or another, nothing is changed and you are told so.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhose queue | string | body |
idrequiredWhich waiting message | string | body |
revisionrequiredThe message's revision as you read… | integer | body |
textrequiredWhat the message should say instead | string | body |
What comes back
| Field | Type |
|---|---|
itemsWhat waits, in the order it… | object[] |
idThe message's id: what its sender… | string |
textThe words, as they will go… | string |
attachmentsFiles that go with it, as… | string[] |
voiceWho it is from: a person,… | "person" | "sandbox" | "agent" |
queuedAtWhen it joined the queue, in… | number |
revisionThe queue's revision when this message… | integer |
untilWhen this message goes out by… | number |
afterThe conversation whose finished work must… | string |
reopenOfThe allowance this message's `until` waits… | object |
agentThe provider whose allowance it waits… | string |
accountWhich of its accounts | string |
servesWho serves the turn this message… | object |
agentThe provider | string |
harnessThe agentic loop | "native" | "claude-code" | "codex" | "opencode" … (7) |
modelThe model | string |
effortHow hard it thinks, where the… | string |
accountThe account that pays for it | string |
continuesA continuation, not words: when it… | true |
revisionMoves with every change to the… | integer |
pausedWhy the messages with no booking… | "stopped" | "refused" | "scheduled" |
untilThe soonest booked message's time, in… | number |
afterThe conversation the first booked message… | string |
curl -X POST "$SANDBOX/agent/queue/edit" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","id":"a1b2c3d4","revision":0,"text":"export const start = () => listen(PORT);\n"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.queueEdit({
"conversationId": "nightly-changelog",
"id": "a1b2c3d4",
"revision": 0,
"text": "export const start = () => listen(PORT);\n"
});POST/agent/queue/removeTake back a waiting message
Removes a message from the conversation's queue before the agent gets it. Name the revision you read it at: a message somebody reworded since is left alone, so you never take back words you have not seen. A message that opened its conversation by being scheduled, with nothing else in that conversation since, takes the conversation with it: the answer says so, and the words are the caller's to put back where they were written.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhose queue | string | body |
idrequiredWhich waiting message | string | body |
revisionrequiredThe message's revision as you read… | integer | body |
What comes back
| Field | Type |
|---|---|
itemsWhat waits, in the order it… | object[] |
idThe message's id: what its sender… | string |
textThe words, as they will go… | string |
attachmentsFiles that go with it, as… | string[] |
voiceWho it is from: a person,… | "person" | "sandbox" | "agent" |
queuedAtWhen it joined the queue, in… | number |
revisionThe queue's revision when this message… | integer |
untilWhen this message goes out by… | number |
afterThe conversation whose finished work must… | string |
reopenOfThe allowance this message's `until` waits… | object |
agentThe provider whose allowance it waits… | string |
accountWhich of its accounts | string |
servesWho serves the turn this message… | object |
agentThe provider | string |
harnessThe agentic loop | "native" | "claude-code" | "codex" | "opencode" … (7) |
modelThe model | string |
effortHow hard it thinks, where the… | string |
accountThe account that pays for it | string |
continuesA continuation, not words: when it… | true |
revisionMoves with every change to the… | integer |
pausedWhy the messages with no booking… | "stopped" | "refused" | "scheduled" |
untilThe soonest booked message's time, in… | number |
afterThe conversation the first booked message… | string |
unopenedTrue when the message was the… | boolean |
curl -X POST "$SANDBOX/agent/queue/remove" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","id":"a1b2c3d4","revision":0}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.queueRemove({
"conversationId": "nightly-changelog",
"id": "a1b2c3d4",
"revision": 0
});POST/agent/queue/resumeLet waiting messages go
Releases a queue held after a stop or a refusal: what waits goes out now as one turn when nothing is running, or after the running turn otherwise. Name who serves that turn when the conversation has been re-pointed since the messages were queued. Name messages by id to let only those go (a scheduled one now, ahead of its time), leaving every other booking on its time.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhose queue to let go | string | body |
routingWho serves the turn the waiting… | object | body |
agentrequiredWhich provider serves the re-run | string | body |
harnessrequiredWhich agentic loop runs it | "native" | "claude-code" | "codex" | "opencode" … (7) | body |
accountWhich of that provider's accounts pays… | string | body |
modelWhich model | string | body |
effortHow hard the model should think… | string | body |
carryWhen the account changes, keep the… | boolean | body |
handoffHow a turn a spent allowance… | "carry" | "trim" | "summary" | body |
idsWhich waiting messages to let go:… | string[] | body |
What comes back
| Field | Type |
|---|---|
runThe turn the waiting messages started | string |
queueThe queue the release left: what… | object |
itemsWhat waits, in the order it… | object[] |
idThe message's id: what its sender… | string |
textThe words, as they will go… | string |
attachmentsFiles that go with it, as… | string[] |
voiceWho it is from: a person,… | "person" | "sandbox" | "agent" |
queuedAtWhen it joined the queue, in… | number |
revisionThe queue's revision when this message… | integer |
untilWhen this message goes out by… | number |
afterThe conversation whose finished work must… | string |
reopenOfThe allowance this message's `until` waits… | object |
agentThe provider whose allowance it waits… | string |
accountWhich of its accounts | string |
servesWho serves the turn this message… | object |
agentThe provider | string |
harnessThe agentic loop | "native" | "claude-code" | "codex" | "opencode" … (7) |
modelThe model | string |
effortHow hard it thinks, where the… | string |
accountThe account that pays for it | string |
continuesA continuation, not words: when it… | true |
revisionMoves with every change to the… | integer |
pausedWhy the messages with no booking… | "stopped" | "refused" | "scheduled" |
untilThe soonest booked message's time, in… | number |
afterThe conversation the first booked message… | string |
reasonWhy nothing went out though messages… | string |
curl -X POST "$SANDBOX/agent/queue/resume" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","routing":{"agent":"…","harness":"native","account":"work","model":"claude-sonnet-4-6","effort":"…","carry":true,"handoff":"carry"},"ids":["a1b2c3d4","e5f6a7b8"]}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.queueResume({
"conversationId": "nightly-changelog",
"routing": {
"agent": "…",
"harness": "native",
"account": "work",
"model": "claude-sonnet-4-6",
"effort": "…",
"carry": true,
"handoff": "carry"
},
"ids": [
"a1b2c3d4",
"e5f6a7b8"
]
});POST/agent/queue/rerouteMove waiting messages to another model
Points the person's messages waiting in the conversation's queue at another provider, loop, model or account, without letting them go: held ones stay held and booked ones keep their time, and when they go they go there. What a pick in the model picker does to words already waiting, which otherwise go out on the pick they were sent under. The sandbox's and an agent's own messages always go wherever the conversation runs, and are left alone.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhose queue | string | body |
routingrequiredWho serves the turn each message… | object | body |
agentrequiredWhich provider serves the re-run | string | body |
harnessrequiredWhich agentic loop runs it | "native" | "claude-code" | "codex" | "opencode" … (7) | body |
accountWhich of that provider's accounts pays… | string | body |
modelWhich model | string | body |
effortHow hard the model should think… | string | body |
carryWhen the account changes, keep the… | boolean | body |
handoffHow a turn a spent allowance… | "carry" | "trim" | "summary" | body |
idsWhich waiting messages to move | string[] | body |
What comes back
| Field | Type |
|---|---|
itemsWhat waits, in the order it… | object[] |
idThe message's id: what its sender… | string |
textThe words, as they will go… | string |
attachmentsFiles that go with it, as… | string[] |
voiceWho it is from: a person,… | "person" | "sandbox" | "agent" |
queuedAtWhen it joined the queue, in… | number |
revisionThe queue's revision when this message… | integer |
untilWhen this message goes out by… | number |
afterThe conversation whose finished work must… | string |
reopenOfThe allowance this message's `until` waits… | object |
agentThe provider whose allowance it waits… | string |
accountWhich of its accounts | string |
servesWho serves the turn this message… | object |
agentThe provider | string |
harnessThe agentic loop | "native" | "claude-code" | "codex" | "opencode" … (7) |
modelThe model | string |
effortHow hard it thinks, where the… | string |
accountThe account that pays for it | string |
continuesA continuation, not words: when it… | true |
revisionMoves with every change to the… | integer |
pausedWhy the messages with no booking… | "stopped" | "refused" | "scheduled" |
untilThe soonest booked message's time, in… | number |
afterThe conversation the first booked message… | string |
curl -X POST "$SANDBOX/agent/queue/reroute" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","routing":{"agent":"…","harness":"native","account":"work","model":"claude-sonnet-4-6","effort":"…","carry":true,"handoff":"carry"},"ids":["a1b2c3d4","e5f6a7b8"]}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.queueReroute({
"conversationId": "nightly-changelog",
"routing": {
"agent": "…",
"harness": "native",
"account": "work",
"model": "claude-sonnet-4-6",
"effort": "…",
"carry": true,
"handoff": "carry"
},
"ids": [
"a1b2c3d4",
"e5f6a7b8"
]
});POST/agent/queue/scheduleReschedule waiting messages
Books what waits in the conversation's queue to go out by itself at another instant, or once another conversation has finished and its work has landed, holding it until then. Works on a queue that is held for any reason, or on messages waiting behind a running turn. Name messages by id to re-time only those; every other keeps its own booking. A time already past, or a conversation with nothing left to land, lets them go now.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhose queue | string | body |
sendAtSend what waits at this instant… | integer | body |
sendAfterSend what waits once that conversation… | string | body |
sendAtReopenSays `sendAt` is the reopen of… | true | body |
idsWhich waiting messages to re-time; every… | string[] | body |
What comes back
| Field | Type |
|---|---|
itemsWhat waits, in the order it… | object[] |
idThe message's id: what its sender… | string |
textThe words, as they will go… | string |
attachmentsFiles that go with it, as… | string[] |
voiceWho it is from: a person,… | "person" | "sandbox" | "agent" |
queuedAtWhen it joined the queue, in… | number |
revisionThe queue's revision when this message… | integer |
untilWhen this message goes out by… | number |
afterThe conversation whose finished work must… | string |
reopenOfThe allowance this message's `until` waits… | object |
agentThe provider whose allowance it waits… | string |
accountWhich of its accounts | string |
servesWho serves the turn this message… | object |
agentThe provider | string |
harnessThe agentic loop | "native" | "claude-code" | "codex" | "opencode" … (7) |
modelThe model | string |
effortHow hard it thinks, where the… | string |
accountThe account that pays for it | string |
continuesA continuation, not words: when it… | true |
revisionMoves with every change to the… | integer |
pausedWhy the messages with no booking… | "stopped" | "refused" | "scheduled" |
untilThe soonest booked message's time, in… | number |
afterThe conversation the first booked message… | string |
curl -X POST "$SANDBOX/agent/queue/schedule" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","sendAt":1,"sendAfter":"…","sendAtReopen":true,"ids":["a1b2c3d4","e5f6a7b8"]}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.queueSchedule({
"conversationId": "nightly-changelog",
"sendAt": 1,
"sendAfter": "…",
"sendAtReopen": true,
"ids": [
"a1b2c3d4",
"e5f6a7b8"
]
});POST/agent/queue/continueBook a Continue for later
Books the conversation to carry on from where its last turn stopped at an instant, or once another conversation has finished and its work has landed: a Continue that waits in the queue, drawn as scheduled, rather than words. Nothing is added to the conversation as your message. When it goes, a turn the sandbox still holds runs again as it was; otherwise the agent is told to continue in its own session. A turn that starts in the conversation before then makes it moot, and it is dropped. Take it back with queueRemove, send it sooner with queueResume, re-time it with queueSchedule.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich conversation carries on | string | body |
sendAtCarry on at this instant (epoch… | integer | body |
sendAfterCarry on once that conversation has… | string | body |
sendAtReopenSays `sendAt` is the reopen of… | true | body |
routingWho serves the turn it starts | object | body |
agentrequiredWhich provider serves the re-run | string | body |
harnessrequiredWhich agentic loop runs it | "native" | "claude-code" | "codex" | "opencode" … (7) | body |
accountWhich of that provider's accounts pays… | string | body |
modelWhich model | string | body |
effortHow hard the model should think… | string | body |
carryWhen the account changes, keep the… | boolean | body |
handoffHow a turn a spent allowance… | "carry" | "trim" | "summary" | body |
messageIdNames the booking, so the same… | string | body |
What comes back
| Field | Type |
|---|---|
itemsWhat waits, in the order it… | object[] |
idThe message's id: what its sender… | string |
textThe words, as they will go… | string |
attachmentsFiles that go with it, as… | string[] |
voiceWho it is from: a person,… | "person" | "sandbox" | "agent" |
queuedAtWhen it joined the queue, in… | number |
revisionThe queue's revision when this message… | integer |
untilWhen this message goes out by… | number |
afterThe conversation whose finished work must… | string |
reopenOfThe allowance this message's `until` waits… | object |
agentThe provider whose allowance it waits… | string |
accountWhich of its accounts | string |
servesWho serves the turn this message… | object |
agentThe provider | string |
harnessThe agentic loop | "native" | "claude-code" | "codex" | "opencode" … (7) |
modelThe model | string |
effortHow hard it thinks, where the… | string |
accountThe account that pays for it | string |
continuesA continuation, not words: when it… | true |
revisionMoves with every change to the… | integer |
pausedWhy the messages with no booking… | "stopped" | "refused" | "scheduled" |
untilThe soonest booked message's time, in… | number |
afterThe conversation the first booked message… | string |
curl -X POST "$SANDBOX/agent/queue/continue" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","sendAt":1,"sendAfter":"…","sendAtReopen":true,"routing":{"agent":"…","harness":"native","account":"work","model":"claude-sonnet-4-6","effort":"…","carry":true,"handoff":"carry"},"messageId":"a1b2c3d4"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.queueContinue({
"conversationId": "nightly-changelog",
"sendAt": 1,
"sendAfter": "…",
"sendAtReopen": true,
"routing": {
"agent": "…",
"harness": "native",
"account": "work",
"model": "claude-sonnet-4-6",
"effort": "…",
"carry": true,
"handoff": "carry"
},
"messageId": "a1b2c3d4"
});POST/agent/resumeRun a refused turn again
Sends the same turn again when the model provider's allowance refused it, with everything it originally carried except who serves it: the caller may name a different provider, harness or account, which is the usual answer to a spent allowance. It repeats the request rather than adding a new message to the conversation, so pressing it twice costs nothing and the agent is never told to continue work it has not started.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich conversation's held turn to run… | string | body |
routingWho serves the re-run, when the… | object | body |
agentrequiredWhich provider serves the re-run | string | body |
harnessrequiredWhich agentic loop runs it | "native" | "claude-code" | "codex" | "opencode" … (7) | body |
accountWhich of that provider's accounts pays… | string | body |
modelWhich model | string | body |
effortHow hard the model should think… | string | body |
carryWhen the account changes, keep the… | boolean | body |
handoffHow a turn a spent allowance… | "carry" | "trim" | "summary" | body |
What comes back
| Field | Type |
|---|---|
runThe id of the run that… | string |
curl -X POST "$SANDBOX/agent/resume" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","routing":{"agent":"…","harness":"native","account":"work","model":"claude-sonnet-4-6","effort":"…","carry":true,"handoff":"carry"}}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.resume({
"conversationId": "nightly-changelog",
"routing": {
"agent": "…",
"harness": "native",
"account": "work",
"model": "claude-sonnet-4-6",
"effort": "…",
"carry": true,
"handoff": "carry"
}
});POST/agent/accountMove a conversation to another account
Points the conversation at another connected account of the provider it runs on, for every turn from now on. It starts nothing by itself: with `run`, a turn held by a spent allowance or a stop runs again at once on that account, which is how a refused turn continues elsewhere. Without `carry` the next turn opens a fresh session seeded from the record.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich conversation to move | string | body |
accountrequiredWhich of the conversation's provider's connected… | string | body |
carryKeep the provider session across the… | boolean | body |
handoffHow the held turn continues the… | "carry" | "trim" | "summary" | body |
runAlso run a turn that a… | boolean | body |
What comes back
| Field | Type |
|---|---|
runThe run that re-ran a held… | string |
curl -X POST "$SANDBOX/agent/account" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","account":"work","carry":true,"handoff":"carry","run":true}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.switchAccount({
"conversationId": "nightly-changelog",
"account": "work",
"carry": true,
"handoff": "carry",
"run": true
});POST/agent/handoffChoose how a held turn continues
Records how the turn a spent allowance is holding continues the conversation once it is sent again: carry the session as it is, trim it, or summarise it. Starts nothing: a press, a booked move or the reset sends it, and each uses this pick.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich conversation's held turn | string | body |
handoffrequiredHow the next send of the… | "carry" | "trim" | "summary" | body |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X POST "$SANDBOX/agent/handoff" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","handoff":"carry"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.chooseHandoff({
"conversationId": "nightly-changelog",
"handoff": "carry"
});POST/agent/rewindGo back to an earlier message
Puts the files back as they stood at that point, drops every message after it, and forgets what the model remembered, so the next thing you say starts from there cleanly. Refused while a turn is running, because a restore cannot overwrite files an agent is editing; refused for a message with no saved state to return to; and refused when that position no longer holds the message you named, because the conversation moved since you read it.
What you send
| Field | Type | Where |
|---|---|---|
conversationIdrequiredWhich conversation to rewind | string | body |
indexrequiredWhich message to go back to,… | integer | body |
messageIdrequiredThe id of the message at… | string | body |
What comes back
| Field | Type |
|---|---|
snapshotThe saved point the files were… | string |
droppedHow many messages were removed | integer |
curl -X POST "$SANDBOX/agent/rewind" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"conversationId":"nightly-changelog","index":0,"messageId":"a1b2c3d4"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.rewind({
"conversationId": "nightly-changelog",
"index": 0,
"messageId": "a1b2c3d4"
});GET/agent/commandsShortcut commands the agent knows
The commands a provider published the last time one of its turns ran, so a composer can offer them before this conversation has run anything. A running turn's own list wins over this one.
What you send
| Field | Type | Where |
|---|---|---|
agentWhose commands to read | string | query |
What comes back
| Field | Type |
|---|---|
commandsThe shortcut commands, as the provider… | object[] |
nameWhat to type, without the leading… | string |
descriptionWhat it does | string |
hintWhat its argument should look like,… | string |
curl "$SANDBOX/agent/commands" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.commands();POST/agent/route-chatChoose what a new chat opens on
Reads a new chat's opening message once and answers whichever of two questions it still has: the model, effort and account that conversation should run on, from what is connected and still has allowance left, and which of this sandbox's personas should handle it. `model` and `persona` on the ask say which halves to answer, and only those are put to the model. Asked once per chat, on the message actually sent, and never again: every turn after it runs on what the chat is wearing, which you are free to change. Answers with nothing, and a reason, whenever it cannot choose — a chat is never held up by this.
What you send
| Field | Type | Where |
|---|---|---|
promptrequiredThe message a new chat is… | string | body |
pathsWorkspace paths the message names: uploads,… | string[] | body |
folderThe workspace folder the chat was… | string | body |
editorContextWhether the message carries a file… | boolean | body |
planModeWhether the chat opens in plan… | boolean | body |
modelrequiredWhether to choose the model, effort… | boolean | body |
personarequiredWhether to choose the persona: true… | boolean | body |
What comes back
| Field | Type |
|---|---|
personaThe persona half's answer, present only… | object |
idThe persona this message belongs to,… | string |
reasonWhy, in the one clause a… | string |
modelThe model half's answer, present only… | object |
pickWhat the conversation should run on,… | object |
providerWhich provider serves the conversation | string |
modelWhich of its models | string |
effortHow hard it should think, where… | string |
accountWhich connected account pays, by its… | string |
reasonWhy, in the one clause a… | string |
judgeWhich model answered, as `provider:model`, so… | string |
curl -X POST "$SANDBOX/agent/route-chat" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"prompt":"Update the changelog for the last five commits.","paths":["src/app.ts","README.md"],"folder":"…","editorContext":true,"planMode":true,"model":true,"persona":true}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.routeChat({
"prompt": "Update the changelog for the last five commits.",
"paths": [
"src/app.ts",
"README.md"
],
"folder": "…",
"editorContext": true,
"planMode": true,
"model": true,
"persona": true
});GET/agent/refusalsThe last time each provider said no
What each model provider most recently refused and why. Read this alongside an account's usage: the usage says how full it was when last checked, this says whether it has since started turning work away.
What you send
Nothing. Call it as it is.
What comes back
| Field | Type |
|---|---|
refusalsEvery refusal on file per provider,… | object |
curl "$SANDBOX/agent/refusals" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.agent.refusals();