Skip to content

agentsmith.yml reference

Which surface reads this

This page documents the file format. A server reads only the bootstrap slice (persistence:, secrets:, auth:, tool_runner:) from it and keeps everything else in its database, edited in the Config studio. The CLI reads the whole file. Same shape either way, and agent-smith config import takes exactly this document. See Where configuration lives.

The file is a set of named catalogs (agents, trackers, connections, repos, MCP servers, secrets) plus projects that wire catalog entries together by name, plus a handful of global settings blocks. Names are matched without regard to case, so TodoList and todolist are the same project; two entries of one catalog that differ only in case are refused.

The annotated config/agentsmith.example.yml in the repo is the fullest worked example, and config/agentsmith.schema.json gives your editor completion (see agentsmith.yml).

The loader ignores a key it doesn't know, so an older file keeps loading after an upgrade. The schema is therefore where a misspelt key is caught: it declares exactly the keys the loader reads, and every block refuses any other. The one exception is a retired block kept so an older file still validates: pipeline_storage is declared, marked deprecated, and ignored. agent-smith config import names each key of the file it doesn't store, with the reason: retired, bootstrap-only, or no such setting. A retired key in a loaded configuration is also reported as an advisory startup finding.

A complete small example

agents:
  default-claude:
    type: claude
    catalog:
      sonnet: { model: claude-sonnet-4-6, tier: strong }
      haiku:  { model: claude-haiku-4-5-20251001, tier: fast }
    models:
      primary:       { use: sonnet }
      planning:      { use: sonnet }
      scout:         { use: haiku }
      summarization: { use: haiku }
    pricing:
      models:
        claude-sonnet-4-6:         { input_per_million: 3.0, output_per_million: 15.0, cache_read_per_million: 0.30 }
        claude-haiku-4-5-20251001: { input_per_million: 1.0, output_per_million: 5.0,  cache_read_per_million: 0.10 }

connections:
  acme:
    type: github
    owner: acme-org
    auth: github_token

trackers:
  acme-issues:
    type: github
    url: https://github.com/acme-org/todolist-api
    auth: github_token
    open_states: [open]
    done_status: closed
    default_pipeline: code
    pipeline_from_label:
      agent-smith:bug:     code
      agent-smith:feature: code

projects:
  todolist:
    agent: default-claude
    tracker: acme-issues
    repos:
      - acme/todolist-api
      - acme/todolist-web
    resolution:
      tag: todolist

secrets:
  claude_api_key: ${ANTHROPIC_API_KEY}
  github_token:   ${GITHUB_TOKEN}

The prices above are placeholders; put in what your provider charges.

agents

One entry per LLM configuration. A project names one with agent:.

Key Description
type claude (alias anthropic), openai, azure_openai, gemini (alias google), ollama, copilot, external_worker. See AI providers
endpoint, api_version provider endpoint: Azure OpenAI, Ollama, or with type: openai any OpenAI-compatible server (see OpenAI-compatible servers)
api_key_secret the name of the environment variable holding the key, when the provider default isn't it. With type: openai and an endpoint there is no default
catalog.<entry> the models the agent may call, declared once each, see below
models.<role> which model each role uses, see below
model, deployment the inline form: the agent's own model, which an unset primary answers with. The config studio saves the catalog form and clears these
pricing.models.<model> input_per_million, output_per_million, cache_read_per_million in USD
cache is_enabled (default true), strategy (default automatic), prompt caching
retry max_retries (5), initial_delay_ms (2000), backoff_multiplier (2.0), max_delay_ms (60000)
network_timeout_seconds how long one provider call may take, default 300
rate_limit requests_per_minute, input_tokens_per_minute; unset takes the provider's default budget
compaction is_enabled (true), max_context_tokens (200000), max_context_tokens_trigger_ratio (0.7), keep_recent_iterations (3). It summarizes with the summarization role
loop tuning max_master_loop_iterations (200), max_sub_agent_loop_iterations (100), max_fix_iterations (3), ledger_reminder_every_n_iterations (10), reminder_drift_editless_iterations (8), verdict_owed_after_iterations (3), checkpoint_push_min_interval_seconds (120), supports_vision (true)
scan tuning scan_min_source_reads (6), scan_master_max_output_tokens (32000), scan_master_loop_iterations (100), scan_context_window_tokens (200000)

