---
title: "Create Run"
method: POST
path: "/api/v1/runs"
tags: ["Runs"]
---

# Create Run

`POST /api/v1/runs`

Creates a new workflow run in `submitted` status from an immutable workflow-version intent. Creation does not start or schedule the run.

Failures return the standard error body. The endpoint responds `404` (`workflow_version_not_found`, `environment_not_found`), `422` (`run_intent_invalid`, `target_invalid`, `target_environment_unsupported`, `pull_request_environment_unsupported`, `workflow_version_unusable`, `run_compile_invalid`), `503` (`integration_unavailable`), or `500` (`workflow_version_store_error`, `credential_store_error`, `variable_store_error`, `run_persistence_failed`).

## Request body

- RunIntent — A request to create, but not start, one run from an immutable workflow version and an explicit workspace target.
  - `workflow_version_id` string, required — SHA-256 identity of validated canonical workflow-version bytes. Hex input is case-insensitive; Fabro emits the canonical lowercase form.
  - `target` union, required — Workspace content and location requested for a run.
    - GitRunTarget — Public github.com repository target. The branch names the attached working branch. An optional tag selects a release at worker start, and an optional exact SHA is authoritative when both are present.
      - `kind` 'git', required
      - `repo` string, required — GitHub repository slug in `owner/name` form.
      - `branch` string, required — Required attached working branch name, preserved exactly.
      - `tag` string — Optional bare tag name. Prefixes such as `refs/tags/` and `tags/` are rejected. Without `sha`, the worker resolves this tag when the sandbox starts and fails if it is unavailable.
      - `sha` string — Optional exact commit. The server lowercase-normalizes its syntax but does not resolve it, prove branch ancestry, or prove that it matches an accompanying tag. When present, this exact commit wins.
    - NoneRunTarget — Empty workspace with no repository. Docker and Daytona accept this target and suppress cloning even when workflow settings enable it. Local environments reject it; Local scratch allocation is a separate future capability.
      - `kind` 'none', required
    - FolderRunTarget — Existing directory on the Fabro server, executed in place by a Local environment. The submitted path must be absolute and name an existing directory; Fabro resolves symlinks and persists its canonical UTF-8 path. This target is intended for trusted single-tenant deployments. Docker and Daytona environments always reject it. This target does not add Local Git cloning or Local scratch workspaces. Folder runs execute in place without Fabro Git checkpoints, so fork and rewind are unavailable.
      - `kind` 'folder', required
      - `path` string, required — Absolute path on the Fabro server, not on the API caller's machine.
  - `args` RunIntentArgs, required — Structured run overrides accepted by workflow-version creation.
    - `model` string
    - `provider` string — LLM provider; this does not select the sandbox environment.
    - `inputs` object
    - `labels` object
    - `dry_run` boolean — Overrides `run.execution.mode`: true selects `dry_run`, false selects `normal`, and omission inherits the lower-precedence setting.
    - `auto_approve` boolean — Overrides `run.execution.approval`: true selects `auto`, false selects `prompt`, and omission inherits the lower-precedence setting.
    - `preserve_sandbox` boolean — Overrides `run.environment.lifecycle.preserve`; omission inherits the lower-precedence setting.
  - `environment_id` string — Server environment catalog ID. Omission selects `default`.
  - `parent_id` string — Optional orchestration parent run ID.
  - `title` string — Optional explicit run title, normalized by the server.
  - `goal` string — Optional inline goal override.

## Response `201`

Run created

