Foreman›Docs›Making it yours›Agents and traits
Agents and traits
Making it yours · page 1 of 4
What each of the five agents does, and how to add rules, builders or your own agents.
Foreman builds a story with five agents: an architect, a builder, a tester and two reviewers. This page says what each one reads, decides and hands on, how the rounds between them work, and the three ways you shape them: traits (short rules added to an agent’s prompt), more builders, and agents of your own. It also covers the model each role runs on and how to hand a review to the Antigravity CLI. Read it once your first story has shipped and you want the agents to work the way your team does.
Three levels
There are three levels, from lightest to heaviest:
- Traits add rules without replacing an agent. Put them in
.claude/foreman/traits/all.md(every agent) or.claude/foreman/traits/<role>.md(one role), or list them inroles.<role>.traitsinforeman.config.json. A pack adds its own traits first, so yours win: the Salesforce pack’s every-agent, security-reviewer and tester traits are inplugin/packs/salesforce/traits/. See Trait order below. - More builders. Add an entry under
roles.builderswith auseline. The architect picks a builder by that line. - Replace an agent. Point
roles.<role>.agentat your own project agent, a file in the project’s.claude/agents/. Aforeman:prefix names one of Foreman’s own agents.
The project’s own rules come from its CLAUDE.md, which every agent reads first. Foreman can also add traits and skills by itself; see How Foreman learns.
A role is one of architect, tester, a builder’s name under roles.builders, or a reviewer’s name under roles.reviewers. Each role entry takes agent, traits and model; a builder also takes use and fullChecks; a reviewer also takes prompt and engine. Any other key is a config error. The defaults are:
{
"roles": {
"architect": { "agent": "foreman:architect" },
"builders": { "developer": { "agent": "foreman:builder", "use": "everything" } },
"tester": { "agent": "foreman:tester" },
"reviewers": [
{ "name": "compliance", "agent": "foreman:compliance-reviewer" },
{ "name": "security", "agent": "foreman:security-reviewer" }
]
}
}
Builder and reviewer names are slugs: lower-case letters, digits and hyphens. A reviewer name used twice is an error. roles.builders in the file replaces the whole default set, so a project that adds a builder lists the default one too.
Agent check. foreman doctor (‘role agents’) warns when a role names an agent it cannot find: a
foreman: agent that is not in the plugin, or a project agent that is not in
.claude/agents/ (or in ~/.claude/agents/ when session.userSettings is true). Agents of
other plugins are not checked. A missing builder is still one the architect can pick, and that build fails.
The five agents
Each agent is a Claude Code subagent with its own prompt file in the plugin’s agents/ folder and its own tools. All five read the project’s CLAUDE.md first, then the brief’s ## Project traits section, then any learned skills listed for them, and they run the project’s checks only through foreman checks. None of them commits, pushes or touches the tracker: the story session does that after review (How a story ships).
| Agent | Reads | Decides | Hands on |
|---|---|---|---|
architect (foreman:architect; Read, Grep, Glob, Bash) |
The story note, the code it will change, the docs of any library it relies on, and foreman checks --recorded for the last check result. Never runs the checks and never edits a file. |
Whether the story can be built now. It cannot when only the owner can supply something (a key, an account, a decision, a sign-off), when it builds on a story not yet done (the blocker starts with the story ids, so the picker waits for them), when the plan contradicts the code, or when its Done-when already holds (“Nothing to build:”). A story that is only part-buildable is blocked, not half designed. | A design and test plan the builder can follow alone: what changes file by file, data shapes and permissions tied to the project rule that fixes them, tests first with the error path and the refused actor, what must not change, the Done-when line as a check someone can run, the builder chosen from the brief’s ## Builders list, the exclusive resources the story needs and every file it will touch. When the owner must choose between options it also gives an owner_question with a one-line summary, option hints, a recommendation and a plain-words explanation, which becomes a decision on Waiting on you. |
builder (foreman:builder; Read, Write, Edit, Grep, Glob, Bash) |
The design and test plan (or the design file that holds them), and the code around the files it names. | Nothing about scope: it builds the story and nothing beyond it, no refactor on the side, no new dependency the rules do not allow. | The change in the working tree. It writes the tests first and sees them fail, implements until they pass, runs foreman checks --changed --quick while it works and once more before handing over (foreman checks --changed for a builder with fullChecks), keeps the project’s docs true where CLAUDE.md asks, and reports what it built, the files, each command and whether it passed. Sent back with findings, it fixes every blocker and major and says what it changed, or says why a finding is wrong. |
tester (foreman:tester; Read, Grep, Glob, Bash) |
The working tree against where the branch left the base (git diff --merge-base <base>), never a local base branch. Takes nothing on the builder’s word. |
Approve or reject. It runs every check itself with foreman checks --changed (never --reuse), does what the Done-when line says and observes the result, reads each test to see it would fail if the behaviour broke, tries to break the change (empty, oversized and malformed input, the wrong actor, the second call, a failing dependency) with throwaway scripts in the temp folder, and checks the change stayed in scope. A failing or skipped check, a test that asserts nothing or was weakened, is a blocker. |
Findings graded blocker (wrong, unsafe or untested), major (works, but a required case or the Done-when line is not met) or minor, each with file and line, what it observed and what would fix it, plus what it ran. It approves only with no blocker and no major, and leaves the tree exactly as it found it. |
compliance-reviewer (foreman:compliance-reviewer; Read, Grep, Glob, Bash) |
The same diff, the story, its design and the project’s rules; the check results through foreman checks --changed --reuse. |
Whether the story was built the way the project agreed to build: the change does what the story says and no more, each CLAUDE.md rule it touches holds, each behaviour has a test, no lint rule, test, type check or CI step was weakened without a stated reason, no dependency was added beyond what the rules allow, no fixed file (decision records, shipped migrations, generated or vendored code) was edited, and every doc the project asks to keep current is updated. Security is the other reviewer’s. |
Findings graded blocker (a rule the project marks as must-hold, or a file that must not change), major (another rule) or minor, with the rule broken and the fix; “no findings” and what it checked when there are none. No style comments. |
security-reviewer (foreman:security-reviewer; Read, Grep, Glob, Bash) |
The same diff, CLAUDE.md and any security rules or architecture it names; the check results through foreman checks --changed --reuse. |
Eight things, each cited file:line: access checks on every new entry point, input validated before use, no injection through pasted strings, no secret or personal data in code, logs, fixtures, URLs or errors, no internal detail in a response, no untrusted data fed to a parser that can run code, each new dependency needed, pinned and free of known vulnerabilities, and every security rule CLAUDE.md names. |
Findings graded blocker (exploitable, or a must-hold security rule), major (a real weakness) or minor, most severe first, then what it checked and found clean. |
The relay agent (foreman:review-relay) is a sixth, small one: it only carries a review to an outside CLI and back, and never reviews. See A reviewer through the Antigravity CLI. The Salesforce pack brings its own set of agents; see Agentforce and OmniStudio and Salesforce overview.
Rounds, and who sends a story back
The pipeline runs the agents in four phases: Architect, Build, Test, Review. A round is one pass through Test and Review on a built change. A story gets rounds build attempts in all (the first build plus the fix rounds; the setting is in Settings and switches, default 3, from 1 to 10).
- The architect runs once. A plan is saved as a file, so a story that is picked up again after a deferral, a stop or a restart keeps its design. It is designed again only when one of the files the plan names has changed on the base branch since; see How Foreman picks.
- The builder builds, then the tester runs. If the tester rejects, the reviewers do not run that round: reviewing code that is about to change is wasted work.
- If the tester approves, every reviewer in
roles.reviewersruns side by side, each on its own copy of the prompt. - A finding marked
blockerormajorsends the story back. The tester and each reviewer can do that; aminorfinding never does. All stopping findings from the round go to the builder together in one fix round, and the next round runs the tester and the reviewers again on the fixed change. - A stage that returns nothing counts as a blocker (“stage did not report”).
- With no stopping finding left, the story passes with its minor findings listed, and the story session commits and releases it. After
roundsattempts it fails with the findings still open and the story goes to the owner (When things go wrong).
Two special starts skip the architect: a fix round at the start (a change already built that CI or a merge sent back) and a resume (a session that stopped after the build; verdicts whose findings were all minor are carried over, and a reviewer’s only together with the tester’s). The minor findings a shipped story leaves can become a follow-up story; see How Foreman learns.
Every prompt ends the same way: the story header, then the ## Checks section (each check’s command, when it runs and its quick command), then ## Project traits for that role, then ## Learned skills. When any role has learned traits or skills, the tester and the reviewers are also asked to raise a finding with the [L-n] tag when a learned rule is wrong.
Salesforce builders
The pack lists the admin and developer builders, plus the
Agentforce builder unless salesforce.agentforce is off. No OmniStudio builder ships yet,
whatever salesforce.omnistudio says: the architect gives OmniStudio work (Data Mappers,
Integration Procedures, OmniScripts, FlexCards) to the developer builder. To use your own
OmniStudio agent, add it under roles.builders with a use line. The Salesforce pack is a preview: its release paths pass their own tests, but no story has yet shipped through them on a live org.
Choose a model per role
roles.<role>.model (roles.builders.<name>.model, and
roles.reviewers[i].model in the file) is one of haiku, sonnet, opus or fable.
Unset, the agent uses the story session’s model. The pipeline passes the model to each agent call only when the role sets one, so a project that sets none runs exactly as before. The Salesforce pack’s roles take model the same way, through the same roles block.
session.model is a different thing: it is the model of the story session that moves the story between stages and ships it, not of any agent, so changing it leaves every roles.<role>.model as it was.
The dashboard’s Settings tab has an Agent models group with one dropdown per role the project has, in the order architect, each builder, tester, each reviewer; “Same as the story session” removes the choice. From the command line, foreman settings set roles.tester.model haiku or foreman settings set roles.reviewers.security.model haiku does the same (a reviewer’s dotted name stands for the reviewer of that name in the roles.reviewers array), and foreman settings list --group models shows them. Saving one for the team (--team) copies that role’s block into foreman.config.json when the file has none: the role object, the whole builders object or the whole reviewers array, so the file still validates. A change applies from the next story.
Foreman reads the model each agent actually ran on from its transcript. The dashboard’s command centre shows it beside the agent, the run’s events name it when an agent finishes, and the token report lists the models each role ran on. When an agent ran on another model family than its role is set to, the command centre adds a note such as “Set to Opus, runs on Sonnet 5.5”, the run record keeps the mismatch, foreman report lists it under Models, and foreman doctor (‘agent models’) warns about the newest session of the last 7 days whose record has its agents. The warning clears once a later session runs on the right models. The relay agent always runs on sonnet; it only copies text.
Trait order
Traits are short markdown texts added to a role’s prompt under ## Project traits. Every source applies, in this order, and the later ones win when they disagree:
- The pack’s
all.md, then the pack’s<role>.md, from the pack’s traits folder. A project with no pack, or a pack without traits, has none here. .claude/foreman/traits/all.mdin the project, for every role..claude/foreman/traits/<role>.md, for that role.- Each entry of
roles.<role>.traitsinforeman.config.json, in order. An entry that names an existing file is read; one ending in.mdor.txtthat does not exist is a config error; anything else is the trait text itself. - Foreman’s own learned traits, from the state folder’s
learned/traits/all.mdand thenlearned/traits/<role>.md, each entry tagged[L-n]. They sit under the heading “Learned by Foreman (CLAUDE.md and the traits above win)”, so your text wins. They are left out altogether whenlearning.applyisfalse. They are capped at 3 KB per role: the entries with the highestLnumbers are left out first, with a warning that names them, and an entry without a tag is never left out.
A role’s whole traits text over 8 KB gets a warning too; keep traits short. A trait file or list entry can be any markdown, but the agents read it as rules, so write it as one.
foreman traits add <role> <text...> appends the text as a new paragraph to .claude/foreman/traits/<role>.md, creating the folder and file when needed. The role is all or a role the config names; any other name is refused with the list of known roles. For example:
foreman traits add tester "Always run the slow suite before approving."
foreman traits add all "Dates in the API are ISO 8601 strings, never epoch numbers."
The trait files live in the project, so commit them and the team gets them. With learning.auto off, foreman learn proposes traits for you to approve the same way; see How Foreman learns.
Reviewer prompts
Each reviewer gets the same brief as the tester (the story header, the design and test plan, the Done-when line, and what the builder says it did), followed by its own review prompt. roles.reviewers[i].prompt, a string, replaces that prompt. Unset, a reviewer named security is told to review the story’s changes as the working tree against where the branch left the base, untracked files included, and to grade each finding blocker, major or minor; every other reviewer is told to “Review this story’s changes against the plan and the project’s rules.” The prompt is only the instruction line; the reviewer’s own agent file (foreman:compliance-reviewer, foreman:security-reviewer or yours) still says how it works.
A third reviewer is one more entry:
{
"roles": {
"reviewers": [
{ "name": "compliance", "agent": "foreman:compliance-reviewer" },
{ "name": "security", "agent": "foreman:security-reviewer" },
{
"name": "api",
"agent": "api-reviewer", // .claude/agents/api-reviewer.md in the project
"prompt": "Review the public API of this change against docs/api-rules.md. Grade each finding blocker, major or minor.",
"traits": ["Cite the rule number from docs/api-rules.md in every finding."]
}
]
}
}
Every reviewer must answer in the pipeline’s verdict shape (approved, findings with severity, rule, where, observed and fix, and checked); the pipeline asks for it as a schema, so a project agent needs no special output code. A reviewer with no blocker or major finding approves.
A reviewer through the Antigravity CLI
A reviewer with engine runs outside Claude Code, on
that tool’s own plan and limits, so the review costs no Claude tokens beyond a small relay.
Today’s one engine is the Antigravity CLI (agy, installed and signed in on the machine that runs
Foreman):
{
"name": "security",
"agent": "foreman:security-reviewer",
"engine": { "name": "antigravity", "model": "<an agy model>", "minutes": 20 }
}
engine.name must be antigravity; engine.model is one of the models agy models lists, as a non-empty string; minutes, a whole number from 1 to 180, caps one review and defaults to 20. The builder, tester and architect always run on Claude.
You can also set the engine without opening the file. The dashboard’s Agent models settings have an engine row for each reviewer, under its model row, written as engine:model; foreman settings set roles.reviewers.security.engine antigravity:claude-opus-4-6-thinking does the same. Setting it writes the reviewer’s engine block (name and model; a minutes already there is kept), and emptying it removes the whole block. The reviewer’s model row is then the Claude model it falls back to when its engine cannot run, or the model it runs on when it has no engine.
While a relayed review runs, the slot’s agent card on the command centre shows the reviewer, such as Security, “via Antigravity”, on the engine’s model. Until the relay has named its reviewer, the card reads Review relay.
How a relayed review runs:
- The pipeline hands the full review text to the relay agent (
foreman:review-relay, onsonnet), between<<<REVIEWand>>>REVIEWmarkers, with the reviewer’s name and the text’s character count. - The relay writes the text byte for byte to
foreman-review-<reviewer>.mdin the temp folder and runsforeman review --start --reviewer <name> --prompt <file> --chars <count>. That command checks the reviewer exists and has an engine, that the copy’s length is within 2% of the count (a short copy would review less than Foreman asked), and thatagy --versionanswers; then it copies the prompt into the state folder, starts a detached worker and prints an id. - The worker runs
agy -pwith the reviewer prompt,--modelfrom the config, in plan mode so it edits nothing, with JSON output and Foreman’s verdict schema, and--print-timeoutset tominutes. It may run the targeted tests the prompt asks for. - The relay runs
foreman review --wait <id> --for 540and reads the answer. Exit code 75 means the engine is still working, and the relay waits again, up to six times in all.--fordefaults to 90 seconds. - A finished review prints the verdict as JSON with
engine,model, the seconds it took and its usage; the relay answers with it and the pipeline takes it as the reviewer’s verdict. The CLI’s own JSON is read first; a verdict inside a code fence or after narration is tolerated; a verdict of the wrong shape is refused.
When something fails, foreman review prints an “unavailable” JSON (engine: "unavailable", a reason, no findings) with exit 1, and the relay answers with it. That happens when the config has no such reviewer or it has no engine, the prompt file cannot be read, the count is wrong, the CLI does not answer (missing, or not signed in), the engine prints nothing or no JSON, answers a status other than success (out of quota included), gives no verdict, its process is gone with no result, or it is still working after the sixth wait (over time). The pipeline then logs “the antigravity engine was unavailable for the <name> reviewer (<reason>); running its own agent” and runs the reviewer’s own Claude agent as if there were no engine. The story is never left unreviewed.
When the CLI says its quota is used up, Foreman reads when the quota resets from the message (an hour from then when the message gives no time) and records it. Until that time, every review goes straight to the reviewer’s Claude agent and no relay agent is started: foreman review --start answers unavailable at once, naming the reset time, and foreman workflow-args leaves the reviewers’ engine out of the args, saying on stderr that the engine is out of quota until then. Once the time passes, reviews go through the engine again.
The relay’s files live in <state folder>/review-engine/, named by the id: <id>.json (the job), <id>.prompt.md, <id>.out and <id>.err (what the CLI printed) and <id>.result.json. The quota record sits beside them as down.json, with the engine, the time it is down until and the reason. Relays older than a day are removed. foreman doctor adds a check, ‘review engine antigravity’, for each engine a reviewer names: it warns when agy --version fails, says that reviews with that engine fall back to the Claude reviewer, and tells you to install the CLI, sign in and open a new terminal. foreman review is on Every command.
What every agent may not do
A story session runs under Foreman’s guards, whatever the agent: it runs the project’s checks only through foreman checks, searches only inside the project, the state folder, ~/.claude and the temp folder, never writes the real project’s config, settings or keys, never stops the run, and the tester and reviewers are kept off production hosts (ship.productionHosts, or the smoke URLs’ hosts and the Supabase project’s when unset). The full rules, the commands that are denied and what the agents do instead are on Story sessions.
Was this page useful? Something missing or wrong?Email us and say which section.