agents.catalog

Each entry is one model the agent may call, under a name you choose. Two roles on one deployment name one entry instead of repeating it:

catalog:
  sonnet:
    model: claude-sonnet-4-6
    max_tokens: 8192               # the OUTPUT cap, default 8192
    deployment: gpt4-1-deployment  # Azure OpenAI deployment name, when it differs from the model
    context_window_tokens: 200000  # optional: the INPUT window the deployment accepts
    provider_type: openai          # optional: answer on another provider than the agent's
    endpoint: https://…            # optional: its own host; unset takes the agent's endpoint
                                   #   when it runs on the agent's provider
    tier: strong                   # optional: strong | fast, your word for the model

tier is advice, never enforced. The roles that decide structure (primary, planning, reasoning, context_generation, code_map_generation) need a strong model; one that resolves to an entry marked fast is reported as an advisory startup finding. An entry with no tier is never reported, because agent-smith doesn't rate models.

agents.models

A role names its catalog entry with use:. No role has a built-in model. An unset role inherits, max_tokens included:

Role Used for Unset means
primary the agentic work the agent's model and deployment
scout code analysis, file discovery primary
planning cutting the work into specs primary
summarization condensing long histories primary
reasoning extended thinking primary
context_generation discovering components and writing each context.yaml primary
code_map_generation the repo analyzer scout, then primary
models:
  primary: { use: sonnet }
  scout:   { use: haiku }

A use: that names no entry of the catalog is reported at startup; a run that reaches the role fails. The config studio and config import refuse it.

The inline form still loads: instead of use:, a role may state its model itself, with the same keys as a catalog entry except tier. With use: set, the inline keys beside it are ignored, and the studio and config import refuse a role that carries both:

model: claude-sonnet-4-6
max_tokens: 8192               # the OUTPUT cap
deployment: gpt4-1-deployment  # Azure OpenAI deployment name, when it differs from the model
context_window_tokens: 200000  # optional: the INPUT window the deployment accepts
provider_type: openai          # optional: answer this role on another provider than the agent's
endpoint: https://…            # optional: this role's own host; unset takes the agent's endpoint
                               #   when the role runs on the agent's provider

context_window_tokens is unset by default, because the model name doesn't imply it. The config studio offers the price list's window as a one-click value, but saves only what you confirm. State it and the tool loop for that role folds its history and finishes before the provider refuses; preflight reports a compaction threshold that could never fire below a stated window.

Every catalog model needs a price: the bundled price list knows most hosted models by id, and pricing.models states or overrides the rest. The studio refuses to save an agent with a catalog model neither knows. Tokens nothing can price are counted, and the run's cost is then marked incomplete rather than shown as a total.

connections

A discovery scope: host, org and auth once, and repos found under it by the provider API.

Key Description
type github, gitlab, azure_devops
owner GitHub owner or org
group GitLab group, a subgroup path works too
organization, project Azure DevOps organization and project
host API host for GitHub Enterprise or self-managed GitLab
auth name of an entry in secrets:
default_branch fallback only, used when the platform can't say what a repo's default branch is

A project references a connection's repos as <connection>/<repo>: exactly (acme/todolist-api) or by wildcard rule (acme/todolist-*, "!acme/todolist-legacy"). agentsmith.yml schema has how each form resolves. GitLab repos found under a group are named by their path relative to it (team-platform/todolist-api).

repos

One entry per individual repository, for a repo no connection covers.

Key Description
type github, gitlab, azure_devops, local
url clone URL (remote types)
path filesystem path (local)
organization, project Azure DevOps
auth name of an entry in secrets:
default_branch fallback only, see below

Default branch. The repository's own default branch, as the platform reports it, always wins. A configured default_branch (on the repo, on a project's repo item, or on the connection) applies only when the platform has no answer, and main when nothing does. When a configured value disagrees with the repository, the run logs a warning naming both.

trackers

Where tickets come from and how their workflow looks. The tracker owns the workflow for every project routed to it.

