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

# Programmatic BlueprintRun

> Run Genesis blueprints from an external application through a server-side BFF, external gates, events, and mission artifacts.

## Overview

**Programmatic BlueprintRun** lets an external application start and supervise a
Genesis blueprint mission by HTTP API. The external app can keep its own user
experience while Genesis handles the mission thread, phase execution, work log,
repository artifacts, and event stream.

This is useful when a partner or host application wants to:

* launch a Genesis workflow from its own UI
* provide a catalog, dataset, or case file as input
* pause Genesis at structured gates for host-side choices
* receive progress and completion events
* read final mission artifacts from the Genesis project repository

The browser should not hold Genesis credentials. The recommended integration is
a small **backend-for-frontend (BFF)** owned by the host app.

```text theme={null}
Host browser UI  ->  Host BFF  ->  Genesis API
                       |
                       +-- holds Genesis PAT/JWT
```

## Reference example

A complete local example is included in the Genesis repo:

```text theme={null}
examples/atlas-blueprintrun-external/
```

That example contains:

| File | Purpose |
| - | - |
| `server/bff.mjs` | Node BFF that stores the Genesis token server-side and proxies BlueprintRun/repo calls. |
| `src/main.ts` | Thin browser UI for the Cedar Health Atlas dataroom review demo. |
| `vite.config.ts` | Vite dev server that proxies `/demo-bff/*` to the BFF. |
| `README.md` | Full local runbook for env setup, routes, gates, and troubleshooting. |

The example demonstrates the main production pattern: the browser talks only to
the BFF, and the BFF calls Genesis with `Authorization: Bearer ...`.

The reference blueprint shipped in Genesis is **`atlas_dataroom_review_demo`**
(Cedar Health dataroom review). It uses string phase ids (`catalog`,
`select_documents`, …) and a manifest `phase_order` so the document-flow graph,
default next-phase hints, and BlueprintRun gates stay aligned.

## REST endpoints

All routes are under `/api` and require `Authorization: Bearer <PAT or JWT>` with
access to the run's agent. Commit-style routes accept an optional
`Idempotency-Key` header (max 120 characters); replays with the same body return
`204`, mismatched bodies return `409`.

| Method | Path | Purpose |
| - | - | - |
| `POST` | `/blueprints/{blueprint_name}/runs` | Start a run (`202` created, `200` replay terminal, `409` active conflict or blocked when required high-risk tools are globally disabled). |
| `GET` | `/runs/{run_id}` | Aggregate state (`pending_inputs`, `current_phase`, `project_id`, …). |
| `GET` | `/runs/{run_id}/events?since={seq}` | Poll lifecycle events; `next_since` for pagination. |
| `POST` | `/runs/{run_id}/input/{input_id}` | Commit or detail a specific external gate. |
| `POST` | `/runs/{run_id}/input` | Compat when exactly one gate is open. |
| `POST` | `/runs/{run_id}/external-inputs` | Register a dynamic gate at runtime (`allow_dynamic_external_inputs`). |
| `POST` | `/runs/{run_id}/cancel` | Cancel the run. |
| `GET` | `/runs/{run_id}/deliveries` | Webhook delivery attempts. |
| `GET` | `/runs/{run_id}/capabilities` | Git RBAC hints for host UIs. |
| `GET` | `/runs/{run_id}/repos` | Mission repositories linked to the run. |
| `GET` | `/runs/{run_id}/repos/{repo_id}/tree` | List or fetch files in a mission repo. |
| `GET` | `/runs/{run_id}/repos/{repo_id}/bundle` | Download a repo bundle (optional `since` commit). |

Mission detail responses also expose `blueprint_run_id` when the mission thread
is attached to a programmatic run (`GET /api/projects/{project_id}`).

## Core flow

1. The host BFF starts a run:

```http theme={null}
POST /api/blueprints/{blueprint_name}/runs
Authorization: Bearer <Genesis PAT or JWT>
Content-Type: application/json
```

