> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Digital agent scripts: branching step graphs for live chat and messaging conversations

> Author guided, branching step graphs your agents walk during live digital conversations — create, read back, version, and roll out an agent script from the Inbox settings page or the /inbox/agent-scripts API.

# Digital agent scripts: branching step graphs

An agent script is a small, directed **step graph** the agent console walks during a live digital conversation — chat, email, or messaging. The console opens on the script's start step, shows the agent what to say or do, and follows whichever branch option matches the customer's answer. The agent never has to remember the flow; the next question is always on screen.

Set that against the two tools your agents already have:

* **Macros** are static: a prewritten reply, inserted as-is. Nothing reacts to what the customer said.
* **AI reply suggestions** are generative: a drafted reply, not a process — the AI has no idea which question must come after the answer.

A script is the third kind: a *process* the agent can follow on a regulated or multi-branch flow — a refund, a cancellation, an eligibility check — where the right next step depends on the customer's answer.

## Where it lives

Open **Inbox → Settings → Agent scripts**. The page is restricted to owners and admins — writes to the API require an owner or admin key too. Reads are open to every teammate, so the agent console can fetch the graph while a conversation is live.

The settings tiles on **Inbox → Settings** sit next to Macros and Routing; Agent scripts is the tile with the branching icon.

## The API surface

Five endpoints, all under the `/api/v1/inbox` base path:

| Method   | Path                       | Purpose                                                 |
| -------- | -------------------------- | ------------------------------------------------------- |
| `GET`    | `/inbox/agent-scripts`     | List every script (any authenticated caller).           |
| `POST`   | `/inbox/agent-scripts`     | Create a script (owner/admin).                          |
| `GET`    | `/inbox/agent-scripts/:id` | One script with its full step graph.                    |
| `PATCH`  | `/inbox/agent-scripts/:id` | Update; `steps` fully replaces the graph (owner/admin). |
| `DELETE` | `/inbox/agent-scripts/:id` | Remove a script permanently (owner/admin).              |

Scripts are stored per workspace as a JSONB array on your organization settings — there is nothing to provision and no table to migrate; a saved script is readable by the console immediately. The wire shape is snake case (`step_id`, `next_step_id`, `start_step_id`); the sections below build that shape by hand.

## Author your first script

You author three things:

1. **Steps.** Each step has a `step_id`, a `kind` (`prompt`, `question`, `note`, or `disposition`), an optional `title`, and a `body` — what the agent reads, asks, or does.
2. **Branch options.** On any step, an `options` array — each option is a `label` (the answer the agent picks) and a `next_step_id` (the step it advances to). A `null` next step ends the flow.
3. **A start step.** `start_step_id` picks where the console opens; omit it and the flow starts at the first step.

One more authoring habit: give every flow an **explicit fallback**. Customers rarely answer in your option labels, so end each branch of questions with an escape option ("None of these", "Customer won't say") that lands on a note or disposition step instead of a dead end.

### Worked example — a three-branch refund intake

The agent asks for the customer's name, then the order ID, then routes to ship-back, replacement, or a fallback. Rendered tree:

```
[start] s-name (question: customer name verified?)
   ├─ "Name verified" → s-order (question: order ID?)
   └─ "No match" → s-fallback (note: verify by email instead)
s-order:
   ├─ "Wants a refund" → s-shipback (prompt: send the return label)
   ├─ "Wants a replacement" → s-replace (prompt: confirm the address)
   └─ "Undecided" → s-fallback
s-shipback / s-replace → s-done (disposition: resolve and tag)
```

Create it with a single POST:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/inbox/agent-scripts" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Refund intake",
    "description": "Name, order ID, then ship-back vs replacement.",
    "channels": ["web_chat", "whatsapp"],
    "enabled": true,
    "start_step_id": "s-name",
    "steps": [
      {
        "step_id": "s-name",
        "kind": "question",
        "title": "Verify the name",
        "body": "Ask for the full name on the order and confirm it matches the thread.",
        "options": [
          { "label": "Name verified", "next_step_id": "s-order" },
          { "label": "No match", "next_step_id": "s-fallback" }
        ]
      },
      {
        "step_id": "s-order",
        "kind": "question",
        "title": "Order ID and outcome",
        "body": "Ask for the order ID, then whether they want a refund or a replacement.",
        "options": [
          { "label": "Wants a refund", "next_step_id": "s-shipback" },
          { "label": "Wants a replacement", "next_step_id": "s-replace" },
          { "label": "Undecided", "next_step_id": "s-fallback" }
        ]
      },
      {
        "step_id": "s-shipback",
        "kind": "prompt",
        "title": "Send the return label",
        "body": "Send the prepaid return label and summarize the refund timeline.",
        "options": [
          { "label": "Label sent", "next_step_id": "s-done" }
        ]
      },
      {
        "step_id": "s-replace",
        "kind": "prompt",
        "title": "Confirm the address",
        "body": "Read back the shipping address and confirm it before placing the replacement.",
        "options": [
          { "label": "Address confirmed", "next_step_id": "s-done" }
        ]
      },
      {
        "step_id": "s-fallback",
        "kind": "note",
        "title": "Fallback",
        "body": "Internal: do not guess. Verify the customer by email, then restart from the order-ID question.",
        "options": [
          { "label": "Verified — restart", "next_step_id": "s-order" }
        ]
      },
      {
        "step_id": "s-done",
        "kind": "disposition",
        "title": "Resolve",
        "body": "Resolve the conversation and tag it refund-shipback or refund-replace."
      }
    ]
  }'