Key Description
type github, gitlab, azure_devops, jira
url GitHub: the repository whose issues are the tickets. Jira: the site. Azure DevOps: optional, an Azure DevOps Server base such as https://tfs.example.com/tfs (the organization is its collection); empty or a cloud URL means https://dev.azure.com/{organization}
organization, project Azure DevOps organization and project. GitLab: project is the project path. Jira: project is the project key
auth name of an entry in secrets:
open_states states a ticket may be in to be picked up
trigger_statuses states that start a run, falls back to open_states
done_status where a finished run moves the ticket
failed_status where a failed run moves it; must lie outside trigger_statuses
needs_clarification_status where a run parks a ticket it has questions about
not_implementable_status where a ticket goes that can't be implemented as written; falls back to needs_clarification_status
close_transition_name Jira: the transition that reaches done_status
closed_status Jira, Azure DevOps: the status "also close on the tracker" moves a ticket into. Unset: done_status
pipeline_from_label label → pipeline. Matched in order, first hit wins. With entries, a ticket matching none isn't routed
default_pipeline what a ticket runs when the label map is empty. Unset everywhere means code, with a startup finding
label_names renames the labels the framework writes. Keys: pending, enqueued, in-progress, done, failed, waiting, shortfall, approved-set
lifecycle_status_names Jira: lifecycle state → native workflow status, instead of carrying the lifecycle only as labels
work_item_kinds Azure DevOps and Jira: filing role (work, bug, spec — phase still accepted — chat) → work-item or issue type. GitHub and GitLab ignore it
extra_fields additional work-item fields to fetch
zero_match_comment comment on a ticket no project matched
polling enabled (false), interval_seconds (60), jitter_percent (10). See Polling
endpoints Jira: override individual REST paths — search, issue, comment, transitions, create. A path left out keeps its Jira Cloud v3 default. See Jira

