> For the complete documentation index, see [llms.txt](/llms.txt).
> Markdown versions of each page are available by appending .md to any URL.

# Factory definitions as code

Define a factory's agents, automations, runners, skills, and defaults as version-controlled, validated files.

Factory definitions as code let you manage a factory’s entire configuration as files in a Git repository. The files describe the factory’s repositories, agents, automations, runners, skills, and execution defaults, and they are the source of truth: when the files change, Warp updates the factory to match. Because the definition is version-controlled, every change to the factory gets the same treatment as a code change, with review, history, and rollback.

## Live-managed and file-managed factories

Every factory manages its configuration in one of two ways:

-   **Live-managed** - The configuration lives in the control room, and you edit it there directly. There are no definition files.
-   **File-managed** - The configuration lives in definition files in a Git repository, and the files are the source of truth. The control room reflects what the files say.

A file-managed factory keeps its definition in one of two places:

-   **GitHub-backed** - The definition lives in a directory you register in a GitHub repository you own. You change the factory the way you change code: open a pull request, let Warp’s check validate it, and merge.
-   **Warp-managed** - The definition lives in a repository that Warp hosts for you. You edit it in the control room, and each save commits directly.

A factory can be created in either mode, and a live-managed factory becomes file-managed when you link a definition source. In every mode, the definition files own configuration only; the factory’s operational state stays in the control room.

| Mode | Source of truth | Where you edit | How changes are reviewed and applied |
| --- | --- | --- | --- |
| Live-managed | Control-room state | Control room | Edits take effect directly in the control room. There are no files to sync until you link a definition source. |
| GitHub-backed | The registered directory on the production branch of your repository | Your GitHub repository; control-room settings are read-only and link to the files | Pull requests receive a validation check, and pushes to the production branch sync the factory. An admin can unlink the source to return the factory to live-managed. |
| Warp-managed | The Warp-hosted factory repository | The control room’s **Code** tab and supported control-room editors | Each edit validates, commits, and syncs in one step. The source cannot be unlinked or switched. A failed sync keeps the last successful definition active. |

### Editing a Warp-managed definition

For a Warp-managed source, the **Code** tab in the control room edits the definition files directly. Saves are safe against concurrent edits: if someone else committed a change after you loaded the files, Warp reports a conflict instead of overwriting the newer commit. Every save validates the whole definition and reports problems with the file and line where they occur.

For a GitHub-backed source, the control room does not provide an editor. It links to the registered directory in your repository instead.

## Directory structure

A definition is a small tree of YAML and Markdown files. Each resource takes its name from its path: `agents/reviewer/agent.md` defines an agent named `reviewer`, and `runners/linux-build.yaml` defines a runner named `linux-build`. Files never declare `kind` or `apiVersion` fields.

```
factory.yamlagents/  foreman/    agent.md    skills/      incident-triage/        SKILL.md  reviewer/    agent.mdautomations/  labeled-issue/    automation.mdrunners/  linux-build.yamlskills/  repository-conventions/    SKILL.md
```

Skills live in two places: `skills/` applies to the whole factory, while `agents/<name>/skills/` applies only to that agent. A skill is a directory containing a `SKILL.md`, not a YAML field; see [Skills for agents](../agents/capabilities/skills).

## Resource reference

YAML keys are case-sensitive.

### `factory.yaml`

`factory.yaml` names the factory and sets everything shared across it: the repositories it works in, factory-wide access, and the execution defaults agents inherit.

| Field | Purpose | Rules |
| --- | --- | --- |
| `schemaVersion` | Declares the definition schema. | Required. Must be `v1alpha1`. |
| `name` | Names the factory. | Required. |
| `description` | Describes the factory’s purpose. | Optional. |
| `alias` | Sets a display alias. | Optional. Must be unique in the workspace (case-insensitive). |
| `credentialStrategy` | Chooses whose credentials runs receive. | `EXECUTOR` uses the principal executing the run; `CREATOR` uses the user who created the run. Defaults to `EXECUTOR`. |
| `repositories` | Lists the GitHub repositories the factory works in, as `owner` and `name` pairs. | Required and non-empty. |
| `secrets` | Lists Warp-managed secret names granted to every agent. | Optional. |
| `mcpServers` | Maps server names to Warp MCP server `warpId` values, granted to every agent. | Optional. |
| `cloudProviders` | Configures GCP or AWS access. | GCP accepts `projectNumber`, `workloadIdentityFederationPoolId`, `workloadIdentityFederationProviderId`, and `serviceAccountEmail`; AWS accepts `roleArn`. |
| `integrations` | Declares connected factory integrations. | Optional. `type` accepts `slack`, `linear`, or `jira`. Declare at most one issue tracker: `linear` and `jira` are mutually exclusive, and omitting a tracker is valid. GitHub is not declared here; repository access comes from `repositories` and the connected GitHub App. |
| `agentDefaults` | Sets the execution defaults agents inherit: shared `model` or `harness`, `runner`, `environmentId`, `secrets`, `mcpServers`, and `workerHost`. | Required. Agents inherit any execution field they omit. |
| `agentDefaults.workerHost` | Sets the factory’s default execution host. | Optional. A non-empty value becomes the factory default; omitting or clearing it defers to the workspace default. |

