Skip to content

Agent roots

An agent root answers “what does this agent need to know before it starts?” It’s a named bundle of domain context: repo, branch, subdirectory, runtime, model, goal, and default artifacts.

From roots.json:

"zimmer": {
"name": "zimmer",
"display_name": "Zimmer",
"description": "The Zimmer orchestrator itself — self-hostable AI coding agent orchestration.",
"url": "https://github.com/tadasant/zimmer.git",
"default_branch": "main",
"user_invocable": true,
"default_goal": "open-reviewed-green-pr"
}
FieldMeaning
url / default_branchWhich repo to clone, and from where
subdirectoryScopes the agent to a subtree of the repo (monorepo case)
user_invocableWhether it appears in the “new session” picker
default_goalSeeds session.goal
default_runtime / default_modelSeeds the runtime and model

The default_skills, default_mcp_servers, default_hooks, default_plugins, and default_subagent_roots fields you’ll see at runtime are not written in roots.json — AIR computes them by inverting default_in_roots from each artifact’s own entry.

RootInvocableRepoNotes
zimmertadasant/zimmerWork on Zimmer itself. All 5 skills default here.
general-agenttadasant/zimmerThe catch-all. AgentRootsConfig::DEFAULT_ROOT.
agent-orchestratortadasant/zimmer-catalogScoped to agents/agent-orchestrator
agentstadasant/zimmer-catalogScoped to agents — the catalog artifacts
catalog-managementtadasant/zimmer-catalogLead root; fans out to the four below
catalog-mgmt-research↳ subagent phasedefault_in_roots: [catalog-management], model sonnet
catalog-mgmt-configs↳ subagent phasesame
catalog-mgmt-proctor↳ subagent phasesame
catalog-mgmt-save↳ subagent phasesame

A root whose default_in_roots names another root becomes a subagent root of it. AIR computes default_subagent_roots on the parent, and the lead root’s agent can then spawn sessions against those phases.

This is how catalog-management decomposes into research → configs → proctor → save. A root never becomes its own subagent, even via the "*" wildcard.

At session creation (Session#create_from_agent_root!), the root supplies defaults that the caller can override:

Once seeded, the session owns its own lists. The UI’s PATCH endpoints mutate them directly, and air prepare is called with --without-defaults so AIR won’t re-add anything the user removed.

Roots live in roots.json at the repo root and are resolved through AIR like every other artifact. Adding one is a PR. Zimmer’s own zimmer-change-ai-artifact skill is the guide, and the invariant it enforces is the one that matters: no dangling references.