Projects
Every per-project field in agent-orchestrator.yaml — agents, workspace, tracker, reactions, per-role overrides, and more.
The projects key is a map of project IDs to project configs. Each entry tells AO which repo to watch, which agents to use, and how to isolate work. AO spawns one agent session per issue per project — running them in parallel, each in its own git worktree with its own PR.
projects:
my-app: # project ID — used in session names and dashboard
repo: org/my-app
path: ~/projects/my-appProject IDs must match ^[a-zA-Z0-9_-]+$ (letters, numbers, hyphens, underscores — no dots or slashes).
Required fields
Two fields must be present for a functional project:
| Field | Type | Description |
|---|---|---|
path | string | Absolute path to the local checkout. ~ expands to $HOME. |
repo | string | GitHub/GitLab repository in owner/repo format. Used by the SCM and tracker plugins to open PRs and fetch issues. |
Without repo, AO cannot create PRs or listen for issues. Without path, AO cannot find the codebase to create worktrees.
All project fields
name
Type: string Default: project ID
Human-readable display name shown in the dashboard. Defaults to the map key if not set.
name: My Apprepo
Type: string Default: none
The GitHub or GitLab repository in owner/repo format. AO infers whether to use the github or gitlab SCM/tracker plugins from this value (and from explicit scm.plugin / tracker.plugin if set).
repo: acme-org/my-appdefaultBranch
Type: string Default: "main"
The branch agents create feature branches off of and target for PRs.
defaultBranch: mainsessionPrefix
Type: string — must match [a-zA-Z0-9_-]+ Default: derived from path basename
Short prefix used in tmux session names and worktree directory names. AO auto-derives one from the project directory basename using the following rules (see /docs/configuration/storage#session-prefix for details):
- 4 chars or fewer: used as-is (lowercased)
- CamelCase: uppercase initials —
PyTorch→pt - kebab/snake case: first letter of each word —
agent-orchestrator→ao - Single long word: first 3 chars —
integrator→int
Set this explicitly when two projects would otherwise derive the same prefix:
sessionPrefix: app1agent
Type: string Default: defaults.agent (built-in: claude-code)
The AI agent plugin to use for this project. Overrides defaults.agent.
agent: codexAvailable built-in values: claude-code, codex, aider, opencode.
runtime
Type: string Default: defaults.runtime (built-in: tmux)
Where agent processes run. tmux gives you persistent sessions you can attach to from any terminal. process is lighter but sessions are lost if AO restarts.
runtime: tmuxworkspace
Type: string Default: defaults.workspace (built-in: worktree)
How code is isolated per session. worktree uses git worktree add on your existing clone — fast and disk-efficient. clone does a full git clone — slower but completely independent.
workspace: worktreetracker
Type: object Default: inferred from repo
Issue tracker configuration. When repo is set, AO infers github or gitlab automatically. Override by setting plugin:
tracker:
plugin: linear
teamId: "ENG"For external tracker plugins, specify package (npm) or path (local) instead of plugin:
tracker:
package: "@acme/ao-plugin-tracker-jira"Built-in tracker values: github, linear, gitlab.
Extra keys under tracker (trackerConfig)
The tracker schema is open (passthrough) — any extra keys you provide are forwarded to the tracker plugin as its config. Common fields vary by plugin:
GitHub tracker:
tracker:
plugin: github
labels: [agent, automated]
assignee: octocat
milestone: "Q1 2025"GitLab tracker:
tracker:
plugin: gitlab
host: https://gitlab.example.com
labels: [agent]Linear tracker:
tracker:
plugin: linear
teamId: "ENG"
priority: 2Check each tracker plugin's documentation for the full list of supported keys.
scm
Type: object Default: inferred from repo
Source control management configuration. AO infers github or gitlab from the repo value if omitted.
scm:
plugin: githubWebhook acceleration (optional): Instead of polling every 30 seconds, configure a webhook to receive instant CI and review events:
scm:
plugin: github
webhook:
enabled: true
path: /api/webhooks/github
secretEnvVar: GITHUB_WEBHOOK_SECRET
signatureHeader: x-hub-signature-256
eventHeader: x-github-event
deliveryHeader: x-github-delivery
maxBodyBytes: 1048576Set GITHUB_WEBHOOK_SECRET in your environment. Point the GitHub webhook at http://your-host:3000/api/webhooks/github.
symlinks
Type: string[] Default: none
Files or directories to symlink from the project root into each workspace. Useful for .env files and agent config directories that agents need but that should not be committed or duplicated.
symlinks:
- .env
- .claudePaths are relative to path. AO logs a warning and skips symlinks that do not exist.
postCreate
Type: string[] Default: none
Shell commands to run inside the workspace after it is created, before the agent starts. If any command fails, AO logs the error and does not start the agent.
postCreate:
- "pnpm install"
- "cp .env.example .env"agentConfig
Type: object Default: {}
Agent-specific settings applied to all agents for this project.
agentConfig.permissions
Type: "permissionless" | "default" | "auto-edit" | "suggest" Default: "permissionless"
Controls how strictly the agent asks for permission before making changes. The legacy value "skip" is accepted and treated as "permissionless".
| Value | Behavior |
|---|---|
permissionless | Agent makes all edits and runs commands without prompting |
default | Agent uses the tool's own built-in permission behavior |
auto-edit | Agent auto-approves file edits but asks for other actions |
suggest | Agent only suggests changes, never applies them |
agentConfig:
permissions: permissionlessagentConfig.model
Type: string Default: agent's built-in default
Override the model the agent uses. Accepted values depend on the agent:
agentConfig:
model: claude-sonnet-4-5For Claude Code: claude-opus-4, claude-sonnet-4-5, claude-haiku-3-5, etc.
For Codex: any model string supported by the Codex CLI.
agentConfig.orchestratorModel
Type: string Default: same as model
When using multi-agent mode, the model used specifically by the orchestrator agent. Lets you run a capable model for planning and a faster one for worker tasks.
agentConfig:
model: claude-haiku-3-5
orchestratorModel: claude-opus-4orchestrator
Type: object Default: none
Per-role config overrides for the orchestrator agent. This is a headline feature of multi-agent mode — it lets you assign a different agent or model to the orchestrator role without changing the global agent setting.
orchestrator:
agent: claude-code
agentConfig:
model: claude-opus-4See Per-role agent overrides for a full walkthrough of setting up orchestrator/worker role splits.
Fields available under orchestrator:
| Field | Type | Description |
|---|---|---|
agent | string | Agent plugin name for this role |
agentConfig.permissions | enum | Permission mode for this role (same values as top-level) |
agentConfig.model | string | Model override for this role |
agentConfig.orchestratorModel | string | Nested orchestrator model (advanced) |
worker
Type: object Default: none
Per-role config overrides for worker agents. Same shape as orchestrator. Use this to run a faster or cheaper model for routine coding tasks:
worker:
agent: codex
agentConfig:
model: gpt-4o
permissions: permissionlessagentRules
Type: string Default: none
Inline instructions included in every agent prompt for this project (Layer 3 of the three-layer prompt system). Written as a multi-line YAML string. This is the fastest way to add project-specific rules:
agentRules: |
Always run the test suite before pushing: `pnpm test`.
Use conventional commits: feat:, fix:, chore:, etc.
Never modify package.json directly — use pnpm add/remove.
Target Node.js 20+. Do not use CommonJS require().agentRulesFile
Type: string Default: none
Path to a Markdown rules file, relative to path. Use this when your rules are long or you want to version-control them separately:
agentRulesFile: .agent-rules.mdIf both agentRules and agentRulesFile are set, both are included in the prompt.
orchestratorRules
Type: string Default: none
Rules applied only to the orchestrator agent. Same multi-line string format as agentRules. Useful for giving the orchestrator specific decomposition or delegation instructions:
orchestratorRules: |
Break each issue into at most 3 sub-tasks.
Delegate implementation to workers; review their output before merging.opencodeIssueSessionStrategy
Type: "reuse" | "delete" | "ignore" Default: none
Only relevant when agent: opencode. Controls what AO does when an existing OpenCode session is found for the same issue on re-spawn:
| Value | Behavior |
|---|---|
reuse | Attach to the existing session and continue |
delete | Delete the old session and start fresh |
ignore | Leave the old session running and create a new one |
orchestratorSessionStrategy
Type: "reuse" | "delete" | "ignore" | "delete-new" | "ignore-new" | "kill-previous" Default: none
Controls what AO does when an existing orchestrator session is found for the same issue. Useful for recovering from restarts without losing work.
| Value | Behavior |
|---|---|
reuse | Attach to the existing orchestrator session |
delete | Delete the old session, start a new one |
ignore | Leave the old session, start a second one alongside it |
delete-new | Delete any new session if one is found (keep old) |
ignore-new | Ignore any new session if one is found |
kill-previous | Kill the previous session before starting the new one |
reactions
Type: Record<string, partial ReactionConfig> Default: none
Per-project overrides for reaction settings. Keys correspond to the global reactions keys. Only the fields you specify are overridden — everything else falls through to the global reaction config.
reactions:
approved-and-green:
auto: true # auto-merge enabled for this project only
ci-failed:
retries: 5 # more retries than the global defaultSee Reactions for the full list of reaction events and available fields.
Complete example
projects:
my-app:
name: My App
repo: acme-org/my-app
path: ~/projects/my-app
defaultBranch: main
sessionPrefix: app
agent: claude-code
runtime: tmux
workspace: worktree
tracker:
plugin: github
labels: [agent, automated]
assignee: octocat
scm:
plugin: github
webhook:
enabled: true
path: /api/webhooks/github
secretEnvVar: GITHUB_WEBHOOK_SECRET
symlinks:
- .env
- .claude
postCreate:
- "pnpm install"
- "cp .env.example .env"
agentConfig:
permissions: permissionless
model: claude-sonnet-4-5
orchestrator:
agent: claude-code
agentConfig:
model: claude-opus-4
worker:
agentConfig:
model: claude-haiku-3-5
agentRules: |
Run `pnpm test` before every commit.
Use conventional commits (feat:, fix:, chore:, etc.).
Never push directly to main.
agentRulesFile: .agent-rules.md
orchestratorRules: |
Break large issues into at most 3 sub-tasks.
reactions:
approved-and-green:
auto: true
ci-failed:
retries: 5Common failure modes
"Project ID must match [a-zA-Z0-9_-]+" — the project map key contains a dot, slash, or other special character. Rename org.my-app to org-my-app or my-app.
Duplicate map key silently collapsed — if you list the same project ID twice in YAML, standard YAML parsers keep only the last definition. AO will run with the second entry and silently drop the first. Use unique keys.
"Duplicate session prefix detected" — two projects auto-derive the same prefix from their directory basenames (e.g. both ~/work/api and ~/personal/api produce prefix api). Add an explicit sessionPrefix to at least one of them to resolve the conflict — AO prints a suggested fix in the error message.
"Duplicate project ID detected" — two project paths share the same directory basename. AO uses the basename as an internal project ID for storage paths. Rename one of the directories, or set sessionPrefix explicitly (which resolves the storage collision).
Missing GITHUB_TOKEN / GITLAB_TOKEN — the SCM and tracker plugins require an auth token in the environment. Without it, issue fetch and PR creation will fail at spawn time with an authentication error.
postCreate command fails — AO logs the error and skips starting the agent. Check that all dependencies (e.g. pnpm) are available on $PATH and that any referenced files (e.g. .env.example) exist.