Warp still parses the legacy `providers` key. The next time a Warp-managed edit rewrites the configuration, Warp saves it as `cloudProviders`.

In the control room, **Settings** lets you edit cloud providers for Warp-managed sources. For GitHub-backed sources, cloud provider settings are read-only and link to `factory.yaml` in the registered repository directory.

#### How access and defaults combine

Two different rules decide what an agent ends up with:

-   **Factory-wide access is additive.** Top-level `secrets` and `mcpServers` in `factory.yaml` are granted to every agent. An agent cannot opt out of them.
-   **Defaults are replaceable.** Values in `agentDefaults` apply only when an agent omits the field. An agent that sets its own `secrets` or `mcpServers` replaces the `agentDefaults` value, but the factory-wide entries still apply. Every other omitted execution field inherits from `agentDefaults`.

#### How `workerHost` resolves

`workerHost` follows the same three-way rule wherever it appears:

-   **Set a value** to choose a host: `warp` for Warp-hosted execution, or the ID of a connected self-hosted worker.
-   **Omit the field** to inherit from the level above.
-   **Set an empty or `null` value** to skip inheritance and use the workspace default.

#### Choosing a model or harness

Fields that accept a model or harness take one of two mutually exclusive forms. `model` on its own is shorthand for the Warp Agent harness, serialized as type `oz`:

```
model: auto
```

The shorthand is equivalent to:

```
harness:  type: oz  model: auto
```

Use the `harness` form for a third-party harness or advanced settings:

```
harness:  type: codex  model: gpt-5.3-codex  reasoningLevel: high  auth:    source: managedSecret    secretName: CODEX_API_KEY
```

A `harness` mapping accepts `type`, `model`, `reasoningLevel`, and `auth`. For `auth`, set `source: managedSecret` with a `secretName`, or `source: workerEnvironment` with no `secretName`; `workerEnvironment` requires that the effective `workerHost` is a self-hosted worker. Type `oz` does not accept explicit `auth` or `reasoningLevel`. See [supported harnesses](../platform/harnesses/) and [cloud agent secrets](../platform/secrets).

### `agents/<name>/agent.md`

An agent file combines YAML frontmatter with a Markdown body. The frontmatter configures how the agent runs; the body is the prompt that carries the role’s durable instructions.

| Field | Purpose | Rules |
| --- | --- | --- |
| `description` | Describes the role. | Optional. |
| `agentType` | Classifies the role. | `CUSTOM`, `FOREMAN`, `TRIAGE`, `SPEC`, `IMPLEMENT`, `REVIEW`, or `VERIFY`. `MAIN` is an alias for `FOREMAN`. |
| `credentialStrategy` | Chooses whose credentials this agent’s runs receive. | Overrides the factory-level strategy. |
| `model` or `harness` | Selects the runtime and model. | Mutually exclusive. Overrides `agentDefaults`. |
| `runner` | Names a runner defined under `runners/` or an existing runner. | Overrides `agentDefaults.runner`. |
| `environmentId` | References an existing environment. | Overrides `agentDefaults.environmentId`. |
| `secrets` | Grants role-specific secrets. | Replaces `agentDefaults.secrets`. Factory-wide secrets from `factory.yaml` still apply. |
| `mcpServers` | Grants role-specific MCP servers. | Replaces `agentDefaults.mcpServers`. Factory-wide servers from `factory.yaml` still apply. |
| `workerHost` | Selects this agent’s execution host. | Set a value to override, omit to inherit `agentDefaults.workerHost`, or clear to use the workspace default. |

A valid definition contains exactly one foreman: an agent with `agentType: FOREMAN` or its alias `MAIN`. The foreman is the factory’s entry point and the default target for automations that omit `agent`. Validation fails if a definition declares no foreman or more than one.

### `automations/<name>/automation.md`

An automation file also combines YAML frontmatter with a Markdown body. The frontmatter declares when runs start and how they execute; the body is the run prompt.

| Field | Purpose | Rules |
| --- | --- | --- |
| `enabled` | Turns the automation on or off. | Optional. |
| `agent` | Names the agent that handles runs. | Optional. Must name a declared agent. Defaults to the foreman. |
| `model` or `harness` | Selects execution for automation runs. | Mutually exclusive. Overrides the target agent. |
| `runner` | Selects compute for automation runs. | Overrides the target agent’s runner. |
| `environmentId` | Selects the environment for automation runs. | Overrides the target agent’s environment. |
| `secrets` | Selects secrets for automation runs. | Overrides the target agent’s secret list. |
| `mcpServers` | Selects MCP servers for automation runs. | Overrides the target agent’s MCP map. |
| `workerHost` | Selects the execution host for automation runs. | Set a value to override, omit to inherit from the target agent, or clear to use the workspace default. |
| `triggers` | Declares the events or schedules that start runs. | Required and non-empty. Each entry uses `provider`, `event`, an optional `filter`, and an optional `schedule` with `name` and `cron`. |

