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

# Draft vs Published vs Sandbox

> How edits, the tester, and live phone & chat traffic relate — and why you publish before going live.

Every agent has two faces: the **draft** you are editing and the **published** version your customers reach. Understanding which one runs where is the difference between "it works in the tester but fails on the phone" and a clean launch.

## The three states

<CardGroup cols={3}>
  <Card title="Draft" icon="pencil">
    Your live working copy. Every edit — knowledge, skills, guardrails, playbooks — changes the draft. It is never billed and never frozen.
  </Card>

  <Card title="Published" icon="circle-check">
    A frozen snapshot of the draft, taken at publish time. Phone calls and chat sessions serve the **last published version**, not your draft.
  </Card>

  <Card title="Sandbox" icon="flask">
    A way to run the *draft* on demand — the tester and `draftMode: true` chat sessions compile the draft ephemerally so you can try changes before they go live.
  </Card>
</CardGroup>

## How traffic is routed

* **The tester runs the draft.** It compiles your current draft on the fly, so it always reflects your latest unsaved-to-live changes.
* **Phone & chat serve the last published version.** Until you publish, callers and the public chat endpoint keep getting the old behavior.
* **Publishing freezes a version.** A publish takes your draft, compiles it, and stores it as an immutable, numbered version. That snapshot is what goes live.
* **Rollback restores a version.** If a new publish misbehaves, repoint "published" at any earlier version — no re-editing required.

<Warning>
  This is the most common gotcha: you edit, the tester looks perfect, but the phone still does the old thing. **Editing changes the draft; only publishing moves it to live.**
</Warning>

## Why your first live call returns 409

A chat session (and any non-draft channel) needs a published version to serve. If an agent has **never been published**, a non-draft chat session responds `409` with the problem code `no_published_version`. The fix is always the same: **publish first**.

```jsonc theme={null}
// POST /chat/sessions with draftMode:false on an unpublished agent
{ "type": "...", "title": "Conflict", "detail": "no_published_version" }
```

<Tip>
  Testing the draft directly? Set `draftMode: true` when you create a chat session, or use the in-dashboard tester. Draft sessions compile your draft ephemerally and are **not billed**.
</Tip>

## A clean release flow

<Steps>
  <Step title="Edit the draft">
    Make your changes. Add knowledge, wire skills, tune guardrails.
  </Step>

  <Step title="Test against the draft">
    Use the tester or a `draftMode: true` chat session to confirm behavior.
  </Step>

  <Step title="Review what will change">
    Pull the pre-publish diff and report to see exactly what is about to go live.
  </Step>

  <Step title="Publish">
    Freeze the draft into a new numbered version. Phone & chat now serve it.
  </Step>

  <Step title="Roll back if needed">
    Repoint published to a known-good version in one call.
  </Step>
</Steps>

## In the API

| Action                        | Endpoint                                     | Scope          |
| ----------------------------- | -------------------------------------------- | -------------- |
| Publish (freeze a version)    | `POST /agents/{id}/publish`                  | `agents:write` |
| Roll back to a version        | `POST /agents/{id}/rollback`                 | `agents:write` |
| List version history          | `GET /agents/{id}/versions`                  | `agents:read`  |
| Pre-publish what-changed diff | `GET /agents/{id}/versions/{versionId}/diff` | `agents:read`  |
| Pre-publish report            | `GET /agents/{id}/prepublish-report`         | `agents:read`  |

<Note>
  Authenticate every call with `Authorization: Bearer flowyte_sk_…`. A successful publish returns `201` with the new frozen version; `409` signals a publish race or version mismatch. See [Agents](/concepts/agents) and [Channels](/concepts/channels) for what each version actually serves.
</Note>
