---
title: "One agent · intentic sandbox API"
description: "Run a turn in one conversation, then attach to it, answer it, steer it or stop it. Every route in the one agent group of the intentic sandbox API."
url: "https://intentic.dev/api/agent/"
---

Agents

# One agent

Run a turn in one conversation, then attach to it, answer it, steer it or stop it

**On this page (15 sections)**

- [Say something to an agent](#agent-run)
- [Watch a turn happen](#agent-attach)
- [Answer a question the agent asked](#agent-reply)
- [Interrupt a running turn](#agent-steer)
- [Stop a turn now](#agent-stop)
- [Reword a waiting message](#agent-queueEdit)
- [Take back a waiting message](#agent-queueRemove)
- [Let waiting messages go](#agent-queueResume)
- [Reschedule waiting messages](#agent-queueSchedule)
- [Run a refused turn again](#agent-resume)
- [Move a conversation to another account](#agent-switchAccount)
- [Go back to an earlier message](#agent-rewind)
- [Shortcut commands the agent knows](#agent-commands)
- [Choose what a new chat opens on](#agent-routeChat)
- [The last time each provider said no](#agent-refusals)

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.

15 calls. Pick one to open it, or use the list on the right.

**POST`/agent` Say 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 |
| --- | --- | --- |
| `prompt` required What to say to the agent | string | body |
| `errand` What the words are for, when… | "land-conflict" | "verify-nudge" | "land-breakage" | "land-fix" … (10) | body |
| `messageId` Your id for this message | string | body |
| `title` A title for a conversation this… | string | body |
| `attachments` Files to hand the agent along… | string[] | body |
| `mentions` Workspace paths the prompt mentions with… | string[] | body |
| `agent` Which model provider serves this turn | string | body |
| `harness` Which agentic loop runs the turn | "native" | "claude-code" | body |
| `account` Which of that provider's connected accounts… | string | body |
| `actsAs` Which persona the turn speaks as… | string | body |
| `sessionId` Resume this provider session instead of… | string | body |
| `conversationId` The conversation this turn belongs to | string | body |
| `isolated` Work in this conversation's own private… | boolean | body |
| `startIn` Which folder the conversation opens in,… | string | body |
| `placement` Where this conversation runs: this sandbox… | object | body |
| `when kind is "local"` | shape | body |
| `when kind is "runner"` | shape | body |
| `id` required | string | body |
| `worktreeBase` Pin a new private copy to… | object[] | body |
| `repo` required | string | body |
| `base` required | string | body |
| `autoLand` Whether this turn's work merges into… | boolean | body |
| `runRole` What started this turn, when it… | "commit-message" | "session-title" | "safety-judge" | "loop-verdict" … (13) | body |
| `origin` Set by the sandbox alone: this… | object | body |
| `automationId` required | string | body |
| `provider` required | string | body |
| `channelId` | string | body |
| `author` | string | body |
| `forkOf` Where this conversation was cut from,… | object | body |
| `conversationId` required The conversation this one was cut… | string | body |
| `keep` required How many of that conversation's messages… | integer | body |
| `files` required Which files the fork opens on:… | "then" | "now" | body |
| `model` Which model to use | string | body |
| `unattended` Nobody is watching this turn: a… | boolean | body |
| `outsideWake` Content from outside caused this turn,… | string | body |
| `permissionMode` How tool calls are gated: ask… | "default" | "plan" | "bypassPermissions" | body |
| `allowedTools` Narrow the turn to these tools | string[] | body |
| `effort` How hard the model should think,… | string | body |
| `thinking` Whether to show the model's reasoning… | boolean | body |
| `fast` Ask for the same work at… | boolean | body |
| `autoPicked` Whether this turn's model was chosen… | boolean | body |
| `editorContext` What the user has open in… | object | body |
| `file` required The file open in the editor,… | string | body |
| `startLine` First line of the selection, counting… | integer | body |
| `endLine` Last line of the selection, counting… | integer | body |
| `selection` The selected text itself | string | body |
| `sendAt` Hold this message until then (epoch… | integer | body |
| `sendAfter` Hold this message until the conversation… | string | body |
| `conversationAutoLand` Whether this conversation's finished work merges… | boolean | body |
| `continues` Carry the conversation on from where… | true | body |

### What comes back

| Field | Type |
| --- | --- |
| `delivered` What became of the message: it… | "started" | "steered" | "queued" |
| `run` The run the message is in:… | string |
| `duplicate` The sandbox had already taken a… | true |

Try it answered in this tab

curl

```bash
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","author":"Ada Lovelace"},"forkOf":{"conversationId":"nightly-changelog","keep":0,"files":"then"},"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,"sendAfter":"…","conversationAutoLand":true,"continues":true}'
```

TypeScript

```typescript
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",
 "author": "Ada Lovelace"
 },
 "forkOf": {
 "conversationId": "nightly-changelog",
 "keep": 0,
 "files": "then"
 },
 "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,
 "sendAfter": "…",
 "conversationAutoLand": true,
 "continues": true
});
```

**POST`/agent/attach` Watch a turn happen stream**

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 |
| --- | --- | --- |
| `conversationId` required Which conversation to watch | string | body |
| `run` The run you were watching | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `when event is "message"` | shape |
| `data` | object |
| `when kind is "attached"` | shape |
| `run` The run's id | string |
| `startedAt` When it started, in milliseconds, so… | number |
| `seq` How many frames the run has… | number |
| `rows` The turn's rows as they stand:… | object[] |
| `when kind is "patch"` | shape |
| `seq` Its position in the run, counting… | number |
| `patch` | object |
| `when kind is "fact"` | shape |
| `seq` Its 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 |

Try it answered in this tab

curl

```bash
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"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.attach({
 "conversationId": "nightly-changelog",
 "run": "run_8c2f41d9"
});
```

**POST`/agent/reply` Answer 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 |
| `requestId` required Which card you are answering, from… | string | body |
| `approve` required Whether to go ahead | boolean | body |
| `feedback` Why not, which goes back to… | string | body |
| `when kind is "question"` | shape | body |
| `requestId` required Which card you are answering | string | body |
| `answers` What you chose, keyed by the… | object | body |
| `attachments` Files that go with your own-words… | object | body |
| `cancelled` Dismissing it instead, which tells the… | boolean | body |
| `when kind is "permission"` | shape | body |
| `requestId` required Which card you are answering | string | body |
| `decision` required Once allows this call alone; always… | "once" | "always" | "everything" | "deny" | body |
| `feedback` Why not, which goes back to… | string | body |
| `child` For a request to start a… | object | body |
| `provider` required Which provider serves it | string | body |
| `model` required Which of that provider's models | string | body |
| `harness` Which agentic loop runs it | "native" | "claude-code" | body |
| `account` Which of that provider's connected accounts… | string | body |
| `effort` How hard it thinks, where the… | string | body |
| `thinking` Whether it reasons before it answers,… | boolean | body |
| `fast` Whether it asks for the faster… | boolean | body |
| `when kind is "browser_help"` | shape | body |
| `requestId` required Which card you are answering | string | body |
| `helped` required Whether you cleared it | boolean | body |
| `note` Anything the agent should know, which… | string | body |
| `when kind is "terminal_help"` | shape | body |
| `requestId` required Which card you are answering | string | body |
| `helped` required Whether you did it | boolean | body |
| `note` Anything the agent should know, which… | string | body |
| `when kind is "capability_offer"` | shape | body |
| `requestId` required Which card you are answering | string | body |
| `connect` required Yes keeps the agent waiting while… | boolean | body |
| `when kind is "payment_offer"` | shape | body |
| `requestId` required Which card you are answering | string | body |
| `approve` required Yes releases exactly one payment | boolean | body |
| `when kind is "credential_offer"` | shape | body |
| `requestId` required Which card you are answering | string | body |
| `approve` required Yes releases it, as far as… | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
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":"…"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.reply({
 "kind": "plan",
 "requestId": "a1b2c3d4",
 "approve": true,
 "feedback": "…"
});
```

**POST`/agent/steer` Interrupt 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 |
| --- | --- | --- |
| `conversationId` required Which running conversation to interrupt | string | body |
| `text` required What to say to it | string | body |
| `messageId` Your id for this message | string | body |
| `attachments` Files to send with it, as… | string[] | body |
| `mentions` Workspace paths the message mentions with… | string[] | body |
| `editorContext` What you have open, folded in… | object | body |
| `file` required The file open in the editor,… | string | body |
| `startLine` First line of the selection, counting… | integer | body |
| `endLine` Last line of the selection, counting… | integer | body |
| `selection` The selected text itself | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `delivered` What became of the message: it… | "started" | "steered" | "queued" |
| `run` The run the message is in:… | string |
| `duplicate` The sandbox had already taken a… | true |

Try it answered in this tab

curl

```bash
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":"…"}}'
```

TypeScript

```typescript
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/stop` Stop 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 |
| --- | --- | --- |
| `conversationId` required Which conversation's running turn to cancel | string | body |
| `run` required The run you mean to cancel,… | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `stopped` Whether a turn was cancelled | boolean |
| `running` The run that is live instead… | string |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/agent/stop" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"conversationId":"nightly-changelog","run":"run_8c2f41d9"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.stop({
 "conversationId": "nightly-changelog",
 "run": "run_8c2f41d9"
});
```

**POST`/agent/queue/edit` Reword 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 |
| --- | --- | --- |
| `conversationId` required Whose queue | string | body |
| `id` required Which waiting message | string | body |
| `revision` required The message's revision as you read… | integer | body |
| `text` required What the message should say instead | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `items` What waits, in the order it… | object[] |
| `id` The message's id: what its sender… | string |
| `text` The words, as they will go… | string |
| `attachments` Files that go with it, as… | string[] |
| `voice` Who it is from: a person,… | "person" | "sandbox" | "agent" |
| `queuedAt` When it joined the queue, in… | number |
| `revision` The queue's revision when this message… | integer |
| `revision` Moves with every change to the… | integer |
| `paused` Why nothing goes out by itself:… | "stopped" | "refused" | "scheduled" |
| `until` When scheduled messages go out by… | number |
| `after` The conversation whose finished work must… | string |

Try it answered in this tab

curl

```bash
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"}'
```

TypeScript

```typescript
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/remove` Take 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.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `conversationId` required Whose queue | string | body |
| `id` required Which waiting message | string | body |
| `revision` required The message's revision as you read… | integer | body |

### What comes back

| Field | Type |
| --- | --- |
| `items` What waits, in the order it… | object[] |
| `id` The message's id: what its sender… | string |
| `text` The words, as they will go… | string |
| `attachments` Files that go with it, as… | string[] |
| `voice` Who it is from: a person,… | "person" | "sandbox" | "agent" |
| `queuedAt` When it joined the queue, in… | number |
| `revision` The queue's revision when this message… | integer |
| `revision` Moves with every change to the… | integer |
| `paused` Why nothing goes out by itself:… | "stopped" | "refused" | "scheduled" |
| `until` When scheduled messages go out by… | number |
| `after` The conversation whose finished work must… | string |

Try it answered in this tab

curl

```bash
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}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.queueRemove({
 "conversationId": "nightly-changelog",
 "id": "a1b2c3d4",
 "revision": 0
});
```

**POST`/agent/queue/resume` Let 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.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `conversationId` required Whose queue to let go | string | body |
| `routing` Who serves the turn the waiting… | object | body |
| `agent` required Which provider serves the re-run | string | body |
| `harness` required Which agentic loop runs it | "native" | "claude-code" | body |
| `account` Which of that provider's accounts pays… | string | body |
| `model` Which model | string | body |
| `carry` When the account changes, keep the… | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `run` The turn the waiting messages started | string |
| `queue` The queue the release left: what… | object |
| `items` What waits, in the order it… | object[] |
| `id` The message's id: what its sender… | string |
| `text` The words, as they will go… | string |
| `attachments` Files that go with it, as… | string[] |
| `voice` Who it is from: a person,… | "person" | "sandbox" | "agent" |
| `queuedAt` When it joined the queue, in… | number |
| `revision` The queue's revision when this message… | integer |
| `revision` Moves with every change to the… | integer |
| `paused` Why nothing goes out by itself:… | "stopped" | "refused" | "scheduled" |
| `until` When scheduled messages go out by… | number |
| `after` The conversation whose finished work must… | string |

Try it answered in this tab

curl

```bash
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","carry":true}}'
```

TypeScript

```typescript
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",
 "carry": true
 }
});
```

**POST`/agent/queue/schedule` Reschedule 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. A time already past, or a conversation with nothing left to land, lets them go now.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `conversationId` required Whose queue | string | body |
| `sendAt` Send what waits at this instant… | integer | body |
| `sendAfter` Send what waits once that conversation… | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `items` What waits, in the order it… | object[] |
| `id` The message's id: what its sender… | string |
| `text` The words, as they will go… | string |
| `attachments` Files that go with it, as… | string[] |
| `voice` Who it is from: a person,… | "person" | "sandbox" | "agent" |
| `queuedAt` When it joined the queue, in… | number |
| `revision` The queue's revision when this message… | integer |
| `revision` Moves with every change to the… | integer |
| `paused` Why nothing goes out by itself:… | "stopped" | "refused" | "scheduled" |
| `until` When scheduled messages go out by… | number |
| `after` The conversation whose finished work must… | string |

Try it answered in this tab

curl

```bash
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":"…"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.queueSchedule({
 "conversationId": "nightly-changelog",
 "sendAt": 1,
 "sendAfter": "…"
});
```

**POST`/agent/resume` Run 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 |
| --- | --- | --- |
| `conversationId` required Which conversation's held turn to run… | string | body |
| `routing` Who serves the re-run, when the… | object | body |
| `agent` required Which provider serves the re-run | string | body |
| `harness` required Which agentic loop runs it | "native" | "claude-code" | body |
| `account` Which of that provider's accounts pays… | string | body |
| `model` Which model | string | body |
| `carry` When the account changes, keep the… | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `run` The id of the run that… | string |

Try it answered in this tab

curl

```bash
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","carry":true}}'
```

TypeScript

```typescript
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",
 "carry": true
 }
});
```

**POST`/agent/account` Move 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 |
| --- | --- | --- |
| `conversationId` required Which conversation to move | string | body |
| `account` required Which of the conversation's provider's connected… | string | body |
| `carry` Keep the provider session across the… | boolean | body |
| `run` Also run a turn that a… | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `run` The run that re-ran a held… | string |

Try it answered in this tab

curl

```bash
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,"run":true}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.switchAccount({
 "conversationId": "nightly-changelog",
 "account": "work",
 "carry": true,
 "run": true
});
```

**POST`/agent/rewind` Go 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 |
| --- | --- | --- |
| `conversationId` required Which conversation to rewind | string | body |
| `index` required Which message to go back to,… | integer | body |
| `messageId` required The id of the message at… | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `snapshot` The saved point the files were… | string |
| `dropped` How many messages were removed | integer |

Try it answered in this tab

curl

```bash
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"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.rewind({
 "conversationId": "nightly-changelog",
 "index": 0,
 "messageId": "a1b2c3d4"
});
```

**GET`/agent/commands` Shortcut 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 |
| --- | --- | --- |
| `agent` Whose commands to read | string | query |

### What comes back

| Field | Type |
| --- | --- |
| `commands` The shortcut commands, as the provider… | object[] |
| `name` What to type, without the leading… | string |
| `description` What it does | string |
| `hint` What its argument should look like,… | string |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/agent/commands" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.commands();
```

**POST`/agent/route-chat` Choose 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 |
| --- | --- | --- |
| `prompt` required The message a new chat is… | string | body |
| `paths` Workspace paths the message names: uploads,… | string[] | body |
| `folder` The workspace folder the chat was… | string | body |
| `editorContext` Whether the message carries a file… | boolean | body |
| `planMode` Whether the chat opens in plan… | boolean | body |
| `model` required Whether to choose the model, effort… | boolean | body |
| `persona` required Whether to choose the persona: true… | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `persona` The persona half's answer, present only… | object |
| `id` The persona this message belongs to,… | string |
| `reason` Why, in the one clause a… | string |
| `model` The model half's answer, present only… | object |
| `pick` What the conversation should run on,… | object |
| `provider` Which provider serves the conversation | string |
| `model` Which of its models | string |
| `effort` How hard it should think, where… | string |
| `account` Which connected account pays, by its… | string |
| `reason` Why, in the one clause a… | string |
| `judge` Which model answered, as `provider:model`, so… | string |

Try it answered in this tab

curl

```bash
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}'
```

TypeScript

```typescript
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/refusals` The 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 |
| --- | --- |
| `refusals` The most recent refusal per provider | object |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/agent/refusals" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.agent.refusals();
```

More in Agents

[Next The fleet →](https://intentic.dev/api/agents/)