- Run — Canonical public run shape.
  - `id` string, required
  - `parent_id` string, nullable — Current orchestration parent run ID, if linked.
  - `children_count` integer, required — Number of runs currently linked to this run as their orchestration parent.
  - `title` string, required
  - `goal` string, required
  - `workflow` WorkflowRef, required
    - `slug` string, nullable, required
    - `name` string, nullable, required
    - `graph_name` string, nullable, required
    - `node_count` integer, required — Number of nodes in the workflow graph.
    - `edge_count` integer, required — Number of edges in the workflow graph.
  - `automation` AutomationRef, required
    - `id` string, required
    - `name` string, nullable, required
    - `trigger_id` string, nullable
    - `workflow_source` ResolvedAutomationGitWorkflowSource — Workflow source coordinate and exact commit captured when an automation run was created. The requested selectors remain available for audit context while `resolved_sha` identifies the immutable source revision that supplied the workflow bytes.
      - `repo` string, required — GitHub repository slug in `owner/name` form.
      - `branch` string, required — Required branch fallback and audit context.
      - `tag` string — Optional tag requested by the automation.
      - `sha` string — Optional exact commit requested by the automation.
      - `resolved_sha` string, required — Exact lowercase Git commit that supplied the workflow bytes.
  - `repository` RepositoryRef, required — Durable repository metadata for a run.
    - `name` string, required
    - `origin_url` string, nullable, required
    - `provider` 'github' | 'git' | 'unknown', required
  - `created_by` union, required
    - PrincipalUser
      - `kind` 'user', required
      - `identity` IdpIdentity, required
        - `issuer` string, required
        - `subject` string, required
      - `login` string, required
      - `auth_method` 'github' | 'dev_token', required — Runtime user authentication method.
      - `avatar_url` string, nullable
    - PrincipalWorker
      - `kind` 'worker', required
      - `run_id` string, required
    - PrincipalWebhook
      - `kind` 'webhook', required
      - `delivery_id` string, required
    - PrincipalSlack
      - `kind` 'slack', required
      - `team_id` string, required
      - `user_id` string, required
      - `user_name` string, nullable
    - PrincipalAgent
      - `kind` 'agent', required
      - `session_id` string, nullable
      - `parent_session_id` string, nullable
      - `model` string, nullable
    - PrincipalSystem
      - `kind` 'system', required
      - `system_kind` 'engine' | 'watchdog' | 'timeout', required
  - `origin` RunOrigin, required
    - `kind` 'api', required
  - `labels` object, required
  - `lifecycle` RunLifecycle, required
    - `status` union, required — Execution status of a run. Archive state is represented separately on `RunLifecycle.archived` so terminal status payloads remain intact.
      - RunStatusSubmitted
        - `kind` 'submitted', required
      - RunStatusPending
        - `kind` 'pending', required
        - `reason` 'approval_required', required — Reason a pre-execution run is pending instead of runnable.
      - RunStatusRunnable
        - `kind` 'runnable', required
      - RunStatusStarting
        - `kind` 'starting', required
      - RunStatusRunning
        - `kind` 'running', required
      - RunStatusBlocked
        - `kind` 'blocked', required
        - `blocked_reason` 'human_input_required', required — Specific reason a run is blocked on external intervention.
      - RunStatusPaused
        - `kind` 'paused', required
        - `prior_block` 'human_input_required', required — Specific reason a run is blocked on external intervention.
      - RunStatusRemoving
        - `kind` 'removing', required
      - RunStatusSucceeded
        - `kind` 'succeeded', required
        - `reason` 'completed' | 'partial_success', required — Reason attached to a successful terminal run status.
      - RunStatusFailed
        - `kind` 'failed', required
        - `reason` 'workflow_error' | 'publish_failed' | 'cancelled' | 'approval_denied' | 'terminated' | 'transient_infra' | 'budget_exhausted' | 'launch_failed' | 'bootstrap_failed' | 'sandbox_init_failed', required — Reason attached to a failed terminal run status.
      - RunStatusDead
        - `kind` 'dead', required
    - `approval` RunApproval, required — Pre-execution approval state for runs that require one-time human approval.
      - `state` 'pending' | 'approved' | 'denied', required — State of a run's pre-execution approval request.
      - `requested_at` string, date-time, required
      - `decided_at` string, date-time, nullable, required
      - `denial_reason` string, nullable, required
    - `pending_control` 'cancel' | 'pause' | 'unpause', required — Run control action requested by the API.
    - `queue_position` integer, nullable, required
    - `error` RunError, required — Error information for a failed run.
      - `message` string, required — Error message.
    - `archived` boolean, required
    - `archived_at` string, date-time, nullable, required
  - `sandbox` RunSandbox, required — Sandbox lifecycle record for a run. A run can have a requested sandbox plan before it has an initialized sandbox instance.
    - `kind` 'planned' | 'initializing' | 'ready' | 'failed', required — Lifecycle state for a run sandbox request.
    - `plan` RunSandboxPlan, required — Requested sandbox provider and base image/snapshot from run settings.
      - `provider` string, required — Sandbox provider kind. `local`, `docker`, and `daytona` are bundled with the server; any other value names a sandbox-driver plugin configured under `server.sandbox.providers.<kind>`.
      - `image` string, nullable
      - `snapshot` string, nullable
    - `instance` RunSandboxInstance — Initialized sandbox provider and runtime metadata.
      - `provider` string, required — Sandbox provider kind. `local`, `docker`, and `daytona` are bundled with the server; any other value names a sandbox-driver plugin configured under `server.sandbox.providers.<kind>`.
      - `image` string, nullable
      - `snapshot` string, nullable
      - `runtime` RunSandboxRuntime, required
        - `id` string, required
        - `working_directory` string, required
        - `repo_cloned` boolean, nullable, required
        - `clone_origin_url` string, nullable, required
        - `clone_branch` string, nullable, required
        - `workspace_root` string, nullable
        - `repos_root` string, nullable
        - `primary_repo_path` string, nullable
        - `primary_repo_link` string, nullable
    - `failure` RunSandboxFailure — Sandbox initialization failure details.
      - `provider` string, required — Provider reported by the sandbox initialization event.
      - `error` string, required
      - `causes` string[], required
      - `duration_ms` integer, required
  - `models` RunModel[], required
    - `provider` string, nullable, required
    - `name` string, required
  - `source_directory` string, nullable, required
  - `timestamps` RunTimestamps, required
    - `created_at` string, date-time, required
    - `started_at` string, date-time, nullable, required
    - `last_event_at` string, date-time, nullable, required
    - `completed_at` string, date-time, nullable, required
  - `timing` RunTiming, required — Timing rollup for an entire run. Active fields sum work across stage visits, so `active_time_ms` can exceed `wall_time_ms` when parallel branches run concurrently. For a running run, stages still in flight contribute a live estimate rather than nothing, so wall and active both advance continuously. Unlike `StageTiming`, active is not clamped to wall here — concurrent branches can legitimately sum past run wall time.
    - `wall_time_ms` integer, required
    - `inference_time_ms` integer, required
    - `tool_time_ms` integer, required
    - `active_time_ms` integer, required — Equals `inference_time_ms + tool_time_ms`.
  - `usage` Usage, required — lithos `Usage`: token counts and, when known, what they cost. `cost` is absent when there is no cost data, never zero. A sum has a cost only when every part that used tokens was priced; its `source` is the parts' shared source, or `application` when they differ.
    - `tokens` TokenCounts, required — lithos `TokenCounts`: five disjoint token buckets. Every token is counted in exactly one, so their plain sum is the total. `input` excludes cache reads and writes, while `output` excludes reasoning tokens when the provider reports them separately. A bucket that is absent reads as zero.
      - `input` integer — Prompt tokens that were neither read from nor written to a cache.
      - `output` integer — Completion tokens that are not reasoning tokens.
      - `reasoning` integer — Completion tokens spent on reasoning, priced at the output rate.
      - `cache_read` integer — Prompt tokens served from a provider cache.
      - `cache_write` integer — Prompt tokens written into a provider cache.
    - `cost` Cost — lithos `Cost`: a USD amount in micros and where it came from.
      - `usd_micros` integer, required
      - `source` 'catalog' | 'provider' | 'application', required — Where a cost came from: `catalog` (estimated from catalog prices), `provider` (the provider's own reported cost), or `application` (a sum the caller assembled from differently sourced parts).
  - `size` 'XS' | 'S' | 'M' | 'L' | 'XL', required — Run size bucket derived from the run's current cost.
  - `ask_fabro` AskFabro, required — Readiness and defaults for starting an Ask Fabro session on this run.
    - `available` boolean, required
    - `unavailable_reason` 'no_sandbox' | 'sandbox_not_ready' | 'llm_unconfigured' | 'null', nullable, required
    - `default_model` string, nullable, required
  - `diff` DiffSummary, required — Cheap aggregate file and line counts for a run diff.
    - `files_changed` integer, required — Total number of changed files, including binary files.
    - `additions` integer, required — Total lines added across text files.
    - `deletions` integer, required — Total lines deleted across text files.
  - `pull_request` PullRequestLink, required — Minimal GitHub pull request link associated with a run.
    - `owner` string, required
    - `repo` string, required
    - `number` integer, required
    - `html_url` string, uri, required — Computed GitHub web URL for the pull request.
  - `current_question` RunQuestion, required — A pending human-in-the-loop question summary.
    - `text` string, required — Question text.
  - `superseded_by` string, nullable, required — Run ID that superseded this run via rewind, if any.
  - `retried_from` string, nullable, required — Source run ID when this run was created by manual retry.
  - `links` RunLinks, required
    - `web` string, uri, nullable, required

## Other responses

- `400` — Invalid JSON

## Changes

- **2026-09-14** `57ca921cdd38` — 6 breaking, 5 info
  - added the new required request property `args`
  - added the new required request property `target`
  - added the new required request property `workflow_version_id`
  - removed `#/components/schemas/RunManifest, #/components/schemas/RunIntent` from the request body `oneOf` list
  - …7 more
- **2026-09-13** `55913dc72a51` — 1 breaking, 7 warning, 1 info
  - the request's body type changed from `object` to no type
  - removed the request property `args`
  - removed the request property `environment_id`
  - removed the request property `goal`
  - …5 more
- **2026-09-12** `98d835618776` — 5 breaking, 4 info
  - added the new required request property `args`
  - added the new required request property `target`
  - added the new required request property `workflow_version_id`
  - removed `#/components/schemas/RunManifest, #/components/schemas/RunIntent` from the request body `oneOf` list
  - …5 more
- …earlier changes not shown

[Full history](https://skmtc.dev/fabro-sh/apis/fabro-run-api/changes/api/v1/runs/post.md)

---

[API](https://skmtc.dev/fabro-sh/apis/fabro-run-api.md) · [All operations](https://skmtc.dev/fabro-sh/apis/fabro-run-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fabro-sh/apis/fabro-run-api/revisions/1258a4cf33df?raw)
