Agent profiles
An agent profile is a named model tier (deep, strong, fast) that a task selects with profile: instead of spelling out model: and effort:. It lives in harnesses.yaml under profiles:, beside the harness profiles. It does not depend on the harness: deep is the same tier on Claude Code or Codex, with the model id spelled per provider.
profiles:
deep:
providers:
claude: { model: opus, effort: high }
codex: { model: gpt-5.6-sol, effort: high }
strong:
providers:
claude: { model: sonnet, effort: high }
codex: { model: gpt-5.6-terra, effort: high }
fast:
providers:
claude: { model: haiku, effort: low }
tasks:
implementer: { kind: agent, harness: claude, profile: strong, prompt: "..." }
Define an agent profile
Settings › Harnesses writes this shape. Each provider has its own effort, so the providers need not share an effort scale (max is Claude's, not Codex's).
| Field | Type | Default | Meaning |
|---|---|---|---|
providers | mapping | required, unless the older shape is used | A map keyed by provider id, not harness id. Two harnesses on one provider (claude-work, claude-personal) share one spelling. |
providers.<id>.model | string | required | The model id, spelled the way that provider accepts it. |
providers.<id>.effort | string | unset | The effort for that provider. It must be one the provider accepts. |
fallback | list | unset | The default fallback list for a task that selects the agent profile and sets none of its own. |
An agent profile may leave a provider out. It then cannot run on a harness of that provider. Only a task that actually pairs the two is refused, so a new provider never breaks an existing agent profile. Kraft never guesses a model for a provider the agent profile does not name.
An agent profile is written in one shape, never both. A bad effort is named: profiles.deep.providers.codex: effort 'max' is not accepted by provider 'codex'.
The older shape
An older shape, one model: map with one shared effort, still loads. Kraft reads its effort as every provider's:
profiles:
fast:
effort: low
model: { claude: haiku }
Select an agent profile in a task
A task takes one route: profile:, or its own model: and effort:. It cannot set both.
Through extends, the nearer layer's route wins whole. A task that sets profile: drops the model and effort it inherits. A task that sets model: or effort: drops the inherited profile.
Precedence and when an agent profile is read
An agent profile ranks where the task's own model and effort would. The node override, the item override and escalation rank above it. The repo's models: and the harness profile's defaults: rank below it.
The task's agent profile name is frozen with the chain at intake. The agent profile's body is read from harnesses.yaml at every launch, so editing deep changes every later launch that selects it, including on items already running.
Agent profiles from an add-on
A Kraft add-on may ship agent profiles in its profiles.yaml. Each is named <namespace>:<name>, such as release:careful, and a task or a fallback entry selects it by that name. GET /api/harnesses/profiles and kraft admin harnesses list them beside your own. They are read-only.
An add-on's agent profile is not read live. A work item reads it from the add-on version its chain was built with, until the item ends, so an update to the add-on changes no item already filed. An agent profile in your own harnesses.yaml is still read at every launch. See What a work item pins.
An agent profile id in harnesses.yaml never contains :.
Validation
Kraft checks each pairing of a task with its agent profile:
- the agent profile exists;
- it names a model for the provider of the task's harness;
- that provider accepts the model and the effort.
A bad pairing is reported with the chain, task, agent profile, provider and harness:
chain 'default' task 'implementation.main.implement': profile 'fast' has no model for provider 'codex' (harness 'codex')
Kraft reports it in these places:
- Settings › Harnesses;
kraft admin harnesses;kraft admin templates lint;kraft admin doctor, as a failing check.
Kraft refuses a harness save that would cause one. At launch, a task with a bad pairing stops and waits for you with the same text. Kraft never substitutes another model.
Shipped agent profiles
The shipped harnesses.yaml has the three tiers above. The shipped library puts implementer, the three repair_* tasks and strict_judge on profile: strong (sonnet at high effort).
An install seeded before agent profiles existed keeps its own files. kraft admin doctor lists the missing profiles: section under what the install is missing.
Related
- Fallback and escalation: the
fallback:list an agent profile may carry. harnesses.yaml: everyharnesses.yamlkey.- Switch a task to another harness: add a provider to a tier before moving a task.