Workbenches is an open standard. Read why
Docs Spec 1 manifest

The Workbench standard

Spec 1 manifest

The Workbench standard defines a small, versioned package that prepares an AI to do a class of work. This page describes every field of a spec 1 manifest, the stable form of the standard.

The standard is open source and licensed under the Apache License 2.0. The specification, the JSON schema, the event protocol, and the outcomes contract are the interoperability contract. The wb CLI is the reference engine, not the only permitted host.

What the standard covers#

A Workbench is a repository-owned execution recipe. It is not an agent, and it does not define a DAG, workflow, user interface, or product-level run. A host can add those things around it.

Neither spec defines setup hooks, knowledge-file semantics, orchestration, user interfaces, or registry behavior. Implementations must reject unsupported runners, runtimes, images, or integration transports explicitly.

Package layout#

.workbenches/
  core/
    workbench.yml
    instructions.md
    skills/
      migrations/
        SKILL.md

Each immediate child directory of .workbenches/ is one Workbench. Its manifest is named workbench.yml. The reference engine refuses a package anywhere else.

A complete example#

spec: 1
version: 0.1.0

name: migrations
description: Design, review, and safely apply project migrations.

runner: opencode
model:
    id: openai/gpt-5.6-terra
    routes:
        - provider: openai
        - provider: openrouter

instructions: ./instructions.md
skills:
    - ./skills/migrations

tools:
    - cargo
    - dbctl

mcps:
    - name: database
      transport: http
      url: https://api.example.com/mcp
      headers:
          Authorization: Bearer ${DATABASE_API_TOKEN}

env:
    DATABASE_API_TOKEN:
        required: false

workspaces:
    api:
        required: true
        access: read-write

requirements:
    os: [linux, macos]
    cpu: 4
    memory_gb: 8

runtimes:
    local: {}
    docker:
        image: ghcr.io/example/migrations:0.1.0

Fields#

Required fields are spec, version, name, runner, model, instructions, and runtimes. No other top-level field is allowed.

Field Type Required Meaning
spec integer 1 yes The manifest schema version.
version string yes The author's semantic release version, such as 0.1.0 or 1.2.0-rc.1.
name string yes The package name. The default alias and registry name.
description string no One line on what the Workbench is for.
runner string yes The harness that executes the work, such as opencode, pi, or claude-code.
model object yes The model policy. See Model.
runner_config string no A package-relative file or directory of runner-native configuration.
instructions string yes A package-relative Markdown file.
skills list of strings no Package-relative skill directories. Defaults to [].
tools list of strings no CLI executables that must exist before a run starts. Defaults to [].
mcps list of objects no Remote MCP servers. See MCP servers. Defaults to [].
env map no Environment variable names the Workbench reads. See Environment.
workspaces map no Named workspaces beyond the primary one. See Workspaces.
requirements object no What the environment must satisfy. See Requirements.
runtimes map yes The runtimes the author supports, in order. See Runtimes.

spec and version#

spec is the integer Workbench schema version. Engines dispatch on it, accept every spec they support, and reject any other value with Manifest spec N is not supported by this engine; upgrade wb. They never guess at an unknown spec.

version is the author's semantic release version. Source revisions and content digests remain the authority for reproducibility. The registry requires each pushed version to be higher than the last.

Model#

runner: opencode
model:
    id: openai/gpt-5.6-terra

model.id uses lab/model, where lab is the organization that defines the model. It is not a provider selection. It must match ^[a-z0-9][a-z0-9._-]*/[A-Za-z0-9][A-Za-z0-9._:/-]*$.

An engine resolves the model through verified model metadata and chooses the first route for which the selected runner has compatible credentials. The metadata version used for a run is part of the resolved runner configuration.

model.routes restricts or orders the providers that may serve the model. It is a non-empty list:

Field Type Required Meaning
provider string yes A provider identifier matching ^[a-z0-9][a-z0-9._-]*$, such as openai or openrouter.
model string no The provider-native model identifier, when it differs from the catalog or the model is absent from it.

Routes must serve the same model identity. They are not fallbacks to different models.

model:
    id: private-lab/review-model
    routes:
        - provider: internal-gateway
          model: deployment-42
runner_config: ./runner

An unknown model requires an explicit native model identifier for every route and a packaged runner_config.

The author locks the runner and model policy. A person starting a run cannot replace the runner, model, allowed provider routes, or packaged native runner configuration, so a published Workbench stays equivalent to the configuration its maintainer tested.

runner_config#

runner_config is a package-relative file or directory interpreted only by the selected runner adapter. Pi requires a directory. The path must stay inside the package and cannot contain symbolic links, credential files, or literal credential values. Configuration can name environment bindings declared by the manifest; values are supplied only when the Workbench runs.

Credentials#

A Workbench package never owns a person's runner credentials. Engines verify that at least one allowed route is ready before sending a model request. When a runner has a documented command-line sign-in, an engine can offer it during connection setup. An engine must never inject login commands or simulated input into a runner conversation, and must not parse, copy into package state, upload, or print provider token contents.

Instructions and skills#

instructions is a package-relative Markdown file. Each skills entry is a package-relative directory containing a portable SKILL.md. Adapters expose skills through the runner's native on-demand skill mechanism.

Tools#

