Experiment YAML
Lookup reference for the AX experiment YAML schema: fields, object shapes, shorthand forms, constraints, and validation rules.
Experiment YAML is the file format passed to ax experiment run and ax experiment run --local.
The current parser accepts schema_version: 2 and rejects unknown fields at every level. For the canonical machine-readable schema, use experiment.v2.schema.yaml.
Schema URL
Use the version-pinned schema URL for editor validation:
# yaml-language-server: $schema=https://docs.514.ax/schema/experiment.v2.schema.yamlPublished schema URLs:
| URL | Use |
|---|---|
https://docs.514.ax/schema/experiment.schema.yaml | Latest supported schema |
https://docs.514.ax/schema/experiment.v2.schema.yaml | Version-pinned v2 schema |
https://docs.514.ax/schema/experiment.v1.schema.yaml | Legacy v1 schema. v1 experiments no longer run; this remains available so older files that pin it still validate in-editor while migrating to v2. |
ax experiment schema prints the latest supported schema to stdout.
Field index
| Object | Fields |
|---|---|
| Top-level experiment | schema_version, id, name, description, agents, models, prompts, agent_mode, environments, products, extensions, environment_variables, files, tests, limits |
| Agent | name |
| Model | name, lab, effort, context_window_size, thinking, fast |
| Prompt | id, prompt, description, tags |
| Environment | name, setup, description, tags, commit |
| Product | name, type, setup, version, commit, description, tags |
| Setup | name, script, description, tags, files, environment_variables, mcp_servers, setup_checks |
| Extension | id, description, tags, agents, models, prompts, agent_mode, environments, products, extensions |
| Environment variable | name, value |
| File entry | name, source, sha256, dest |
| Test | name, script |
| Setup check | name, script |
| MCP server | name, type, command, args, url, env, headers |
| MCP stdio env entry | name, from |
| MCP HTTP and SSE header | name, value |
| Limits | max_turns, max_time_seconds, max_cost_usd |
Minimal example
# yaml-language-server: $schema=https://docs.514.ax/schema/experiment.v2.schema.yaml
schema_version: 2
id: cli-install
name: "CLI install"
agents: [claude]
models: [claude-sonnet-4-6]
prompts:
- id: install
prompt: |
Install the CLI and write its version to /workspace/version.txt.
products:
- name: cli
type: CLI
setup: npm pack
tests:
- name: version-file-exists
script: test -f /workspace/version.txt
limits:
max_turns: 25
max_time_seconds: 300
max_cost_usd: 0.50Top-level experiment
An experiment defines what you want to learn about agents using a product surface. It names the agents, prompts, products, environments, and tests AX uses to compute and run variants.
| Field | Required | Type / shape | Notes |
|---|---|---|---|
schema_version | Yes | Integer | Must be 2. |
id | Yes | Kebab-case string | Stable experiment id. Should match the YAML file name without .yaml. |
name | Yes | String | Human-readable experiment name. |
description | No | String | Optional context used when analyzing outcomes. |
agents | No | Agent axis | Optional at the top level only if an extension supplies agents. Every resolved variant must have an agent. |
models | No | Model axis | Optional. Cross-multiplied with agents; incompatible pairs are pruned. Absent ⇒ each agent runs its provider-default model. |
prompts | No | Prompt axis | Optional at the top level only if an extension supplies prompts. Every resolved variant must have a non-empty prompt. |
agent_mode | No | Agent-mode axis | Optional. build (default) or plan. Accepts a single value or list. plan runs the agent read-only (no mutations). Defaults to build. |
environments | No | Environment axis | Optional. |
products | No | Product axis | Optional. |
extensions | No | Extension list | Optional. If present, only extension-derived variants are created. |
environment_variables | No | Environment variable list | {name, value} entries injected into every variant. Values can be literals or ax://secrets/<slug> references resolved from your org secret store. |
files | No | File entry list | Host files staged into every variant before setup runs. |
tests | Yes | Tests list | Must contain at least one test. |
limits | Yes | Limits object | Run caps. |
Top-level environment_variables and files apply to every variant. MCP servers and setup checks are setup-owned fields.
Variant axes
Variant axes are the experiment inputs AX combines into runnable variants. This lets you define the dimensions you care about once, then compare results by agent, prompt, environment, and product.
variants = agents × models × prompts × agent_mode × environments × productsOnly agents and prompts must be specified: every resolved variant carries an agent and a prompt (each can also be supplied by an extension). The rest are optional. Omit models and each agent runs its provider-default model; omit agent_mode, environments, or products and that axis is left out of the cross product and of the variant coordinate.
Agents
agents defines which coding agents run the experiment. The model an agent runs comes from the models axis, not the agent.
Accepted shapes:
# String form: one agent.
agents: claude
# List of strings: multiple agents. Valid names: claude, codex, cursor.
agents:
- claude
- codex
- cursor
# Object form is also accepted, but only carries the name.
agents:
- name: claudeThe nested agents[].model key was removed. Put the model on the top-level
models axis instead. Authoring agents: [{ name: claude, model: … }]
fails ax experiment validate with a migration message.
Agent object
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | claude, codex, or cursor | Coding agent to run. The model comes from the models axis. |
Models
models defines which models run, as an independent axis cross-multiplied with agents. Listing agents: [claude] with models: [opus, sonnet] produces both variants without duplicating the agent.
Accepted shapes:
# String form: one model.
models: claude-opus-4-8
# List of strings: multiple models.
models:
- claude-opus-4-8
- claude-sonnet-4-6
# Object form: a model with controls.
models:
- name: gpt-5.3-codex
effort: highmodels is optional. If omitted, each agent runs its provider-default model.
Pruning incompatible pairs
The agents × models cross product keeps only the compatible pairs. A model the catalog knows for a different agent's provider — for example claude × an openai model — is pruned (dropped), not an error, so one agents + models pair of lists expresses every valid combination:
agents: [claude, codex]
models: [claude-opus-4-8, gpt-5.3-codex]
# 2 × 2 = 4 pairs → pruned to the 2 valid ones:
# ✓ claude + claude-opus-4-8 ✓ codex + gpt-5.3-codex
# ✗ claude + gpt-5.3-codex ✗ codex + claude-opus-4-8 (dropped)Pruning is visible — dropped pairs show up as a smaller resolved matrix in ax experiment variants. If a listed agent or model is compatible with nothing else listed (every pair it appears in is pruned), ax experiment validate hard-errors, since that entry is almost certainly a typo.
Model id format
Prefer the lab-official models.dev id with no owner prefix, such as claude-opus-4-8, gpt-5.3-codex, or composer-2.5. AX infers the runtime provider from the selected agent and stores a canonical provider/lab/model id behind the scenes.
If a bare id is ambiguous, validation asks for lab; use the model object form, for example { name: claude-opus-4-8, lab: anthropic }. Most model ids do not need this.
Older owner/provider-prefixed and gateway-style ids, such as anthropic/claude-opus-4-8 or anthropic/claude-opus-4.8, are accepted for compatibility and normalize to the same canonical id.
Model object
A model object configures one model and its controls. Optional controls are passed through when the selected agent supports them. To compare two control settings of the same model, list two models entries.
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | String | Lab-official models.dev id, such as claude-opus-4-8 or gpt-5. |
lab | No | String | Optional disambiguator, such as anthropic or openai, used only when validation reports an ambiguous bare id. |
effort | No | low, medium, high, x-high, max | Reasoning effort control, validated against the (agent, model) catalog. Delivered where each harness honors it: an ACP session/set_config_option for Claude / Codex, baked into the model id for Cursor. |
context_window_size | No | String | Context window size, such as 1M or 200k (a token count also works). Supported for Claude (200k or 1M) and Codex (any size up to the model's limit). Not supported for Cursor — the Cursor CLI cannot select a context window, so ax experiment validate (and therefore ax experiment run / ax experiment run --local) rejects any Cursor variant that sets it. Validation also rejects sizes over the selected model's limit. |
thinking | No | Boolean | Enables thinking mode when supported. |
fast | No | Boolean | Enables fast mode when supported. |
agents: [claude, codex]
models:
- name: claude-opus-4-8
effort: high
context_window_size: 1M
thinking: true
- gpt-5Prompts
prompts defines the tasks agents try to complete. Each resolved variant receives one final prompt.
Accepted shapes:
# String form: one prompt.
prompts: "Build the report."
# List of strings: multiple prompts.
prompts:
- "Build the report."
- "Build the report and explain your steps."
# Object form: list of named prompts.
prompts:
- id: detailed
prompt: "Build the report and explain your steps."Prompt object
A prompt object gives a task stable metadata, so Results can filter and group by the prompt that produced each run.
| Field | Required | Type / values | Notes |
|---|---|---|---|
id | Yes | Kebab-case string | Stable prompt id. Recorded for filtering in Results. |
prompt | Yes | String | Task text given to the agent. |
description | No | String | Human-readable notes. |
tags | No | String list | Free-form labels. |
Bare prompt strings get positional ids: p0, p1, and so on.
Agent mode
agent_mode is a top-level model variable. Accepts a single value or list of build / plan. It is cross-multiplied with the other axes just like agents and models to define the variants tested.
build(default) runs the agent normally: it executes tools, can read and write, and mutates the workspace.planputs the agent in its native read-only / planning mode. This plans, and mutates nothing in the sandbox. The abstractplanvalue resolves to that agent's planning mode (claude / cursor resolve toplan, codex toread-only). If the selected mode isn't available the variant fails loudly rather than silently running inbuild.
# Sweep both modes over one agent/model/prompt → 2 variants.
agents: [claude]
models: [claude-opus-4-8]
agent_mode: [build, plan]agent_mode is optional; defaulting to build mode. When you declare the axis, the mode is emitted into the variant id. This applies to plan and build options. So a [build, plan] sweep produces …::build::my-prompt and …::plan::my-prompt. When the axis is absent nothing is emitted, so experiments that don't use agent_mode keep their original ids (for example claude::anthropic-claude-opus-4-8::my-prompt). Note that authoring agent_mode: build explicitly therefore yields a different id than omitting the axis.
A plan variant produces no file changes. Every test in the flat tests list runs for every variant regardless of mode; the harness does not scope tests by agent_mode. A build-oriented workspace check will fail the plan variant unless you guard it (e.g. [ ! -f out.json ] || <verify out.json>). For a [build, plan] sweep, score the plan variant with trace-based checks over $AX_TRACE_PATH. See examples/experiments/plan-mode-comparison.yaml.
Environments
environments defines the sandbox conditions around the agent, such as installed tools, fixtures, or external integrations. Use environments when you want to compare how agents perform under different surrounding conditions.
Accepted shapes:
# String form: one setup script with a generated environment name.
environments: "pip install -r requirements.txt"
# Object form: one named environment.
environments:
name: workspace
setup: "pip install -r requirements.txt"
# List form: multiple named environments.
environments:
- name: workspace
setup: "pip install -r requirements.txt"Environment object
An environment object names one sandbox setup condition. Its setup prepares the sandbox before the agent receives the prompt.
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | Kebab-case string | Environment coordinate. Recorded for filtering in Results. |
setup | Yes | Setup | Prepares the sandbox before the agent runs. |
description | No | String | Human-readable notes. |
tags | No | String list | Free-form labels. |
commit | No | String | Source commit of the environment under test. |
Bare environment strings are shorthand for an environment whose setup is that string.
Products
products defines the agent-facing surface under test. A product can be a CLI, API, MCP server, SDK, docs surface, or other tool the agent uses to complete the prompt.
Accepted shapes:
# String form: one setup script with a generated product name.
products: "npm install -g my-cli"
# Object form: one named product.
products:
name: my-cli
type: CLI
version: "1.2.0"
setup: "npm install -g my-cli"
# List form: multiple named products.
products:
- name: my-cli
type: CLI
version: "1.2.0"
setup: "npm install -g my-cli"Product object
A product object names what you want to compare. Product metadata is recorded so Results can filter and group by product and product version.
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | Kebab-case string | Product coordinate. Recorded for filtering in Results. |
type | No | Product type | Defaults to Other. |
setup | Yes | Setup | Prepares the product before the agent runs. |
version | No | String | Product version. Quote numeric versions, such as "25.3". |
commit | No | String | Source commit of the product under test. |
description | No | String | Human-readable notes. |
tags | No | String list | Free-form labels. |
Product type
Allowed values: CLI, MCP, API, Skill, SDK, Schema, Docs, Marketing, Agents.md, Other.
Setup
setup prepares the sandbox for an environment or product. Use setup scripts to install tools, create fixtures, start services, or expose resources the agent needs.
Each variant has its own isolated /workspace. A setup script cannot rely on files or side effects created by another variant.
Accepted shapes:
# String form: one setup script.
setup: "npm install"
# List of strings: multiple setup scripts, run in order.
setup:
- "npm install"
- "npm test -- --help"
# Object form: one named setup with optional scoped resources.
setup:
name: install-cli
script: "npm install"
# List of objects: multiple named setups, run in order.
setup:
- name: install-cli
script: "npm install"
- name: smoke-cli
script: "npm test -- --help"
# Mixed list: strings and setup objects can be combined.
setup:
- "npm install"
- name: smoke-cli
script: "npm test -- --help"Setup object
A setup object is the named form of setup. Use it when setup needs its own files, environment variables, MCP servers, or setup checks.
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | Kebab-case string | Required for object form. |
script | Yes | String | Bash run before setup checks and before the agent. Secret values are not injected here. |
description | No | String | Human-readable notes. |
tags | No | String list | Free-form labels. |
files | No | File entry list | Host files staged before this setup's script runs (scoped to variants that resolve this setup). |
environment_variables | No | Environment variable list | Runtime env vars scoped to variants that use this setup. |
mcp_servers | No | MCP server list | MCP servers exposed to the agent. |
setup_checks | No | Setup check list | Checks run after setup and before the agent. |
When both a product and environment contribute setup, product setup runs before environment setup.
Setup checks
setup_checks verify that setup produced a usable sandbox before the agent starts. A failed setup check stops that variant before any agent work happens. Setup checks receive resolved environment_variables, AX_VARIANT_ID, and AX_RUN_CONTEXT_PATH; they do not receive trace or agent-log paths because the agent has not run yet.
setup_checks:
- name: cli-on-path
script: my-cli --versionSetup check object
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | Kebab-case string | Appears in setup-checks/<name>.json. |
script | Yes | String | Bash check streamed over stdin and hidden from the agent. A non-zero exit aborts the variant before the agent runs. |
MCP servers
mcp_servers exposes MCP servers to the agent for variants that use this setup. Use this field when the product surface or environment includes an MCP tool.
mcp_servers:
- name: fixture-sentinel
type: stdio
command: /workspace/fixture-mcp.py
args: []
- name: ax
type: http
url: http://localhost:3001/mcpMCP server object
An MCP server object defines one server and its transport. The required connection fields depend on type.
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | String | Must be unique within the setup's mcp_servers. |
type | Yes | stdio, http, or sse | Transport. |
command | For stdio | String | Executable path or command inside the sandbox. |
args | No | String list | Stdio command arguments. |
url | For http / sse | String | MCP endpoint URL. |
env | No | MCP stdio env entries | Only valid for stdio. |
headers | No | MCP header entries | Only valid for http / sse. |
Transport-specific rules:
stdiousescommand, optionalargs, and optionalenv.httpandsseuseurland optionalheaders.- Mixing stdio-only and endpoint-only fields is rejected.
MCP stdio env entry
env forwards declared environment values to a stdio MCP process. Each entry is either a bare name or an object:
env:
- GITHUB_TOKEN
- name: GH_AUTH
from: GITHUB_TOKEN
# Managed model access for an LLM-backed MCP server (no raw provider key):
- name: ANTHROPIC_API_KEY
from: AXP_MODEL_PROXY_TOKEN
- name: ANTHROPIC_BASE_URL
from: AXP_MODEL_PROXY_URL| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | String | Env var name as seen by the MCP server process. |
from | Yes | Env name or virtual ref | Declared environment_variables name, or a managed-proxy virtual ref (AXP_MODEL_PROXY_TOKEN / AXP_MODEL_PROXY_URL). |
AXP_MODEL_PROXY_TOKEN and AXP_MODEL_PROXY_URL are virtual references to the run's workload token and Anthropic-style proxy base URL. They resolve only when the run has managed model access (ax experiment run, or default ax experiment run --local / ax local run; not with --local-model-keys); without it they are dropped with a warning. They are not org secret-store slugs and are not organization BYOK configuration — see Model Providers and the 514.ax AI Gateway.
MCP HTTP and SSE header object
headers attaches HTTP headers to an http or sse MCP server. Use placeholders when a header needs a declared secret value.
headers:
- name: Authorization
value: "Bearer ${SUPABASE_SERVICE_ROLE_KEY}"| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | String | HTTP header name. Header names must be unique per server, case-insensitively. |
value | Yes | String | May contain ${SECRET_NAME} placeholders. Bare $NAME is literal. |
MCP env entries and header placeholders reference environment variable names visible to the variant. Values can come from literal environment_variables, ax://secrets/<slug> references, or (stdio env only) the managed-proxy virtual refs AXP_MODEL_PROXY_TOKEN / AXP_MODEL_PROXY_URL.
Rules enforced at ax experiment validate time:
- Every stdio
env[*].fromand every${NAME}placeholder in a headervaluemust reference a name visible to the variant, or (stdioenvonly) a managed-proxy virtual ref. - Bare
$NAMEis treated as a literal; only${NAME}is a placeholder. - HTTP header names are unique per server, case-insensitively.
command/args/envare only valid fortype: stdio;url/headersare only valid fortype: http/sse.
Resolved secret values are written into the agent session frame and can appear in run artifacts. Treat artifacts as sensitive whenever an experiment forwards secrets to MCP servers.
Extensions
extensions refine the variant set when the base axes do not express the combinations you need. Use extensions to narrow an axis, swap products or environments for a subtree, or append prompt guidance to a slice of variants.
If an experiment declares any extensions, AX creates only extension-derived variants.
Extension object
An extension object is one node in the refinement tree. Nested extensions are recursively cross-multiplied with their parents.
| Field | Required | Type / values | Notes |
|---|---|---|---|
id | Yes | Kebab-case string | Must be unique among sibling extensions. |
description | No | String | Human-readable notes. |
tags | No | String list | Added to resolved variant tags. |
agents | No | Agent list | Replaces inherited agents for this extension subtree. |
models | No | Model axis | Replaces inherited models for this extension subtree. |
agent_mode | No | Agent-mode axis | Replaces inherited agent modes for this extension subtree. |
prompts | No | Prompt list | Appended to inherited prompt text. Does not replace the prompt axis. |
environments | No | Environment list | Replaces inherited environments for this extension subtree. |
products | No | Product list | Replaces inherited products for this extension subtree. |
extensions | No | Extension list | Nested extensions. |
prompts:
- id: analyze
prompt: "Read /workspace/task.md and write /workspace/report.json."
extensions:
- id: with-cli
products:
- name: cli
type: CLI
setup: "curl -fsSL https://clickhouse.com/ | sh"
prompts: ["Use the ClickHouse CLI for the analysis."]
- id: without-cli
products:
- name: no-cli
setup: "true"
prompts: ["Do not use the ClickHouse CLI; use another local method."]Environment variables
environment_variables injects environment variables into variants at runtime. Use it for non-secret runtime configuration and supported secret references.
environment_variables:
- name: LOG_LEVEL
value: debug
- name: GITHUB_TOKEN
value: ax://secrets/prod-gh
- name: DATABASE_URL
value: ax://secrets/staging-dbEnvironment variable object
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | Env-var name | Must match ^[A-Z_][A-Z0-9_]*$. Harness-reserved names and prefixes are rejected. |
value | Yes | String | Literal value or ax://secrets/<slug> reference (legacy axp://secrets/<slug> is also accepted). Other values beginning with ax:// or axp:// are rejected. |
Store secret values once with ax secret set <slug>, then reference them with ax://secrets/<slug>. Both platform and local ax experiment run invocations resolve these references before injecting env vars into the sandbox.
A referenced slug that does not exist in your org fails at preflight.
Reserved names:
ANTHROPIC_API_KEYANTHROPIC_BASE_URLOPENAI_API_KEYOPENAI_BASE_URLCURSOR_API_KEYMODELMAX_TURNSIS_SANDBOXTRACEPARENT- any name beginning with
AX_,AXP_,CLAUDE_CODE_,CODEX_,CURSOR_, orOTEL_
Files
Top-level files stages host files into every variant's /workspace before setup runs. The same shape is accepted on setup objects; setup-scoped entries stage only for variants that resolve that setup.
files:
- name: my-cli
source: ../build/mycli
dest: tools/mycli
- source: https://example.com/fixtures/data.bin
sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
dest: fixtures/data.binFile entry object
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Sometimes | Kebab-case string | Required when source is omitted. Used as the --file NAME=SOURCE handle. |
source | Sometimes | Host path or http(s) URL | Required when name is omitted. Relative paths resolve against the YAML file's directory. |
sha256 | No | 64-char hex string | Valid for file sources and URL downloads. Invalid for directory sources. |
dest | Yes | Workspace-relative path | Absolute paths, .., .axp-bridge, and :: are rejected. |
Notes:
- Directory sources copy their contents under
dest/. - File sources land as a single file at
dest. - URL sources must be publicly fetchable and land as a single file at
dest; unpack archives insetupif needed. - Sandboxes are Linux containers; macOS binaries staged from a laptop will not run there.
- Directory walks honor
.axpignore, not.gitignore. --file NAME=SOURCEbinds or overrides the source of a named entry.--file SOURCE::DESTstages an ad-hoc entry into every variant.- Missing or unbound sources abort real runs at preflight.
--resolve-variantsrendersMISSING/UNBOUNDannotations without failing. - Staging failures roll the variant up as
status=error/exit_reason=staging_failed; the rest of the run keeps going. - Platform and local runs both stage top-level
files. - Treat experiment YAML like a script you run: sources are read with your permissions and may point anywhere on the host.
Tests
tests defines how AX scores each run. It is one flat list of bash checks. Test scripts receive resolved environment_variables, AX_VARIANT_ID, and path env vars for staged run artifacts, so any test can inspect final /workspace state, run commands, read $AX_TRACE_PATH, or branch on $AX_RUN_CONTEXT_PATH.
tests:
- name: report-exists
description: Confirms the agent produced the required report artifact.
script: test -f /workspace/report.json
- name: under-thirty-tool-calls
script: |
[ "$(jq -s '[.[] | select(.kind == "tool_call")] | length' "$AX_TRACE_PATH")" -lt 30 ]Test runtime environment
Tests run inside the variant sandbox with /workspace as the working tree. The agent does not see the test scripts or these test-only path variables.
| Env var | Available to | Value |
|---|---|---|
AX_RUN_CONTEXT_PATH | Setup checks and tests | /tmp/axp/run-context.json, a JSON object with run_id, run_request_id, repeat_idx, variant_id, variant_tag, agent, model, canonical_model_id, effort, context_window_size, thinking, fast, prompt_id, prompt, environment_id, product_id, product_version, tags, and resolved_extend_id. Absent axes/controls are JSON null. |
AX_TRACE_PATH | Tests only | /tmp/axp/agent-events.jsonl, staged when the agent event stream exists. ACP runs and non-native cursor runs produce one; --flag native runs do not (no ACP session), so the variable is never set for them and trace-based tests fail native variants. |
AX_AGENT_LOG_PATH | Tests only | /tmp/axp/agent.log, staged when the agent log exists. |
AX_VARIANT_ID | Setup checks and tests | The derived variant id. Kept for backward compatibility; the same value is also in run context JSON. |
Example:
jq -e '.run_id != null and .agent == "claude"' "$AX_RUN_CONTEXT_PATH"Test object
| Field | Required | Type / values | Notes |
|---|---|---|---|
name | Yes | Kebab-case string | Must be unique. |
description | No | Non-empty string | Explains the test's intent to analysis models. Updating or removing it with ax experiment push keeps the same semantic version and existing runs; ax experiment pull and the mutable description column in ax experiment query return the latest pushed value. Test outcome fields and version-change reports remain unchanged. |
script | Yes | String | Bash script. Streamed over stdin and not shown to the agent. |
Limits
limits sets the run caps for each variant execution.
Limits object
| Field | Required | Type / values | Notes |
|---|---|---|---|
max_turns | Yes | Integer greater than 0 | Agent turn cap. |
max_time_seconds | Yes | Integer greater than 0 | Wall-clock timeout in seconds. |
max_cost_usd | Yes | Number greater than 0 | Enforced when the agent reports cumulative cost during the run; if no cost is reported, AX cannot stop on cost. |
The cost that max_cost_usd caps is the agent's own reported model spend — the running token cost the agent computes as it works. It excludes 514-managed sandbox and other harness infrastructure spend, and it applies the same way whether the run uses your own provider key or 514-managed model access. Because it's the agent's live estimate rather than a reconciled bill, treat the cap as an approximate guardrail.
Secrets removed
The top-level (and setup) secrets: field is rejected by ax experiment validate and platform submit, including an empty secrets: []. Use environment_variables with literals or ax://secrets/<slug> references. MCP secret-forwarding fields reference declared environment_variables names, not store slugs.
Validation rules
An experiment is invalid if:
- the YAML contains a field not defined by the schema
schema_versionis not2- any required field is missing
- an id that must be kebab-case is not kebab-case
- a model id contains
:: - a declared axis is empty
- duplicate ids or names appear where uniqueness is required
- the resolved variant set is empty
- a resolved variant has an empty prompt
- two resolved variants collide on
variant_id - no tests are defined
- test names are duplicated
- an env var name is invalid or reserved
- a file entry has an invalid
name,source,sha256, ordest - an MCP server mixes transport-specific fields
- an MCP server references an env var name not visible to the variant
- any
secrets:key is present (removed; useenvironment_variables) - any limit is not greater than zero
YAML syntax boundaries
The experiment data model is JSON-compatible even though the authoring file is YAML.
- YAML comments are allowed.
- YAML anchors and aliases are allowed when the resolved value is JSON-compatible.
- Custom YAML tags are unsupported.
- Non-string mapping keys are unsupported.