2. Genesis creates the mission project and thread, binds them to the run, and
   enters the blueprint's requested entry phase (after high-risk tool policy
   preflight passes). This startup work is completed before the create response
   is returned.

3. Genesis schedules the kickoff agent turn and emits BlueprintRun events. The
   kickoff message supplies mission context; it does not enter the same phase a
   second time. For a pre-entered phase, the message also includes the
   `ENTER_PHASE` result: its public briefing (up to 8,000 characters) and any
   injected documents returned by the phase. Injected-document content is
   bounded to an 8,000-character serialized section; truncated content includes
   `metadata.file_path` and `metadata.repo_id` so the agent can re-read the
   authoritative file from the mission repository when needed. Phase
   instructions appear once in this structured entry contract alongside the
   phase purpose and actions; kickoff notes and injected documents remain
   separate. The 24,000-character serialized-contract budget applies to the
   whole contract. If it is exceeded, Genesis omits the contract and requires
   the agent to read it back from the same source and version.

If startup is cancelled or another pre-entry step fails, Genesis records a
`run_failed` terminal event for the run. Poll `GET /api/runs/{run_id}` or the
events endpoint instead of treating a missing kickoff message as an indefinitely
pending startup.

If the blueprint requires high-risk tools that are blocked workspace-wide,
`POST /api/blueprints/{blueprint_name}/runs` returns HTTP `409` with
`error_type` `policy_blocked` and does not create a run. See
[Blueprint mission-start tool policy preflight](/docs/Genesis-API/API-Reference#blueprint-mission-start-tool-policy-preflight).

4. If the blueprint opens an external input gate, Genesis exposes that gate in
   `pending_inputs` and shows it in the Genesis mission UI.

5. The host app commits or details a gate through:

```http theme={null}
POST /api/runs/{run_id}/input/{input_id}
Authorization: Bearer <Genesis PAT or JWT>
Content-Type: application/json
```

6. Genesis continues the mission and writes artifacts into the mission
   repository.

7. The host app can browse or download artifacts through Genesis repo APIs, or
   through its own BFF proxy.

## Starting a run

The request body is a `BlueprintRunCreateRequest`. Important fields:

| Field | Purpose |
| - | - |
| `run_id` | Caller-owned durable run id. Use a UUID. |
| `bot_id` | Agent that owns the mission, usually `Eve`. |
| `mission_name` | Mission name shown in Genesis. |
| `description` | Mission description and context. |
| `kickoff_notes` | Optional host-provided text included in the first mission kickoff message. |
| `mode` | Usually `continuous` for host-driven automation. |
| `demo_scope` | Required for disposable demo blueprints (`demo:disposable` tag). Canonical presenter scope (1–32 lowercase letters and digits with single hyphens). Genesis derives it from the authenticated user and `presenter_session_id`; the value must match that binding on `POST /api/blueprints/{blueprint_name}/start`. |
| `presenter_session_id` | Required with `demo_scope` on `POST /api/blueprints/{blueprint_name}/start` for disposable demos. Browser-local session id (`presenter-` plus 1–20 lowercase letters or digits). Omit for non-disposable blueprints and for BlueprintRun creates that do not use presenter-bound disposable starts. |
| `inputs` | Opaque host inputs persisted on the run and included in kickoff context. |
| `webhooks` | Optional callbacks for BlueprintRun events. |
| `actor` | Optional host identity block echoed on events for audit. |
| `use_fixture_timeline` | Optional deterministic no-LLM timeline for harness tests. |

Example:

```json theme={null}
{
  "run_id": "9a27a51f-f5e7-4a57-8060-84c2b91fd2d3",
  "bot_id": "Eve",
  "mode": "continuous",
  "mission_name": "Cedar Health - Atlas dataroom review",
  "description": "First-pass review started from Atlas.",
  "kickoff_notes": "Host-provided source: read-only repo `atlas-blueprintrun-demo-catalog`, path `cedar/full`. Inventory files there and write deliverables only to the mission repo.",
  "inputs": {
    "source": "atlas-external-ui",
    "catalog_dataset": "cedar_full",
    "catalog_repo_id": "atlas-blueprintrun-demo-catalog",
    "catalog_path": "cedar/full"
  },
  "actor": {
    "type": "service",
    "id": "atlas_external_demo",
    "display_name": "Atlas external BFF"
  }
}
```

<Note>
  `kickoff_notes` is the generic way to tell the running agent what the host
  wants it to do. `inputs` is for machine-readable host state that should be
  persisted on the run and echoed in events.
</Note>

## External input gates

A blueprint can declare programmatic external gates in its manifest:

```yaml theme={null}
programmatic:
  allow_dynamic_external_inputs: true
  external_inputs:
    - id: document_selection
      phase: select_documents
      purpose: document_selection
      input_id: document_selection
      response_schema: DocumentSelectionResponse
      response_policy:
        mode: default_after
        after_seconds: 300
        default_response:
          excluded_document_ids: []
          auto_submitted: true
          reason: timeout
```

When the mission reaches that phase, Genesis pauses and returns the gate in:

```json theme={null}
{
  "pending_inputs": {
    "document_selection": {
      "input_id": "document_selection",
      "purpose": "document_selection",
      "phase": "select_documents",
      "default_after_seconds": 300,
      "default_after_remaining_seconds": 242
    }
  }
}
```

The host commits the gate by posting to the stable `input_id`:

```json theme={null}
{
  "intent": "commit",
  "purpose": "document_selection",
  "response": {
    "excluded_document_ids": ["customer_reference_notes"],
    "auto_submitted": false,
    "reason": "user_submit"
  }
}
```

### `details` vs `commit`

Some gates support a detail round:

* `intent: "details"` sends structured information or a follow-up question
  without closing the gate.
* `intent: "commit"` satisfies the gate and lets Genesis continue.

Use `details` for clarification and `commit` for the final host decision.

### Dynamic gates at runtime

When `programmatic.allow_dynamic_external_inputs` is `true`, the host can open an
additional gate after the run starts:

```http theme={null}
POST /api/runs/{run_id}/external-inputs
```

Body fields match `BlueprintRunRegisterExternalInputRequest`: `input_id`, `phase`
(must equal `current_phase`), `purpose`, `response_schema` (or
`response_schema_inline`), optional `details_request_schema_inline`, and optional
`response_policy` (same shape as manifest `external_inputs`).

## Auto-continue gates

External gates can define:

```yaml theme={null}
response_policy:
  mode: default_after
  after_seconds: 180
  default_response:
    confirmed: true
    auto_submitted: true
    reason: timeout
```

Genesis exposes the countdown in `default_after_remaining_seconds` and the
configured total in `default_after_seconds`. Each pending row can also include
`default_response` (the payload Genesis will apply on timeout or early apply).
When the timer expires, Genesis applies that `default_response`, emits
`input_resolved`, and continues the run.

The Genesis mission UI and the external demo UI both surface this countdown so
operators know the run will not wait indefinitely. When exactly one gate is open
and a countdown is active, operators with API access can choose **Apply default
& continue now** in the mission UI; Genesis posts the manifest
`default_response` with `intent: "commit"` (same effect as waiting for the
timer).

## Genesis mission UI

When a mission is backed by a BlueprintRun, Genesis surfaces operator context on
every mission tab (not only above the work log):

* **External gate ribbon** — shown while `GET /runs/{run_id}` reports open
  `pending_inputs` (or compat `pending_input`). Displays phase, gate purpose, an
  **External** badge, auto-continue countdown, **API details** (run id, input ids,
  curl example for `POST /api/runs/{run_id}/input/{input_id}`), and optional
  **Apply default & continue now** when a single gate has `default_after`.
* **Catalog seed strip** — when the host passed `catalog_repo_id` (or equivalent)
  in run `inputs`, Genesis shows the wired read-only bot-git repo id so operators
  know which catalog the external app selected. Mission deliverables still go to
  the mission repository.
* **Mission Center status** — an open external gate rolls an otherwise active
  mission up to **Awaiting Input** (mustard styling) instead of generic in-progress.
* **Thread tab** — while an external gate is open, chat in the mission thread does
  not clear the gate; operators fulfill it through the API (see the ribbon modal).

## Manifest `phase_order`

Blueprints that use string phase ids (for example `catalog`, `select_documents`)
should declare explicit order under `blueprint.phase_order`:

```yaml theme={null}
blueprint:
  phase_order:
    - catalog
    - select_documents
    - process_documents
    - summarize_review
    - produce_results
```

Genesis uses `phase_order` for:

* document-flow graph layout and phase-modal “next step” defaults,
* mapping a numeric `active_blueprint_phase` index to the canonical string id,
* blueprint engine default progression when a phase has no `next_options`.

Phases omitted from `phase_order` still appear after the listed ids, sorted with
numeric ids first (numerically) then non-numeric ids (alphabetically).

## Events and custom payloads

BlueprintRun emits lifecycle events such as:

* `run_started`
* `phase_entered`
* `phase_exited`
* `input_required`
* `input_resolved`
* `catalog_ready`
* `review_summary_ready`
* `results_ready`
* `run_complete`
* `run_cancelled`
* `run_failed`

Blueprint manifests can map phase exit proof into custom event payloads:

```yaml theme={null}
programmatic:
  feedback_events:
    - name: results_ready
      phase: produce_results
      when: phase_exit
      payload_from: results
```

The agent should then exit the phase with:

```json theme={null}
{
  "results": {
    "file": "docs/atlas_results.md",
    "status": "complete",
    "coverage": {
      "cataloged": 6,
      "included": 5,
      "excluded": 1,
      "processed": 5
    }
  }
}
```

This keeps webhook/event payloads machine-readable instead of only narrative.

## Mission repository artifacts

Genesis creates or resolves a mission repository for the run. The agent writes
phase deliverables there, such as:

* catalog snapshots
* selection notes
* processing outlines
* review summaries
* final results

Host apps can expose those files directly in their own UI by proxying Genesis
repo APIs through their BFF. The example app shows a live repository tree,
markdown preview modal, bundle download, and upload control.

<Tip>
  The Atlas example seeds `atlas-blueprintrun-demo-catalog` locally and passes
  only generic kickoff notes plus run inputs. The kickoff does not list the
  files; Eve inventories the selected folder through bot-git.
</Tip>

## Webhooks

Runs can include webhook specs:

```json theme={null}
{
  "webhooks": [
    {
      "url": "https://host.example.com/webhooks/genesis",
      "events": ["*"]
    }
  ]
}
```

Genesis schedules deliveries for matching BlueprintRun events. If you include
`hmac_secret` on run create, consumers can validate the HMAC signature on the
payload.

For local development, the example BFF can receive webhooks at:

```text theme={null}
http://127.0.0.1:5191/webhooks/genesis
```

Set `WEBHOOK_PUBLIC_BASE` in the example `.env` so the BFF adds the callback to
run creation.

## Security model

Use a BFF for production-style integrations:

* Keep Genesis PAT/JWT values server-side.
* Let the browser call only your BFF.
* Let the BFF enforce tenant/user rules before calling Genesis.
* Use stable `run_id`, `input_id`, and `actor` values for auditability.
* Use `Idempotency-Key` on commit-style actions where replay or retries are
  possible.

<Warning>
  Avoid putting a Genesis PAT or OAuth JWT directly in a browser app. The
  direct-to-Genesis mode in the example is for debugging only.
</Warning>

## Where to start

1. Read `examples/atlas-blueprintrun-external/README.md`.
2. Start a local Genesis env.
3. Configure the example BFF `.env`.
4. Run `npm run dev:full` in the example folder.
5. Start the Cedar Health review and watch the same run in Genesis Missions.

That path exercises the full contract: start run, catalog, external document
selection, optional review clarification, auto-continue, processing, summary,
results, artifact browsing, and mission completion.
