The format
An agent is a Markdown document with two parts:- YAML frontmatter — the machine-readable declaration: name, model, tool permissions, budgets.
- A Markdown body — the agent’s instructions. This becomes its system prompt.
Frontmatter reference
Why the description matters
Two audiences readdescription, and neither is your agent itself:
- You, choosing agents for a workflow — the workflow editor and the agent library show it as the one-line summary of what an agent does.
- Other agents, deciding whether to delegate to it — an agent choosing a sub-agent to spawn sees only its name and description, so those two lines are the entire interface it has to go on.
allowed-tools restricts, it doesn’t grant
Listing a tool doesn’t create capability that doesn’t exist — it narrows the agent to a subset of what the
harness already offers. See the tool reference for valid names.
Restricting tools is a real design technique, not just hygiene. An agent that shouldn’t modify code should
not be given shell, and a verifier that must stay honest should not be given the ability to report
findings. Console’s own policy-fix-verifier works this way: it is deliberately read-only so its verdict
can’t be self-serving.
Budgets: maxIterations and timeout
Both are ceilings, not targets. Leave them unset unless the agent is an outlier.
- Raise
maxIterationsfor agents that legitimately need many tool calls — a broad scan across a large repository. - Raise
timeoutfor orchestrators, whose wall clock includes every child they spawn. Set it above the worst-case sum of the children’s durations.
Contracts: what a step produces and consumes
When you chain agents into a workflow, Console needs to know which step’s output feeds which step’s input, so it can run steps that don’t depend on each other together, wait for the ones that do, and skip a step that has nothing to work on. You declare that withproduces and consumes.
produces
The kinds of result this agent’s step may record:
produces is a may, never a promise — an agent that looked thoroughly and found nothing has still done
its job, and nothing checks that a declared kind was actually emitted.
A kind is either one of Console’s own (prefixed amplify:, like amplify:finding or amplify:patch) or one
you define yourself. See defining your own kind below.
consumes
The kinds this agent’s step reads, and how it wants them delivered:
mode: all (the default) runs your agent once, with everything matching that kind from earlier in the
chain — including an empty set. Use this for a step whose job is to summarize or report on the whole run:
“no issues found” is itself a result worth producing, so it needs to run even when there’s nothing to say.
mode: each runs a separate copy of your agent per item (or per group, if you set group-by). Zero
items means the step doesn’t run at all — it’s recorded as skipped, not
as having run and found nothing. Use this when your agent’s job only makes sense one item at a time, like
generating a fix for a single bug.
A step can only consume a kind that an earlier step in the same workflow actually produces. Console checks
this when you save the workflow, not when it runs.
group-by
For a mode: each step, group-by controls what counts as “one item.” By default every result is its own
item; naming fields under group-by batches results that share the same values into a single item instead.
patch-generator, Console’s built-in patching agent, is the canonical example — one patch should fix every
match of the same underlying issue in the same file, not one patch per individual match:
group-by come from the kind you’re consuming — never from anything about how Console stores it:
- A field the kind itself declares, including one nested inside another declared field, like
properties.filePathabove. - A documented attribute of that kind.
amplify:findingadditionally exposesdetection_idandseveritythis way. id— every item is its own group, overriding any default grouping.amplify:findingalready groups by detection and file when you set nogroup-byof your own, so writegroup-by: [id]explicitly if you want one child per finding instead.
group-by: [] isn’t allowed: grouping by nothing means everything is one group, which is what
mode: all already means. Console rejects it and suggests [id] if that’s what you meant.
A result your grouping can’t place — a finding with no detection behind it, say — is left out of that
step, with the reason recorded on the step. It still reaches any other step consuming the same kind with
mode: all.mutates-worktree
Set this to true if your agent edits files in the repository:
Defining your own kind
Ifproduces names a kind that doesn’t already exist in your organization, attach a schema: block and
Console registers it the moment you save the agent — no separate setup step:
type (string, number, integer, boolean, object, or array) and can be marked
required. A string field can restrict its values with enum; an object field declares its own nested
fields; an array field declares the shape of its items.
Saving the identical schema again is a no-op. Changing an already-registered kind’s shape is not allowed —
Console rejects the save rather than reinterpreting artifacts you’ve already recorded under the old shape.
If a kind’s shape needs to change, give it a new name.
Names starting with
amplify: are reserved for Console’s own kinds. You can consume amplify:finding
or amplify:patch in your own agents, but you can’t register a schema: under that prefix.Writing one in the web console
Open Agents and create an agent. The editor is a Markdown editor with:- Frontmatter linting — malformed YAML is flagged as you type.
- A model picker — selecting a model rewrites the
model:line in place, so what you see in the frontmatter is always what will run. - Folders — organize agents as the list grows.
Writing one in the CLI
The CLI loads agent definitions from the filesystem, so an agent is just a file:AMPLIFY_AGENTS_DIR. Definitions load at startup, so restart the CLI after
adding one.
Shadowing a built-in agent
Give your agent the samename as one Console ships and yours takes precedence. This is the supported way
to change built-in behavior — a workflow step referencing that name keeps working and picks up your
version.
Next steps
Tool reference
Valid
allowed-tools values and what each does.The agent library
Built-in agents worth reading as examples.
