> ## Documentation Index
> Fetch the complete documentation index at: https://developers.sapot.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Safety Boundaries

> The two product boundaries the MCP server enforces server-side — flows stay intent-level, campaigns stay draft-only — and how an agent should treat them.

Two capabilities are deliberately shaped so a coding agent can *prepare* work but never cross a line that must stay human. The Sapot Chat API — not the MCP server, not your agent — enforces both, on every request:

1. **Flows are intent-level only.** An agent operates flow agents but never sees or edits how they are built.
2. **Campaigns are draft-only.** An agent can prepare a blast but never send one.

Both are locked product decisions. When an agent hits either boundary, the right response is **prepare-and-report, then hand to a human** — not retry, not work around it.

## Why these boundaries exist

<CardGroup cols={2}>
  <Card title="Intent, not implementation" icon="diagram-project">
    Agents describe <b>what</b> a flow should do; Sapot Chat decides <b>how</b> to build it. The Designer graph is product IP and stays server-side.
  </Card>

  <Card title="A human confirms every send" icon="paper-plane">
    A blast reaches real customers. An agent assembles it and reports the reach; a person reviews and clicks <b>Send</b>.
  </Card>
</CardGroup>

***

## Flows are intent-level only

An agent operates flow agents by **intent** — it can list them, inspect their name, status, connected inboxes, and runtime metrics, attach inboxes, and publish. It never receives the underlying flow graph.

**What is stripped from every agent-token response.** The Flow Designer's `graph_data`, `graph_snapshots`, and `designer_history` are removed server-side before any agent-reachable render returns. The tools reflect this — `list_flow_agents` and `get_flow_agent` return the intent-level view (id, name, description, status, `conversational_mode`, `reply_delay_seconds`, `handoff_pause_duration`, `inbox_ids`, `inbox_settings`) and nothing more.

**There is no build tool.** There is no create-from-scratch, export, import, or restore-snapshot tool in the catalog. Graphs are authored and fixed in the Sapot Chat Flow Designer in the dashboard.

**Publish returns an opaque error.** `publish_flow_agent` validates the graph first; if it is invalid, the call fails — but the error an agent receives is deliberately **opaque**. Detailed validator strings embed node labels, node types, and branch names (product IP), so those stay on the dashboard only.

<Warning>
  A missing graph is <b>not</b> a failed read to retry. If <code>publish\_flow\_agent</code> reports the graph is invalid, tell the user to open the Flow Designer and fix it — you cannot see or edit the graph, so you cannot debug it from the tool response.
</Warning>

**What to do at this boundary:** operate what you can (`set_flow_agent_inboxes`, then `publish_flow_agent`), and when a graph needs to change, hand it to a human in the Flow Designer. See [Flow Agents](/ai-agents/flow-agents) for the operate-and-publish recipe.

***

## Campaigns are draft-only

An agent can read campaigns, preview an audience, and draft or edit a draft. It can never fire the blast.

**A drafted campaign is forced non-sending.** A campaign created or edited through an agent token is forced to `campaign_status: "draft"` (and `enabled: false`) server-side — merged last, so it always wins no matter what an agent sends. The scheduler only ever fires `scheduled` campaigns, and the trigger path early-returns on a draft, so a draft cannot slip into the send queue.

**An agent can only edit its own drafts.** `update_campaign_draft` edits a draft and leaves it a draft. Editing a campaign that is not a draft is refused with a `403` — an agent can neither send a campaign nor pull a live one back out of the queue.

**There is no send scope.** The only campaign scope is `campaigns:draft`. No scope, and no tool, sends a campaign. Sending happens exactly one way: a human opens Campaigns in the dashboard and clicks **Send**, which promotes the draft to scheduled.

<Warning>
  A campaign that stays a draft is the boundary working as designed — not a failure and not something to schedule around. Do not imply you sent it.
</Warning>

**What to do at this boundary:** run `preview_campaign_audience` to report the reach, `draft_campaign` to prepare the blast, then tell the user: "Draft ready — open Campaigns and click Send to blast to N contacts." See [Campaigns](/ai-agents/campaigns) for the full draft-then-hand-off recipe.

***

## Treat a boundary as expected, not a failure

Both boundaries surface as ordinary tool responses, and neither is worth retrying or working around:

| You see                                                  | What it means                                      | What to do                                             |
| -------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------ |
| A flow agent returns with no graph                       | Designer IP is stripped from agent-token responses | Operate by intent; edit the graph in the Flow Designer |
| No create / export / import flow tool exists             | Building a graph is not an agent capability        | Author the flow in the dashboard, then operate it      |
| `publish_flow_agent` fails with a vague validation error | The graph is invalid; details are dashboard-only   | Ask the user to fix it in the Flow Designer            |
| A campaign you created stays `draft`                     | Agent-authored campaigns can never auto-send       | Report the reach; ask a human to click Send            |
| Editing a non-draft campaign returns `403`               | An agent may only edit its own drafts              | Leave live campaigns to the dashboard                  |

<Note>
  These are product boundaries, distinct from <b>scope</b> denials (a capability your key wasn't granted) and <b>quota</b> limits (<code>429</code>). See [Authentication & Scopes](/ai-agents/authentication) for those.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Flow Agents" icon="diagram-project" href="/ai-agents/flow-agents">
    Operate and publish flow agents at the intent level.
  </Card>

  <Card title="Campaigns" icon="paper-plane" href="/ai-agents/campaigns">
    Draft a blast, preview the audience, and hand off to a human to send.
  </Card>
</CardGroup>