See [triggers](../platform/triggers/) and [integrations](../platform/integrations/) for event sources.

### `runners/<name>.yaml`

A runner file defines compute, not agent behavior.

| Field | Purpose | Rules |
| --- | --- | --- |
| `description` | Describes the workload the runner supports. | Optional. |
| `setupCommands` | Commands that initialize the sandbox. | Ordered list. |
| `instanceShape` | Sets compute capacity. | Uses `vcpus` and `memoryGb`. |
| `platform` | Sets the operating system and architecture. | Uses `os` and `arch`. Linux adds `linux.dockerImage`; macOS adds `mac.version`. |

The control room’s **Runners** page lists the effective runners in every mode. For a Warp-managed source, creating or editing a runner there writes `runners/*.yaml` for you. For a GitHub-backed source, runner controls are read-only and link to the runner directory in your repository. See [cloud agent runners](../platform/runners) and [cloud agent environments](../platform/environments) for execution behavior.

## Example factory definition

This example defines a small factory: one repository, a foreman, an automation triggered by a GitHub label, and a Linux runner.

```
schemaVersion: v1alpha1name: payments-factorydescription: Processes approved work for the payments servicealias: paymentscredentialStrategy: EXECUTORrepositories:  - owner: ACME    name: PAYMENTS_SERVICEagentDefaults:  model: auto  runner: linux-build  environmentId: PAYMENTS_ENVIRONMENT_ID
```

`ACME` is the GitHub organization, `PAYMENTS_SERVICE` is the repository name, and `PAYMENTS_ENVIRONMENT_ID` is the ID of an existing environment.

```
---description: Routes approved payments work through the factoryagentType: FOREMANsecrets:  - SENTRY_AUTH_TOKENmcpServers:  sentry:    warpId: SENTRY_MCP_SERVER_ID---
Own each work item from intake through human handoff.
Confirm the request is ready before dispatching implementation. Requirerepository validation and independent review before marking work complete.
```

The foreman inherits `model`, `runner`, and `environmentId` from `agentDefaults`. Its Sentry secret and MCP server are role-specific; moving them to `factory.yaml` would grant them to every agent in the factory.

```
---enabled: trueagent: foremantriggers:  - provider: github    event: issue_labeled    filter:      repos: [ACME/PAYMENTS_SERVICE]      labels: [factory-ready]---
Review the labeled issue and decide the next required stage. Preserve theissue's acceptance criteria and return unresolved product questions to a human.
```

```
description: Linux runner for payments builds and testssetupCommands:  - corepack enableinstanceShape:  vcpus: 4  memoryGb: 8platform:  os: linux  arch: x86_64  linux:    dockerImage: ubuntu:22.04
```

## Validation and synchronization

Warp treats the definition as a single unit: it parses, validates, and resolves a change as a whole, and only a fully valid tree becomes the active definition. If any step fails, the factory keeps running on the last successful definition. An invalid change never partially applies.

```
flowchart LR  Change["Definition change"] --> Parse["Parse and validate"]  Parse -->|Valid| Resolve["Resolve dependencies"]  Resolve -->|Valid| Apply["Apply desired state"]  Apply -->|Success| Active["Active definition"]  Parse -->|Failure| Last["Keep last successful definition"]  Resolve -->|Failure| Last  Apply -->|Failure| Last
```

Validation rejects:

-   Unknown fields, duplicate YAML keys, unsupported file paths, and malformed frontmatter.
-   YAML anchors, aliases, and explicit tags.
-   A `schemaVersion` other than `v1alpha1`.
-   A missing `repositories` list or `agentDefaults` block, an automation without `triggers`, or a definition without exactly one foreman.
-   References that do not resolve, including agents, runners, environments, secrets, MCP servers, models, and harness settings.

Every diagnostic identifies the source file and line that caused it.

### GitHub pull request checks

For GitHub-backed sources, every pull request that targets the production branch receives a `warp/factory-config (<directory>)` check for each registered path. The check annotates invalid fields or references and summarizes the changes it would apply. A push to the production branch starts synchronization.

### Warp-managed direct synchronization

For Warp-managed sources, supported control-room edits commit directly to the Warp-hosted repository, then validate and sync; there is no separate pull request step. Branch-based review gating is limited and is not a general workflow for these edits. If synchronization fails, the commit remains in the repository, and the factory keeps running on the last successful definition while you repair it.