```

Before anything is saved, the graph is checked: every `step_id` unique, every `next_step_id` resolving to a real step, and `start_step_id` resolving too. A broken graph returns `422 INVALID_SCRIPT_GRAPH` with the reason and persists nothing.

## Read it back while a conversation is live

After you save — from the dashboard editor or the POST above — the script is immediately readable:

1. Save the script with **Active** on (the `enabled` flag).
2. Open any live conversation on a channel the script targets (or any channel, if you left `channels` empty).
3. Open the script panel in the agent console and pick the script from the picker.

The console walks the graph one step at a time: the current step's title and body on top, the branch options as clickable choices on a `question` step, and an explicit end on a `disposition` step. Because reads are open to every teammate, an agent never needs admin rights to follow a script — only to change one.

Patch the same script — rename a step label here — and the console sees it as a new version. `PATCH` **replaces the `steps` array wholesale**, so resend the whole graph on every edit (GET it first if you need the current shape):

```bash theme={null}
curl -X PATCH "https://api.orbit.devotel.io/api/v1/inbox/agent-scripts/s_9f8e7d6c" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": [
      {
        "step_id": "s-name",
        "kind": "question",
        "title": "Verify the name",
        "body": "Ask for the full name on the order.",
        "options": [
          { "label": "Name verified", "next_step_id": "s-order" },
          { "label": "No match", "next_step_id": "s-fallback" }
        ]
      },
      {
        "step_id": "s-order",
        "kind": "question",
        "title": "Order ID and outcome",
        "body": "Ask for the order ID, then refund or replacement.",
        "options": [
          { "label": "Refund", "next_step_id": "s-shipback" },
          { "label": "Replacement", "next_step_id": "s-replace" },
          { "label": "Undecided", "next_step_id": "s-fallback" }
        ]
      },
      {
        "step_id": "s-shipback",
        "kind": "prompt",
        "body": "Send the prepaid return label and the refund timeline.",
        "options": [ { "label": "Label sent", "next_step_id": "s-done" } ]
      },
      {
        "step_id": "s-replace",
        "kind": "prompt",
        "body": "Confirm the shipping address, then place the replacement.",
        "options": [ { "label": "Address confirmed", "next_step_id": "s-done" } ]
      },
      {
        "step_id": "s-fallback",
        "kind": "note",
        "body": "Internal: verify by email, then restart from the order-ID question.",
        "options": [ { "label": "Verified — restart", "next_step_id": "s-order" } ]
      },
      {
        "step_id": "s-done",
        "kind": "disposition",
        "body": "Resolve; tag refund-shipback or refund-replace."
      }
    ]
  }'
```

The response carries a bumped `version` — every PATCH increments it, so the console can tell an agent mid-flow that the script changed and reload it.

Delete a script the same way:

```bash theme={null}
curl -X DELETE "https://api.orbit.devotel.io/api/v1/inbox/agent-scripts/s_9f8e7d6c" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Deletion is permanent and immediate — keep dormant scripts inactive rather than deleting them.

## Version and replace semantics

* Every save bumps `version` (create starts at 1).
* `PATCH` replaces `steps` in full: there is no per-step edit. The supported flow is offline-edit-then-save — GET the script, edit the JSON locally, PATCH the whole graph back.
* If a replaced graph keeps the old start step, it survives; otherwise the start falls back to the first step.
* The graph is validated on the *patched* result, so you can never save a branch that dangles after a steps-only or start-only patch.

## The voice parity note

Digital agent scripts are the messaging-side counterpart to the voice queue scripts you already configure on a voice queue — the same idea (a scripted decision path the console walks during a live interaction), applied to chat, email, and messaging instead of a phone call. If your operation scripts calls today, model your digital flows the same way; the step kinds (`prompt` / `question` / `note` / `disposition`) deliberately mirror the voice script sections.

## Invariants — what a script never does

A script is display-only guidance. It never terminates a delivery by itself: no message leaves for the customer until the agent sends it, no call is placed, no routing is triggered. The console renders the graph; the human walks it. Treat scripts as inert, auditable guidance buildable and reviewable entirely inside your workspace — every create, update, and delete lands in your audit log with the acting user.

## Rollout checklist

1. **Draft inactive.** Create the script with `enabled: false` (or **Active** off in the editor) while you build it.
2. **Trace every branch.** Walk each path from the start step to a `disposition` step; confirm no branch dead-ends and every question has an explicit fallback option.
3. **Dry-run one live conversation.** Have a supervisor follow the script on a real thread while it is still inactive, and fix wording before publishing.
4. **Publish.** Set `enabled: true`; confirm the PATCH response's bumped `version`.
5. **Audit the change.** Check the audit log entry for the create/update with the acting user.
6. **Retire by disabling.** Turn a script inactive instead of deleting it; deletes are permanent.

## See also

* [Agent scripts reference](/inbox/agent-scripts) — the stored shape, graph rules, and the full field tables.
* [Inbox settings map](/inbox/settings-map) — every tile on the Inbox → Settings hub and what it controls.
* [Macros and canned responses](/guides/macros-canned-responses) — the static-reply tool scripts complement.
* [Inbox AI co-pilot](/guides/inbox-ai-copilot) — the generative counterpart — drafts, not decision paths.