tools names CLI executables that must be available in the selected runtime before a run starts. A tool on the host does not satisfy a container or sandbox runtime. Presence is checked, not version compatibility or behavior.

MCP servers#

mcps describes remote Streamable HTTP servers.

Field Type Required Meaning
name string yes Lowercase and hyphenated, matching ^[a-z0-9]+(?:-[a-z0-9]+)*$.
transport http no The only transport. Defaults to http.
url string yes An http:// or https:// URL.
headers map of strings no Request headers. Values can reference declared environment variables as ${NAME}.

A server whose headers reference an unset optional variable is omitted from the run. An unset required variable rejects the run. Adapters keep the reference instead of placing the secret value in generated configuration or dry-run output.

Environment#

env:
    DATABASE_API_TOKEN:
        required: false

env maps variable names to declarations. Names match ^[A-Z][A-Z0-9_]*$. Each declaration has one optional field, required, a boolean that defaults to true.

Environment values never appear in the manifest. The person or host starting a run supplies them.

Workspaces#

Every run has one primary workspace, chosen by whoever starts the run. It is the runner's working directory and is read-write. A Workbench can declare named workspaces when its expertise spans more repositories or directories:

workspaces:
    api:
        required: true
        access: read-write
    schemas:
        required: false
        access: read-only

Names are lowercase and hyphenated, and primary is reserved. required defaults to true and access defaults to read-only; access is read-only or read-write. Declarations hold logical names and access, never machine paths.

A host binds a directory to each name for one run. The reference CLI takes repeatable --workspace NAME=PATH and rejects missing required bindings, undeclared names, unavailable directories, and duplicate resolved paths before launch. Runtimes expose each location as WORKBENCH_WORKSPACE_<NAME>, with hyphens replaced by underscores.

The local runtime checks readability or writability but cannot stop a host process from writing elsewhere. Engines must not present local access declarations as an isolation boundary.

Requirements#

requirements is optional, and every field in it is optional. An absent field places no constraint.

requirements:
    os: [linux, macos]
    arch: [arm64, x64]
    cpu: 4
    memory_gb: 8
    disk_gb: 20
    gpu: false
Field Type Meaning
os non-empty list of linux, macos, windows The environment runs any one of them.
arch non-empty list of x64, arm64 The environment uses any one of them.
cpu positive integer Minimum vCPUs.
memory_gb positive number Minimum memory in GiB.
disk_gb positive number Minimum disk in GiB.
gpu boolean, default false true means the Workbench needs a GPU.

Requirements are checked against the selected runtime before it is prepared, so a mismatch stops the run before it spends anything. A requirement an engine cannot verify or enforce must be reported as unchecked, never as satisfied. How each runtime checks them is on Runtimes.

Runtimes#

runtimes maps a provider name to its configuration. It must declare at least one runtime. Order matters: the first entry is the default.

Provider Configuration
local None. Write local: {} or local:.
docker image (required), docker (optional host engine binding).
e2b image (required).
daytona class (required: linux, windows, gpu, or macos), image (optional in the schema, required to run).

image is either a string naming a published image or a build object:

runtimes:
    docker:
        image:
            build: ./Dockerfile.workbench
            context: .

build is a package-relative Dockerfile and context is package-relative, defaulting to .. Both must stay within the containing repository. Providers decide how to cache prepared images, but the result must be equivalent to preparing the declared input again.

The reference engine runs only the linux Daytona class. It creates the sandbox from the Daytona entry's own published image, with no fallback to another entry's image; a missing image or a build object fails and names runtimes.daytona.image.

A Docker entry can request the host's Docker engine:

runtimes:
    docker:
        image: ghcr.io/example/project-workbench:0.4.0
        docker:
            engine:
                mode: host

mode: host is the only mode. The declaration is not authorization: the person starting each run must grant it, with --allow-host-docker in the reference CLI. Host engine access gives code in the Workbench effective administrative control of the Docker host. The image must contain the Docker CLI.

An unknown provider name is an error and must not silently fall back to the host. runtime, top-level image, and top-level docker are spec 0 fields and are invalid in spec 1.

Runtime selection#

The person or host starting a run can name one declared runtime. The reference CLI accepts --runtime <name> on wb run, wb smoke, wb build, and wb create. Without it, the first declared runtime is used. Naming an undeclared runtime is an error that lists the declared ones.

Execution lifecycle#

  1. Resolve and validate the Workbench package.
  2. Select the named runtime provider and prepare its environment.
  3. Mount or copy the primary workspace, named workspaces, and package assets, then bind the run environment.
  4. Verify every declared tool inside that environment.
  5. Launch the runner and permit model requests only after preflight succeeds.

Preflight failure stops the run before spending model tokens and names the missing or incompatible tool. Durable executions collect changesets, artifacts, and links through the outcomes contract.

Versioning#

A spec version that has shipped never changes. An addition, removal, or change of meaning requires a new spec number. Once a spec is released its parser is immutable: engines select the matching parser and keep old parsers for backward compatibility.

Spec 0 is frozen legacy. It has a single runtime field with top-level image and docker, and no requirements or runtimes. Engines still read it and treat its runtime as a one-entry runtimes map internally. Every 1.x engine reads spec 0 manifests. wb init writes spec 1.