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

# Factory definition syntax

Look up the files and public keys in a factory definition: factory.yaml, agents, automations, runners, routers, benchmarks, scorers, skills, and webhooks.

A factory definition is a versioned tree of YAML and Markdown files rooted at `factory.yaml`. It can define agents, automations, runners, model routers, benchmarks, scorers, skills, and webhooks. Keys are case-sensitive, and Warp applies file changes automatically.

For working definitions you can copy, see [warp-factory-examples](https://github.com/warpdotdev/warp-factory-examples).

## Where the definition lives

Choose where to host the definition when you create a factory:

-   **Warp-managed (default)** - Edit the definition in the [Warp Factories web app](https://docs.warp.dev/factories/factory-dashboard/). Warp validates, commits, and applies changes; its repository stays hidden.
-   **GitHub** - On a paid plan, keep the definition in your own repository. The web app links to the files in a read-only view. Merges to the production branch (`main` by default) update the factory.

Both modes share the file format. You can link a Warp-managed factory to GitHub later.

Work items, runs, and metrics live in the web app, not in the definition.

## Validate a definition

Warp validates syntax, required fields, and resource access before applying a definition: on save for a Warp-managed factory, and in pull requests to a GitHub-backed factory’s production branch.

### Pull request checks

Every pull request to the production branch gets a **warp/factory-config** check. It reports errors by file and line or summarizes the resources a valid change will create, update, or delete. Pull requests that don’t change the definition pass immediately.

Require the check in branch protection to block invalid definitions.

Warp applies a definition as one unit. If validation fails, the factory keeps its last valid definition.

For subdirectory check names and troubleshooting, see [factory-definition pull request checks](https://docs.warp.dev/factories/integrations/github/#factory-definition-pull-request-checks).

### Validate locally or in CI

Run [`validate_factory_files.py`](https://github.com/warpdotdev/warp-factory-examples/blob/main/scripts/validate_factory_files.py) before opening a pull request or in CI. It requires Python 3, but no Warp login or existing factory.

```bash
python3 scripts/validate_factory_files.py path/to/factory-root
```

Pass the factory root to check cross-file references. The script reports errors by file and line. The GitHub check also validates team- and factory-dependent settings.

For a CI job built on the script, see the example repository’s [validation workflow](https://github.com/warpdotdev/warp-factory-examples/blob/main/.github/workflows/validate.yml).

### Validate with a coding agent

-   **Warp Agent** - Ask the agent to change or check the definition. Its `factory-files` skill validates before opening a pull request. For example: “Add a nightly dependency-audit automation and validate the definition.”
-   **Factory MCP** - Connect another coding agent to [Factory MCP](https://docs.warp.dev/factories/factory-mcp/) for schema and validation tools.
-   **Other agents** - Have the agent run the [validator script](#validate-locally-or-in-ci).

## JSON Schema

Warp publishes unauthenticated JSON Schemas for editor completion and validation. They describe each field and reject unknown keys.

-   `https://app.warp.dev/api/v1/factory-files/schemas` - Lists supported versions and the current version.
-   `https://app.warp.dev/api/v1/factory-files/schemas/v1alpha1` - Returns all `v1alpha1` documents, keyed by document name.
-   `https://app.warp.dev/api/v1/factory-files/schemas/v1alpha1/<document>` - Returns one document for use as a schema reference.

Documents include `factory.schema.json` for `factory.yaml`; `agent.schema.json`, `automation.schema.json`, and `scorer.schema.json` for Markdown frontmatter; `runner.schema.json`, `router.schema.json`, `webhook.schema.json`, `benchmark_suite.schema.json`, and `benchmark_suite_task.schema.json` for YAML resources; and `common.schema.json` for shared definitions.

For completion and inline validation in the VS Code YAML extension, add the document URL on the first line:

```yaml title="factory.yaml"
# yaml-language-server: $schema=https://app.warp.dev/api/v1/factory-files/schemas/v1alpha1/factory.schema.json
schemaVersion: v1alpha1
name: payments-factory
```

YAML schemas don’t apply to Markdown frontmatter. Use one of the [definition validators](#validate-a-definition) for Markdown files.

## Directory structure

Each resource takes its name from its path: `agents/reviewer/agent.md` defines an agent named `reviewer`.

```text
factory.yaml
agents/
  foreman/
    agent.md
    skills/
      incident-triage/
        SKILL.md
  reviewer/
    agent.md
automations/
  labeled-issue/
    automation.md
runners/
  linux-build.yaml
routers/
  by-task.yaml
benchmarks/
  pull-request-review/
    suite.yaml
    tasks/
      broken-doc-link.yaml
scorers/
  tests-run/
    scorer.md
skills/
  repository-conventions/
    SKILL.md
webhooks/
  internal-ci.yaml
```

See the [example factory definition](#example-factory-definition), the minimal [`01-single-repo-quickstart`](https://github.com/warpdotdev/warp-factory-examples/tree/main/examples/01-single-repo-quickstart), or the full [`02-sdlc-issue-to-pr`](https://github.com/warpdotdev/warp-factory-examples/tree/main/examples/02-sdlc-issue-to-pr).

## `factory.yaml`

**Required resource.** The root document names the factory, scopes it to repositories, and sets execution defaults.

```yaml title="factory.yaml"
schemaVersion: v1alpha1
name: payments-factory
repositories:
  - owner: acme
    name: payments-service
agentDefaults:
  model: auto
```

### `schemaVersion`

**Required.** Every definition sets `schemaVersion: v1alpha1`.

### `name`

**Required.** The factory’s name.

### `description`

**Optional.** What the factory is for.

### `alias`

**Optional.** The handle used to @-mention the foreman on platforms such as Slack and Linear. The factory dashboard labels it **Foreman name**. It accepts up to 60 letters, numbers, spaces, `.`, `_`, and `-`, and is case-insensitively unique in the workspace.

### `credentialStrategy`

**Optional.** Whose credentials runs use: `EXECUTOR` for the executing principal, or `CREATOR` for the user who created the run. `CREATOR` requires a paid plan. Omit the key to preserve the setting; otherwise, it defaults to `EXECUTOR`. Agents can override it by role.

### `codeForges`

**Optional.** The enabled code hosts: `GITHUB`, `GITLAB`, and `AZURE_DEVOPS`. Omit the key to preserve them. With multiple hosts, set `codeForge` on every repository. An empty `codeForges` list requires empty `repositories` and configures no code host.

### `repositories`

**Required.** The factory’s repositories. The list can be empty. Each entry requires `owner` and `name`; optional `codeForge` selects `GITHUB`, `GITLAB`, or `AZURE_DEVOPS`. With multiple [`codeForges`](#codeforges), every repository requires `codeForge`.

Optional `deferred` defaults to `false`. Set it to `true` to attach a repository without preparing it for every run. Warp prepares it when an agent or automation lists it in `required_repos`, or a run adds it.

```yaml
codeForges:
  - GITHUB
  - GITLAB
repositories:
  - codeForge: GITHUB
    owner: acme
    name: payments-service
  - codeForge: GITLAB
    owner: acme/platform
    name: deployment-config
```

### `benchmarkRepoSubstitutions`

**Optional.** Repository substitutions for benchmark starting states. Each entry requires `source` and `target` objects, each with `codeForge`, `owner`, and `name`. Both `codeForge` values must be `GITHUB`; the source must belong to the factory, and the target must not.

### `secrets`

**Optional.** Names of [managed secrets](https://docs.warp.dev/platform/secrets/) granted to every agent, in addition to secrets declared by an agent.

### `mcpServers`

**Optional.** [MCP servers](https://docs.warp.dev/platform/mcp/) granted to every agent, keyed by the name shown to the agent. Each entry selects exactly one transport:

-   `warpId` - A Warp-managed MCP server ID.
-   `command` - A stdio command. Optional `args` is a list of strings, and optional `env` maps names to string values.
-   `url` - An absolute HTTP or HTTPS URL. Optional `headers` maps header names to string values.

Don’t put credentials in `env` or `headers`. Reference a [managed secret](https://docs.warp.dev/platform/secrets/) as `{{SECRET_NAME}}`, or use `warpId` for a [managed MCP installation](https://docs.warp.dev/platform/mcp/#oauth-authentication).

```yaml
mcpServers:
  sentry:
    warpId: SENTRY_MCP_SERVER_ID
```

### `cloudProviders`

**Optional.** Cloud-provider identity federation for agent runs:

-   `cloudProviders.gcp` configures Google Cloud. It requires `cloudProviders.gcp.projectNumber`, `cloudProviders.gcp.workloadIdentityFederationPoolId`, and `cloudProviders.gcp.workloadIdentityFederationProviderId`. Quote `projectNumber` so YAML keeps it as a string. Optional `cloudProviders.gcp.serviceAccountEmail` selects a service account.
-   `cloudProviders.aws.roleArn` configures AWS and is required for that provider.

```yaml
cloudProviders:
  aws:
    roleArn: arn:aws:iam::123456789012:role/warp-factory
```

### `integrations`

**Optional.** The integration providers attached to the factory: `slack`, `microsoft-teams`, `linear`, and `jira`. Each entry requires `type`. Declare at most one issue tracker because `linear` and `jira` are mutually exclusive. Code-forge access comes from `repositories`, not this list.

Omit `integrations` to preserve the currently attached providers. Set it to an empty list to detach every provider.

```yaml
integrations:
  - type: slack
  - type: linear
```

For Slack and Microsoft Teams, `slack.autoRespondToThreadReplies` and `microsoft-teams.autoRespondToThreadReplies` control whether eligible plain replies in an existing factory thread can continue work without another mention. The Slack setting defaults to `true`. The Microsoft Teams setting defaults to `true` when the shared per-factory reply setting is enabled.

```yaml
integrations:
  - type: slack
    slack:
      autoRespondToThreadReplies: false
```

`integrations[].linear.teamIds` and `integrations[].jira.projectKeys` are accepted for compatibility but don’t control issue discovery or routing. Warp omits them when rewriting the definition. Use automation filters such as `team_ids` and `project_keys`.

### `providers`

**Optional.** Accepted as a legacy alias for [`cloudProviders`](#cloudproviders) with the same keys. Use `cloudProviders` in new files. Warp writes the canonical key when it updates an older definition.

### `scorerDefaults`

**Optional.** Sets `runner`, `secrets`, and `mcpServers` for file-defined scorers. A scorer can override each value. The `mcpServers` map uses the [factory-level transport syntax](#mcpservers).

### `selfImprovement`

**Optional.** Configures scheduled self-improvement for a GitHub-backed factory:

-   `failedRunThreshold` - Distinct scored failures per agent required before a scheduled self-improvement run. Use a value from 1 through 50, or omit it for the server default.
-   `reviewerType` - The pool used to request one reviewer: `admins` (the default), `team`, `custom`, or `none`.
-   `reviewerEmails` - Required when `reviewerType` is `custom` and invalid otherwise. Values must be active members of the factory’s team.

### `agentDefaults`

**Required.** Execution defaults inherited by every agent. Declare exactly one of `model` or `harness`. Agents can override these defaults.

```yaml
agentDefaults:
  model: auto
  runner: linux-build
  environmentId: PAYMENTS_ENVIRONMENT_ID
```

### `agentDefaults.model`

**Conditionally required.** Set exactly one of `model` or `harness`. The `model_id` used for runs. See [model choice for agents](https://docs.warp.dev/agents/inference/model-choice/). `model` is shorthand for the Warp Agent harness:

```yaml
model: auto
```

is equivalent to:

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

`model` and `harness` are mutually exclusive everywhere they appear.

### `agentDefaults.harness`

**Conditionally required.** Set exactly one of `model` or `harness`. The run harness and model. The object requires `type` and `model`. `type` accepts `oz`, `claude`, `codex`, or `claude-code` (an alias for `claude`). Prefer the canonical [harness identifier](https://docs.warp.dev/platform/harnesses/#harness-identifiers) used by the CLI and the Warp Platform API. See [supported harnesses](https://docs.warp.dev/platform/harnesses/) for availability and behavior.

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

Optional `auth` requires `source`. `managedSecret` also requires `agentDefaults.harness.auth.secretName`; `workerEnvironment` rejects it and requires a self-hosted `workerHost`. Set the source with `agentDefaults.harness.auth.source`.

The `oz` harness supplies its own credentials and rejects `auth` and `reasoningLevel`. Third-party harnesses accept optional `reasoningLevel`.

For per-agent harnesses and managed-secret authentication, see [`03-multi-harness`](https://github.com/warpdotdev/warp-factory-examples/tree/main/examples/03-multi-harness). To use the dashboard instead, see [configuring a third-party harness](https://docs.warp.dev/factories/factory-agents/#configuring-a-third-party-harness).

### `agentDefaults.runner`

**Optional.** The name of a runner defined under [`runners/`](#runnersnameyaml) that provides the compute for runs.

### `agentDefaults.environmentId`

**Optional.** The ID of an existing [environment](https://docs.warp.dev/platform/environments/) for runs. Omit it to let Warp manage the workspace from the factory’s repositories.

### `agentDefaults.secrets`

**Optional.** Managed secrets inherited by agents without their own `secrets` list. An agent-level list replaces this one; factory-wide [`secrets`](#secrets) still apply.

### `agentDefaults.mcpServers`

**Optional.** MCP servers inherited by agents without their own map, using the [`mcpServers`](#mcpservers) syntax. An agent-level map replaces this one; factory-wide servers still apply.

### `agentDefaults.workerHost`

**Optional.** Where runs execute: `warp` for Warp-hosted compute, or the ID of a connected [self-hosted worker](https://docs.warp.dev/factories/self-hosting/). Omit the key for the workspace default. At the agent or automation level, use `null` or an empty string to clear an inherited host. Configure the backend on the worker; the definition selects only the worker and runner.

### `agentDefaults.computerUseModel`

**Optional.** The `model_id` used by Computer Use. Omit it for automatic selection.

```yaml
agentDefaults:
  model: auto
  computerUseModel: claude-5-sonnet-high
```

Use `computer-use-agent-auto` for automatic selection. A model suffix selects its effort level; `thinking` enables thinking, and `xhigh-fast` selects fast mode.

| Model | Supported values |
| --- | --- |
| Auto | `computer-use-agent-auto` |
| Claude Sonnet 5 | `claude-5-sonnet-low`, `claude-5-sonnet-medium`, `claude-5-sonnet-high`, `claude-5-sonnet-xhigh`, `claude-5-sonnet-max` |
| Claude Opus 5 | `claude-5-opus-low`, `claude-5-opus-medium`, `claude-5-opus-high`, `claude-5-opus-xhigh`, `claude-5-opus-xhigh-fast`, `claude-5-opus-max` |
| Claude Fable 5.1 | `claude-5-1-fable-low`, `claude-5-1-fable-medium`, `claude-5-1-fable-high`, `claude-5-1-fable-xhigh`, `claude-5-1-fable-max` |
| Claude Fable 5 | `claude-5-fable-low`, `claude-5-fable-medium`, `claude-5-fable-high`, `claude-5-fable-xhigh`, `claude-5-fable-max` |
| Claude Opus 4.8 | `claude-4-8-opus-low`, `claude-4-8-opus-medium`, `claude-4-8-opus-high`, `claude-4-8-opus-xhigh`, `claude-4-8-opus-xhigh-fast`, `claude-4-8-opus-max` |
| Claude Opus 4.7 | `claude-4-7-opus-high`, `claude-4-7-opus-xhigh`, `claude-4-7-opus-max` |
| Claude Opus 4.6 | `claude-4-6-opus-high`, `claude-4-6-opus-max` |
| Claude Sonnet 4.6 | `claude-4-6-sonnet-high`, `claude-4-6-sonnet-max` |
| Claude Opus 4.5 | `claude-4-5-opus`, `claude-4-5-opus-thinking` |
| Claude Sonnet 4.5 | `claude-4-5-sonnet`, `claude-4-5-sonnet-thinking` |
| Claude Haiku 4.5 | `claude-4-5-haiku` |

The value must be available to your plan and workspace. See [model choice for agents](https://docs.warp.dev/agents/inference/model-choice/) for availability and data retention.

Agents and automations can override `computerUseModel`. An omitted or `null` agent value inherits `agentDefaults.computerUseModel`; an automation inherits the selected agent’s effective value. The setting applies only to Computer Use on the Warp Agent harness (`type: oz`). Warp preserves but ignores it otherwise. It can appear with `model` or `harness` because it doesn’t select the main model.

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

**Required resource.** Every definition includes at least one agent file. Each agent has one file. The directory names the agent, the YAML frontmatter configures it, and the Markdown body contains its instructions.

```markdown title="agents/reviewer/agent.md"
---
description: Reviews factory-produced pull requests
agentType: REVIEW
---

Review each pull request against the repository's standards. Request
changes when tests are missing; never approve your own edits.
```

All frontmatter keys are optional:

-   `description` - What the agent does.
-   [`agentType`](#agenttype) - The agent’s role.
-   `credentialStrategy` - Overrides the factory-level [`credentialStrategy`](#credentialstrategy). Omit it to keep the agent’s current setting.
-   `spawnableBy` - Agents allowed to start this agent. Omit it to allow only the foreman, use an empty list to allow none, or list exact agent names.
-   `model` or `harness`, `runner`, `environmentId`, `secrets`, `mcpServers`, `workerHost`, `computerUseModel` - Override the corresponding [`agentDefaults`](#agentdefaults).
-   `idleTimeoutMinutes` - Keeps a completed session available for follow-up for 1 through 60 minutes. Omit it or use `null` to inherit. Without an inherited or run-level value, Warp uses 10 minutes, or 60 minutes for an orchestrated child run.
-   `required_repos` - Repositories prepared for every run by this agent. Each item requires `required_repos[].owner` and `required_repos[].name`. Use `required_repos[].codeForge` to distinguish the same repository across hosts.

An agent’s `harness` object is a sparse override of [`agentDefaults.harness`](#agentdefaultsharness). Set `auth` to `null` to clear inherited authentication. Agent-level `mcpServers` entries use the same transport keys as the factory-level [`mcpServers`](#mcpservers) map.

### `agentType`

**Optional.** The agent’s role: `CUSTOM` (default), `FOREMAN` (alias `MAIN`), `TRIAGE`, `SPEC`, `IMPLEMENT`, `REVIEW`, or `VERIFY`. Every factory has one foreman, which serves as its entry point and the default automation target. See [factory agents](https://docs.warp.dev/factories/factory-agents/) for role behavior.

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

**Optional resource.** Each automation has one file. The directory names the automation, the frontmatter defines its triggers and execution settings, and the Markdown body contains the starting prompt.

```markdown title="automations/labeled-issue/automation.md"
---
agent: foreman
triggers:
  - provider: github
    event: issue_labeled
    filter:
      repos: [acme/payments-service]
      labels: [factory-ready]
---

Review the labeled issue and decide the next required stage. Return
unresolved product questions to a human.
```

### `enabled`

**Optional.** Turns the automation on or off. Defaults to `true`.

### `agent`

**Optional.** The agent that handles the automation’s runs. Defaults to the foreman.

### `triggers`

**Required.** One or more events that start runs. Every automation requires `triggers`. Each trigger declares `provider` and `event`, and can include `filter` or, for scheduled runs, `schedule`.

The providers and their events:

-   `azure_devops` - `pull_request_closed`, `pull_request_commented`, `pull_request_created`, `pull_request_mentioned`, `pull_request_merged`, `pull_request_updated`, `push`, `work_item_assigned`, `work_item_created`, `work_item_labeled`, `work_item_mentioned`
-   `github` - `check_run_rerequested`, `check_suite_completed`, `check_suite_rerequested`, `issue_assigned`, `issue_commented`, `issue_created`, `issue_labeled`, `issue_mentioned`, `pull_request_assigned`, `pull_request_closed`, `pull_request_commented`, `pull_request_labeled`, `pull_request_mentioned`, `pull_request_merged`, `pull_request_opened`, `pull_request_ready`, `pull_request_reopened`, `pull_request_review_requested`, `pull_request_review_submitted`, `pull_request_synchronized`, `push`, `workflow_run_completed`
-   `gitlab` - `bot_mentioned`, `merge_request`, `push`
-   `linear` - `agent_session_created`, `comment_created`, `issue_assigned`, `issue_created`, `issue_labeled`, `issue_state_changed`
-   `jira` - `agent_session_created`, `issue_created`, `issue_labeled`, `status_changed`
-   `slack` - `app_mention`, `member_joined_channel`, `message_dm`, `message_im`, `message_mpim`, `message_posted`, `reaction_added`
-   `teams` - `app_mention`, `message_posted`
-   `schedule` - `cron_fired`
-   `webhook` - `received`
-   `factory` - `work_item_stage_changed`

Slack, Microsoft Teams, Linear, and Jira triggers require the matching [integration](https://docs.warp.dev/platform/integrations/) to be connected. Code-forge triggers use the factory’s repositories and provider connection; see the [GitHub](https://docs.warp.dev/factories/integrations/github/), [GitLab](https://docs.warp.dev/factories/integrations/gitlab/), and [Azure DevOps](https://docs.warp.dev/factories/integrations/azure-devops/) integration guides. `webhook` triggers listen to [custom webhooks](https://docs.warp.dev/factories/webhooks/) declared under [`webhooks/`](#webhooksnameyaml).

### `triggers[].filter`

**Conditionally required.** Required for `webhook` / `received`; optional for other triggers. Narrows which events start runs. Available keys depend on the provider and event, such as `repos`, `labels`, and `authors` for GitHub or `channels`, `users`, and `keywords` for Slack. Keys combine with AND. Within a key’s list, any value can match. An omitted key matches everything.

Most canonical keys accept matcher objects with `in` and `not_in`. The name-based aliases `issues`, `projects`, `states`, `teams`, `channels`, `users`, and `itemUsers` take plain lists; Warp resolves their values to IDs.

A `webhook` trigger for `received` requires `webhook_ids`: a one-item list with one webhook UID. It supports `in` only and doesn’t accept a file name. To listen to multiple webhooks, add one trigger per UID. The optional `payload` pattern matches against the delivery’s JSON body. See [webhook payload filters](https://docs.warp.dev/factories/automations/#payload-filters-for-webhook-triggers) for the pattern syntax.

Filter keys by provider:

-   Factory: `stages`.
-   Azure DevOps: `assignees`, `authors`, `base_branches`, `branches`, `labels`, `mentioned`, `repos`, `source_repos`, and `work_item_types`.
-   GitHub: `assignees`, `authors`, `baseBranches`, `base_branches`, `branches`, `conclusions`, `keywords`, `labels`, `mentioned`, `paths`, `prNumbers`, `pr_numbers`, `repos`, `review_states`, `reviewer_teams`, `reviewers`, and `workflows`.
-   GitLab: `actions`, `base_branches`, `branches`, `mentioned`, and `repos`.
-   Jira: `keywords`, `labels`, `project_keys`, and `status_ids`.
-   Linear: `assignee_ids`, `creator_ids`, `issue_ids`, `issues`, `keywords`, `labels`, `mentioned_user_ids`, `project_ids`, `projects`, `state_ids`, `states`, `team_ids`, and `teams`.
-   Schedule: `schedule_ids` is server-managed and cannot be set in a factory definition.
-   Slack: `channel_ids`, `channels`, `emojis`, `itemUsers`, `item_user_ids`, `keywords`, `user_ids`, and `users`.
-   Microsoft Teams: `channel_ids`, `keywords`, `team_ids`, and `user_ids`.
-   Webhook: `payload` and `webhook_ids`.

Matcher objects use `in` to include values and `not_in` to exclude them. Webhook `payload` also accepts `exists`. Microsoft Teams `team_ids` and `channel_ids` support only `in`.

For Microsoft Teams, `team_ids` contains exactly one Microsoft Graph team UUID, and `channel_ids` contains at least one channel ID.

`baseBranches` and `prNumbers` are authoring aliases for `base_branches` and `pr_numbers`. `teams`, `projects`, `states`, `issues`, `channels`, `users`, and `itemUsers` are name-based aliases for their `_ids` counterparts. An alias and its canonical key are mutually exclusive.

```yaml
triggers:
  - provider: webhook
    event: received
    filter:
      webhook_ids: [WEBHOOK_UID]
      payload:
        status: [failed]
```

### `triggers[].schedule`

**Conditionally required.** Required for `schedule` / `cron_fired` and invalid for other triggers. Defines an inline UTC schedule for a `schedule` / `cron_fired` trigger. The object requires `cron`, which accepts a five-field expression or a descriptor such as `@daily` or `@every 1h`. Use optional `name` to distinguish multiple schedules; at most one can omit it. Changing only `cron` updates a schedule, while changing `name` replaces it.

```yaml
triggers:
  - provider: schedule
    event: cron_fired
    schedule:
      name: weekday-mornings
      cron: "0 9 * * 1-5"
```

### Execution overrides

**Optional.** An automation can declare `displayName`, plus `model` or `harness`, `runner`, `environmentId`, `secrets`, `mcpServers`, `workerHost`, `computerUseModel`, `idleTimeoutMinutes`, and `required_repos`. Use `null` to clear `displayName`. Execution settings override the target agent for runs from this automation.

Automation `required_repos` entries extend the target agent’s list. Each item requires `required_repos[].owner` and `required_repos[].name`; use `required_repos[].codeForge` to distinguish the same repository across hosts.

The `harness` object uses the same sparse override as an agent. Automation-level `mcpServers` use the [factory-level transport syntax](#mcpservers). Omit `idleTimeoutMinutes`, or set it to `null`, to inherit the target agent’s value.

## `runners/<name>.yaml`

**Optional resource.** Runner files define compute. Agents and automations select a file by name with `runner`. See [cloud agent runners](https://docs.warp.dev/factories/runners/) for runtime behavior and [`02-sdlc-issue-to-pr`](https://github.com/warpdotdev/warp-factory-examples/tree/main/examples/02-sdlc-issue-to-pr) for Linux and macOS examples.

```yaml title="runners/linux-build.yaml"
description: Linux runner for payments builds and tests
setupCommands:
  - corepack enable
instanceShape:
  vcpus: 4
  memoryGb: 8
platform:
  os: linux
  arch: x86_64
  linux:
    dockerImage: ubuntu:22.04
```

### `description`

**Optional.** A description of the runner.

### `setupCommands`

**Optional.** Shell commands that run in order while the sandbox is prepared.

### `instanceShape`

**Optional.** The compute size. When set, `instanceShape` requires both `vcpus` and `memoryGb`. Omit it for the workspace default. Linux and Windows require powers of two. macOS accepts 4 vCPUs with 7 GB, 6 vCPUs with 14 GB, 8 vCPUs with 14 GB, 12 vCPUs with 28 GB, or 12 vCPUs with 56 GB.

### `platform`

**Required.** The operating system and architecture. `os` accepts `linux` (default), `macos`, or `windows`. `arch` accepts `x86_64` (the Linux default and only Windows option) or `aarch64` (supported on Linux and required on macOS).

Linux runners require `platform.linux.dockerImage`. For macOS, `platform.mac.version` accepts `"14"`, `"15"`, `"26"`, or `"27"`. Quote the version; omitting `platform.mac` uses `"26"`.

For a private Linux image, set `linux.registryCredentialSecretName` to the name of a managed Docker registry (`docker_registry`) or AWS ECR (`aws_ecr_credential`) credential. The credential’s registry host must match the host in `linux.dockerImage`.

### `failureSessionRetentionMinutes`

**Optional.** Keeps a failed session open for inspection for 1 through 60 minutes. Omit it to use the environment setting.

## `routers/<name>.yaml`

**Optional resource.** Router files define factory-owned custom model routers. Use the file name anywhere the definition accepts a model.

| Field | Requirement | Description |
| --- | --- | --- |
| `name` | Optional | Display label. |
| `type` | Required | `complexity` or `prompt`. |
| `default` | Required | Concrete model used when no route matches. |
| `routing` | Optional | Type-specific routing rules. |

```yaml title="routers/by-task.yaml"
name: By task
type: prompt
default: claude-4-6-sonnet-high
routing:
  - description: Routine documentation changes
    model: claude-4-5-haiku
  - description: Complex implementation or debugging
    model: claude-4-8-opus-high
```

For `type: complexity`, optional `routing.easy`, `routing.medium`, and `routing.hard` map complexity levels to concrete models. For `type: prompt`, `routing` is an ordered list of `routing.description` and `routing.model` pairs. Each pair requires both fields. `routing` is optional for either type. Targets must be concrete supported models, not Auto models or other routers. See [custom model routers](https://docs.warp.dev/agents/inference/custom-routers/) for routing behavior.

Factory members who can access the router can also select it from model catalogs in the factory dashboard, including agent settings and benchmark configurations.

## `benchmarks/<suite-slug>/suite.yaml`

**Optional resource.** Benchmark suite files define trials for one agent, with reusable configurations and an ordered task list. The directory slug is the suite’s stable identity; changing `name` doesn’t move the file. See [benchmarks](https://docs.warp.dev/factories/benchmarks/) for how to run a suite.

```yaml title="benchmarks/pull-request-review/suite.yaml"
name: Pull request review
description: Compare configurations for the review agent.
agent: reviewer
configurations:
  - name: Baseline
    agents:
      - agent: reviewer
        model: auto
  - name: Candidate
    agents:
      - agent: reviewer
        model: auto-efficient
tasks:
  - broken-doc-link
```

### `name`

**Required.** The suite display name, which must be unique in the factory.

### `description`

**Optional.** A short summary of what the suite measures.

### `agent`

**Required.** The factory agent used for every task in the suite.

### `configurations`

**Optional.** One to six reusable configurations. Warp uses these presets when a benchmark run doesn’t supply configurations. Each configuration requires a unique `name`.

Optional `role` is deprecated metadata. Warp ignores it and omits it when rewriting the suite.

The optional `agents` list pins factory agents to models and harnesses for the configuration’s trials. Each `configurations[].agents[]` item names an `agent` and includes exactly one of `model` or `harness`. A `harness` requires `type` and `model`; `type` accepts `oz`, `claude`, `claude-code`, and `codex`. Optional `auth` follows the [harness authentication rules](#agentdefaultsharness). List an agent once per configuration. Omitted agents use their settings at launch time.

### `tasks`

**Optional.** An ordered list of unique task slugs. Each slug matches one file under `benchmarks/<suite-slug>/tasks/`, and every task file appears once. A suite without tasks can be saved but not run.

## `benchmarks/<suite-slug>/tasks/<task-slug>.yaml`

**Optional resource.** Each task file belongs to its parent suite. The file name without `.yaml` is the stable task slug.

```yaml title="benchmarks/pull-request-review/tasks/broken-doc-link.yaml"
title: Fix a broken documentation link
prompt: Find the broken internal documentation link and update it.
successCriteria: The destination resolves and the link text names the destination.
startingRepoRefs:
  - github.com:acme/payments-docs@0123456789abcdef0123456789abcdef01234567
```

### `title`

**Required.** The task display name. It doesn’t need to match the task slug.

### `prompt`

**Required.** The instructions sent to the agent.

### `successCriteria`

**Required.** The Correctness Scorer’s evaluation criteria.

### `sourceRunId`

**Optional.** The ID of the prior run that produced the task. This records provenance and can refer to a deleted run.

### `tags`

**Optional.** An ordered list of task labels.

### `linearSeed`

**Optional.** JSON-compatible starting state for the trial’s isolated Linear workspace.

### `startingRepoRefs`

**Optional.** The GitHub or GitLab repositories and commits used as the task’s starting state. Each entry accepts `github.com:OWNER/REPO@COMMIT_SHA`, `gitlab.com:OWNER/REPO@COMMIT_SHA`, or an object with `codeForge` (`GITHUB` or `GITLAB`), `owner`, `repo`, and `ref`. All four object fields are required. `COMMIT_SHA` and `ref` must be full 40-character commit SHAs, not branches or tags. Omit the key to use the agent’s checkout defaults.

## `scorers/<name>/scorer.md`

**Optional resource.** Scorer files define LLM judges that classify sampled runs against a rubric. The directory is a stable slug; `name` identifies the scorer. Frontmatter defines the classification contract, and the Markdown body holds the rubric. See [configuring scorers](https://docs.warp.dev/factories/measure-and-improve/scorers/) for how scores are used.

```markdown title="scorers/tests-run/scorer.md"
---
name: tests-run
description: Checks whether implementation runs include test evidence.
agents:
  - reviewer
labels:
  - value: tests_run
    description: The transcript contains a test command and its result.
    score: 1
  - value: tests_skipped
    score: 0
passingScore: 1
samplingRate: 25
model: claude-4-5-haiku
---
Evaluate whether the agent ran the relevant tests before finishing. Return
exactly one declared label.
```

### `name`

**Required.** The scorer’s identity. Changing it doesn’t move the directory.

### `description`

**Optional.** A short summary of what the scorer checks.

### `agents`

**Required.** The agents whose runs the scorer evaluates. A string names one agent and scores only that run. To include child runs as evidence, use an object with required `name` and optional `includeDescendants: true`.

```yaml
agents:
  - name: foreman
    includeDescendants: true
```

### Scorer execution settings

**Optional.** `runner`, `secrets`, and `mcpServers` override the factory’s `scorerDefaults` for this scorer. Scorer-level `mcpServers` use the [factory-level transport syntax](#mcpservers). Set shared values under `scorerDefaults` in `factory.yaml`.

### `output`

**Optional.** The scorer output form. `classification` is the supported value.

### `labels`

**Required.** One to 20 classifications. Each label requires a unique `value` and a `score` from 0 through 1; `description` is optional. At least one label must meet `passingScore`, and at least one must fall below it.

### `passingScore`

**Required.** The passing threshold, from 0 through 1.

### `samplingRate`

**Optional.** The percentage of eligible runs to score, from 0 through 100. It defaults to 25, rounds to two decimal places, and disables automatic scoring at 0.

### `model`

**Required.** The model that judges runs.

### `selfImprovement`

**Optional.** When `true`, failing scores can feed the self-improvement flow, which proposes definition changes in pull requests. Defaults to `false`.

## `webhooks/<name>.yaml`

**Optional resource.** Webhook files define [authenticated URLs](https://docs.warp.dev/factories/webhooks/) for JSON POST requests. Automation `webhook` triggers subscribe to them; the file name names the webhook. `secretName` references an existing [managed secret](https://docs.warp.dev/platform/secrets/), not secret material.

```yaml title="webhooks/internal-ci.yaml"
authMode: token
secretName: INTERNAL_CI_WEBHOOK_SECRET
deliveryIdHeader: X-CI-Run-Id
enabled: true
```

### `authMode`

**Optional.** How deliveries authenticate: `token` (default, using an `Authorization: Bearer` header), `url_token` (secret in the URL path), or `signature` (the provider’s signature scheme). See [webhook authentication modes](https://docs.warp.dev/factories/webhooks/#authentication-modes).

### `signatureScheme`

**Conditionally required.** Required for `authMode: signature` and invalid otherwise. The provider signature to verify: `github`, `pagerduty`, `sentry`, `standard_webhooks`, `stripe`, or `vercel`.

### `secretName`

**Required.** The managed secret containing the bearer token, URL token, or provider signing secret. A `url_token` secret becomes part of the ingress URL and accepts only letters, digits, `-`, `.`, `_`, and `~`.

### `deliveryIdHeader`

**Optional.** The sender’s delivery ID header, used to deduplicate retries. It accepts up to 64 characters and must be a valid HTTP header name. Credential-bearing headers such as `Authorization`, `Cookie`, and provider signature headers are rejected.

### `enabled`

**Optional.** Whether the webhook accepts deliveries. Defaults to `true`. Use `false` to stop deliveries immediately without deleting the webhook, or to create it before the provider issues a signing secret. See [setting up a Vercel webhook](https://docs.warp.dev/factories/webhooks/vercel/).

On a Warp-managed factory, creating a webhook in the dashboard writes this file for you and stores the secret under the name you enter in the “Secret name” field.

You can’t change `authMode` or `signatureScheme` on an existing webhook. Delete and recreate the webhook, or create the replacement under a different name.

## Skills

**Optional resource.** A skill is a directory containing `SKILL.md`, not a YAML key. Put shared skills under `skills/` and agent-specific skills under `agents/<name>/skills/`. See [factory skills](https://docs.warp.dev/factories/factory-skills/) for placement and [Skills](https://docs.warp.dev/agents/capabilities/skills/) for the file format.

## Example factory definition

This definition includes one repository, a foreman, an automation triggered by a GitHub label, and a Linux runner. Replace `PAYMENTS_ENVIRONMENT_ID` and `SENTRY_MCP_SERVER_ID` with existing resource IDs.

For more complete definitions, see [warp-factory-examples](https://github.com/warpdotdev/warp-factory-examples).

```yaml title="factory.yaml"
schemaVersion: v1alpha1
name: payments-factory
description: Processes approved work for the payments service
alias: payments
repositories:
  - owner: acme
    name: payments-service
agentDefaults:
  model: auto
  runner: linux-build
  environmentId: PAYMENTS_ENVIRONMENT_ID
```

```markdown title="agents/foreman/agent.md"
---
description: Routes approved payments work through the factory
agentType: FOREMAN
secrets:
  - SENTRY_AUTH_TOKEN
mcpServers:
  sentry:
    warpId: SENTRY_MCP_SERVER_ID
---

Own each work item from intake through human handoff.

Confirm the request is ready before dispatching implementation. Require
repository validation and independent review before marking work complete.
```

```markdown title="automations/labeled-issue/automation.md"
---
enabled: true
agent: foreman
triggers:
  - provider: github
    event: issue_labeled
    filter:
      repos: [acme/payments-service]
      labels: [factory-ready]
---

Review the labeled issue and decide the next required stage. Preserve the
issue's acceptance criteria and return unresolved product questions to a human.
```

```yaml title="runners/linux-build.yaml"
description: Linux runner for payments builds and tests
setupCommands:
  - corepack enable
instanceShape:
  vcpus: 4
  memoryGb: 8
platform:
  os: linux
  arch: x86_64
  linux:
    dockerImage: ubuntu:22.04
```

### Routing to a self-hosted worker

To use a [managed self-hosted worker](https://docs.warp.dev/factories/infrastructure-and-security/#choose-an-execution-host), set `agentDefaults.workerHost` to the worker ID. Agents and automations can override it.

```yaml title="factory.yaml"
agentDefaults:
  model: auto
  runner: linux-build
  workerHost: SELF_HOSTED_WORKER_ID
```

Pair `workerHost` with a runner whose `platform` matches the worker. Follow the [self-hosting quickstart](https://docs.warp.dev/factories/self-hosting/quickstart/) to connect a worker, or copy [`07-self-hosted-worker`](https://github.com/warpdotdev/warp-factory-examples/tree/main/examples/07-self-hosted-worker).

## Related pages

-   [**Factory MCP for coding agents**](https://docs.warp.dev/factories/factory-mcp/) - Read the schema and validate a tree from any coding agent, and send work to a factory.
-   [**GitHub integration**](https://docs.warp.dev/factories/integrations/github/#factory-definition-pull-request-checks) - How the **warp/factory-config** check appears on pull requests, and what to check when it doesn’t.
-   [**Factory dashboard**](https://docs.warp.dev/factories/factory-dashboard/#edit-definitions-in-the-factory-definition-tab) - Where a Warp-managed definition is edited and validated on save.
-   [**warp-factory-examples**](https://github.com/warpdotdev/warp-factory-examples) - Complete definitions to copy, plus the validator script and a CI workflow that runs it.