A label the framework writes may not be spelled like one of your routing words (a pipeline_from_label key or a project's resolution value); that configuration is refused. The tracker pages under Connect your stuff show each type in context.

The pipelines a label map or default_pipeline may name are the ones a ticket can be routed to: code, security-scan, api-security-scan, pr-review, mad-discussion, legal-analysis. The retired names fix-bug, fix-no-test, add-feature and phase-execution no longer run. Write code.

projects

A project wires one agent, one tracker and a set of repos, and says how a ticket finds it.

Key Description
agent name from agents:
tracker name from trackers:
repos list of repo references, always a list. See repos entry forms
resolution how a ticket finds this project, one entry { strategy: value }: tag, area_path, repo, to_address. See Project resolution
templates what this project's contexts are built after. See Project templates
default_pipeline the project's default pipeline (CLI runs and fallback paths). What a ticket runs is decided by the tracker's routing
pipelines pipelines this project hosts with their own overrides: name, agent, skills_path, coding_principles_path
coding_principles_path, skills_path project-level overrides
github_trigger, gitlab_trigger, azuredevops_trigger, jira_trigger a full trigger block, overriding the tracker field by field. Must match the tracker's type
sandbox per-project sandbox overrides, see below
design_sources names from design_sources: this project may read designs from. See Design sources

Trigger blocks

Only needed when one project departs from its tracker's workflow. Every field is optional and overrides the tracker's.

Key Description
project_resolution { strategy, value }, the long form of resolution:
pipeline_from_label, default_pipeline as on the tracker
trigger_statuses, done_status, failed_status, needs_clarification_status, not_implementable_status as on the tracker
in_progress_status the status a parked run's ticket returns to when the run resumes; outside trigger_statuses
comment_keyword a keyword in a ticket comment that triggers
pr_trigger_label GitHub and GitLab: a pull request label that asks for a review. security-review always does too
assignee_name Jira: the webhook starts work when an issue is assigned to this user, default Agent Smith
secret Jira: the webhook shared secret, see Webhooks

projects.templates

templates:
  - context: api                 # a context of this project
    context_repo: todolist-api   # optional, when two repos declare the context name
    project: acme-orders         # the project the template belongs to
    repo: orders-api             # one repo ref of that project, no wildcard
    template_context: service    # the context inside that repo
    revision: v2.4.0             # optional: tag, branch or commit; empty = default branch

Refused: an unknown project, a repo that project doesn't carry, a wildcard repo, a context_repo this project doesn't carry, and a cycle. Project templates explains what reads them.

projects.sandbox

Key Description
toolchain_image one image for the whole project, wins over everything else
images language → image, overrides the built-in image per language
resources cpu and memory requests and limits, all four or none
step_timeout_seconds, run_command_timeout_seconds override the global timeouts
agent_registry, agent_version override the sandbox agent image
hold_seconds how long this project's design conversations hold their sandboxes between turns
run_as_root with sandbox.hardening_enabled on, true runs this project's sandboxes as root with default capabilities, for prerequisites that need root; every run then carries a warning
secrets env (VAR: "secretName:key") and files (mount, secret, key): Kubernetes Secrets mounted into the sandbox

Empty means inherit. Sandbox architecture has what each one does at runtime.

secrets

Names mapped to environment variable references. The file never holds a value, and a config that carries a raw secret is refused.

secrets:
  github_token:      ${GITHUB_TOKEN}
  anthropic_api_key: ${ANTHROPIC_API_KEY}

Every repo, connection and tracker authenticates with the secret its own auth names, for API calls and for clone, fetch and push alike, so two GitLab instances or two Azure DevOps organizations each get their own token. An auth that names no entry here is a blocking finding. A Jira tracker also needs email, the account its token belongs to.

A configuration written before this rule keeps working. An empty auth is filled at load with its type's legacy secret (github_token, gitlab_token, azure_devops_token, jira_token), and that secret is added as ${GITHUB_TOKEN} (and so on) when the catalog lacks it. An empty Jira email comes from the jira_email secret, else JIRA_EMAIL. An empty GitLab or Jira tracker url or project comes from GITLAB_URL, JIRA_URL, GITLAB_PROJECT or JIRA_PROJECT, and the host of a GitLab repo under repos: comes from GITLAB_URL. Each fill shows up as an advisory startup finding, and so does an auth that names a different secret while the old variable is still set, because that is the moment the token in use changes.

pipeline_triggers

A global label → pipeline map, used when neither the project's trigger nor its tracker declares a pipeline_from_label. There's no studio screen for it; on a server, edit it through export and import.

pipeline_triggers:
  agent-smith:bug:     code
  agent-smith:feature: code
  security-review:     security-scan

Global settings

These blocks apply to every project unless a project overrides them. On a server they're the Settings groups.

Block What it sets
deployment registry, version: an optional image pin for the sandbox agent
orchestrator max_run_wall_time_seconds (1800)
sandbox agent image, step_timeout_seconds (900), run_command_timeout_seconds (300), max_concurrent_sandboxes, hold_seconds (180), registry trust, pull secrets and hardening_enabled (false: sandboxes run as uid 1000 with no capabilities when true)
registries private package feeds the agent authenticates against in the sandbox
primary_provider the agent used when a project names none
limits per-skill ceilings of the agentic loop
pipeline_cost_cap money and token caps per run, see Pipeline cost cap
queue max_parallel_jobs (4), consume_block_seconds (5), shutdown_grace_seconds (30), redis_retry_interval_seconds (30)
dialogue hot_wait_seconds (600), approval_timeout_seconds (259200), dashboard_url
skills an override for where the skill catalog comes from; normally unset
pipeline_data_flow whether the data-flow gate warns or enforces
trace enabled: record every model call's prompt and answer. AGENTSMITH_TRACE, when set, wins over it
spec_review rounds (4, 0 turns it off), reviewers (2), max_concurrent (2), budget_share_percent (40): the review each unbuilt spec gets before it is built
series max_specs (24, at most 26), specs_per_attempt (8, at most 18), seconds_per_spec (0 = not measured), budget_usd (150, 0 = no attempt starts by itself), wall_clock_hours (12), continue_after_wall_time (true)
role_mapping what a role name means: role_claim, group_claim, group_roles, roles, person_grants, project_bindings (project, groups, people as claim/value, roles: roles held in that project only, their run, init and dialog permissions), observation_retention_days. Edited on the Access page
mcp_servers the studio's MCP server catalog: transport, url, auth
design_sources the design source catalog: vendor (figma), auth (a name from secrets:), display_name. See Design sources

Bootstrap and file-only blocks

Block Description
persistence provider (sqlite, postgresql, mysql, sqlserver) and connection_string. Replaced by AGENTSMITH_PERSISTENCE_PROVIDER + AGENTSMITH_PERSISTENCE_CONNECTION when both are set
auth the token authority dashboard sign-in validates against
tool_runner how the api-scan tools run, see Tool configuration. Read from the file at start, never stored or imported