-
Notifications
You must be signed in to change notification settings - Fork 0
agentm persona activation
title: persona activation — design status: launched kind: design scope: feature area: agentm/personas governs: [] parent: agentm-hld.md seeded: 2026-06-26 approved: 2026-06-26
Persona activation is how agentm puts on a persona — the Engineer, the Reviewer, the Planner — and gives it the right model, standards, and tools for the job. The pieces a persona is made of are designed and mostly built; this is the part that switches one on, and it's the last piece still missing — parent agentm HLD.
A persona is a hat the agent wears for a job — the Engineer, the Reviewer, the Planner — each borrowing tools from the toolbox without owning them. The persona tier design already built the parts a persona is made of: the persona file format, the check that validates it, the always-on brain (the memory engine that sits under every persona), and a first Planner persona. What's missing is the step that puts a persona on while the agent is running — picking it, loading it, and giving it its model, standards, and tools. This design is that step.
Today the persona files sit on disk but nothing turns one on — the Planner persona is a file that "cannot yet be activated." Several neighboring designs lean on this step without building it: the opinions design hands off where a persona's standards get loaded, model + effort routing hands off where its model gets set, and persona-tier leaves its own load-and-show step for later. Enough waits on it that it has to come first — the full persona roster, automatic switching, and the Planner that keeps the github-projects board up to date.
Activation is a short pipeline with one job — turn a named persona into a running one — built to the shape of the resolvers agentm already has: pure, one-way, and graceful when a binding is absent.
A persona is selected, gated, loaded on demand, has its three bindings resolved through their own resolvers, composed with Memory beneath, and run in its mode. On the sub-agent path it compiles down to the host's native dispatch.
A persona is chosen for a task one of three ways. v1 ships the first two; the third stays research-open (operator ruling).
-
Explicit invocation. The operator launches a named persona in a mode it declares — a session wearing the hat, a
/loop, a/goalrunner, or a dispatched sub-agent. Fully tractable; the v1 floor. -
Workflow-step adoption. A crickets phase command puts the fitting persona on for its step —
/workwears the Engineer,/reviewwears the Reviewer. This rides the phase command: the phase spec names the persona to adopt, so it is deterministic and makes adoption feel native. -
Auto-detection from the task (research-open). A mid-conversation cue selects a persona — a design question surfaces the Designer, a failing diagnosis the Troubleshooter. Reliable mid-conversation intent classification to swap stance is an unsolved problem: there is no trigger grammar, confidence gate, false-switch ceiling, or per-turn cost budget for it yet. The design carries the cue as the
triggers:field and binds it only on the sub-agent path, where the host does the routing; automatic in-session stance-swap stays research-open.
Five calls settle how selection behaves once more than the happy path is in play:
-
The phase spec is the source of truth for a workflow step. A crickets phase names the persona to wear; a manifest's
triggers:field feeds only the sub-agent routing path, so the same field never becomes a second, competing selector. -
An explicit choice wins. Precedence runs explicit invocation > workflow-step > auto-detection, so an operator's chosen stance is never silently overridden and auto-detection is the lowest tier. A workflow-step adoption on the sub-agent path is per-dispatch — a cold Reviewer dispatched by
/reviewdoes not contend with the stance worn in the interactive session. - There is no default opinionated persona. When nothing is selected, the working stance is the brain alone (Memory plus the bare agent); wearing an opinionated persona is always an explicit or workflow-step act.
- Operator-initiated switching ships; automatic switching does not. Re-invoking adoption in a session re-runs the pipeline and swaps the stance — an explicit operator act. Only cue-driven automatic switching stays research-open, because the hard part is reading intent, not the swap itself.
-
One opinionated stance at a time, with the brain beneath. An agent wears one stance plus the brain; a persona that needs another — a Tech-Lead needing a Reviewer — dispatches it as a sub-agent. Stacking two stances would make the
tier:andopinions:bindings ambiguous and break single-threaded coherence.
adopt(persona, mode) runs six steps:
-
Select — resolve the persona name to its manifest in
personas/(an explicit name, or the persona the phase step declares). -
Gate — the manifest must pass
check-personas(itsrequires:resolve to substrate). A manifest that fails the gate is never adopted. -
Load on demand — read the manifest body now, reusing the on-demand memory-load path.
brainis always-on through the recall hook; every other persona is dormant until adopted. - Resolve bindings — fold the three axes through their resolvers (below).
-
Compose — the stance (the manifest body) + the resolved tools (from
enhances:) + Memory beneath become the working persona. An absentenhances:tool degrades to absence; the persona still runs on a bare agentm. -
Run — realize the mode: injected context for an interactive session, a dispatched sub-agent (cold or warm), a scheduled
/loop, or a/goalrunner. The Reviewer runs cold on the sub-agent path, for adversarial independence.
Memory beneath is automatic. Every persona is Memory plus a stance — recall at the start, reflect at the end — so the brain composes under every adoption as a built-in pipeline step. The manifest carries no Memory axis; the pipeline supplies it.
A persona stays an ordinary agent-def: an opinionated prose body, an optional model: and read-only tools:, and its declared deps. The gate validates three invariants today (kind, requires: ⊆ substrate, no always-load); activation adds four declared axes, each wired into the gate as part of this build.
---
kind: persona # the primitive — gate-checked (must be "persona")
name: reviewer # the dispatch key / filename
requires: [...] # hard deps — gate-checked: must resolve to substrate
enhances: [code-review] # soft composition — any capability; an unmet one degrades
always_load: false # the gate rejects always_load: true for every persona
# --- added by activation ---
tier: T2 # T0 Mechanical … T4 Deep — declared here, the scale owned by model-effort routing
opinions: [good] # the Opinion surfaces it leans on — resolved via opinion_resolve
modes: [sub-agent, interactive] # the launch modes it supports — subset of {sub-agent, interactive, loop, goal}
triggers: [review-phase] # automatic-adoption signals — a workflow-step name, or a cue compiled to the host description
---
The stance — the opinionated prompt body.The persona's working state is not in the manifest; it comes from Memory beneath.
Each binding resolves through the resolver that owns it; activation applies the result and never reaches back. All three resolvers are pure and never raise, so a missing binding degrades gracefully and adoption still completes.
-
tier:→ the model + effort routing scale (defined in that design, not in agent memory). The tiers are a five-rung model-and-effort ladder: T0 Mechanical (cheapest model, low effort — rote edits, log-scraping), T1 Execute (opusplan, medium effort — long autonomous build stretches), T2 Author (strongest model, high effort — planning, design, holding the technical bar), T3 Architect (strongest, max effort — cross-system design and roadmap calls), and T4 Deep (strongest, max effort plus orchestration — research and adversarial audit). Activation resolves the persona's declared tier to a concrete model + effort and applies it; the persona declares its tier, the routing design owns the scale. -
opinions:→opinion_resolve(name)from the opinion registry, folding the coded base ⊕ the learned supplement, always-latest. The persona-adoption seam is exactly the consumer the registry named as activation-blocked. -
enhances:/requires:→capability_resolver.py.requires:is hard (gate-floored to substrate);enhances:is soft (absent → graceful degrade).
The arrows run one way — persona → opinions, persona → capabilities, persona → tier scale. Nothing depends back on the persona.
Activation uses each host's own way of launching an agent, so it adds no per-host machinery of its own. The work splits two ways (hybrid): for a dispatched sub-agent, the installer turns each persona into a host-native agent definition at install time, so the host's built-in routing picks it up; for an interactive session, a /loop, or a /goal run, a persona is put on at run time by injecting it into the session. A small, pure helper — persona_resolve, modeled on capability_resolver and opinion_resolve — does the install-time conversion.
-
Claude Code — the sub-agent path compiles a persona to an agent-def:
name→ the Task tool'ssubagent_type,triggers:→ thedescription(the host's auto-route trigger, which the host enforces),tier:→ themodel:+ effort frontmatter, theenhances:-resolved tools → thetools:allowlist. The interactive, loop, and goal modes ride injected context + slash commands, where model choice is advisory only (a host can nudge/model). The always-onbrainrecall fires through hooks. -
Antigravity — no first-class sub-agent slot, so a persona compiles to a
SKILL.mdwrap (the existing sub-agent-as-skill pattern); the parent agent reasons over the skill description and delegates through the runtimestart_subagenttool. Hooks have no Antigravity surface, so the brain's hook-driven recall is Claude-Code-only.
install.sh learns to dispatch personas/ — today its agent dispatch walks harness/agents/ only. The per-host consequence to state plainly: detection-via-triggers: is enforceable on the sub-agent/description path on both hosts; in-session stance-swap is advisory on both.
Extend check-personas.py (the built gate — exit 0/1/2, in check-all.sh + CI across Linux/macOS/Windows) to validate the four new axes without breaking the three built invariants:
-
modes:⊆{sub-agent, interactive, loop, goal};tier:∈{T0…T4};triggers:well-formed (a workflow-step name or a cue string);opinions:entries are strings. -
Shape only for
opinions:andenhances:— resolution stays a runtime, graceful concern (mirroringopinion_available), so an unmet binding degrades at runtime and never fails the build. - Keep the one-way-arrow invariant: a persona's
requires:stays ⊆ substrate — this is what keeps agentm from hard-depending on crickets. - Keep the no-always-load invariant: the gate rejects
always_load: truefor every persona;brainis always-on through the session-start recall hook.
-
vs the opinion registry — the registry owns
opinion_resolve(base ⊕ supplement); activation calls it at adoption to bind a persona'sopinions:. The registry's CLI + composition-edge consumers work before activation exists; only its persona-axis consumers wait on this. -
vs the capability resolver —
capability_resolver.pyowns name → installed-capability matching; activation composes the resolved tools into the running persona. - vs model + effort routing — that design owns the T0–T4 scale + per-host rendering; activation applies the declared tier at adoption.
- vs persona tier — that design owns the primitive, the gate, and the persona-vs-tool discriminator; this design is its build-part 3 (load-on-demand + the surfacing/activation path), the one part V5-11 did not ship.
-
vs the host dispatch — the host owns
Task/start_subagent+ description-routing; activation compiles a persona down to the host's agent-def orSKILL.mdand rides those rails. A persona is a layer above a host sub-agent — surfaced through one on the cold-dispatch path, while remaining a durable classification that outlives any single dispatch.
-
calls the three resolvers —
capability_resolver.py(built), plus the opinion registry'sopinion_resolveand the model + effort routing scale (both designed, building in the same wave). All are pure, one-way, and never raise. -
extends the built gate —
check-personas.pygains the four new-axis checks; the primitive + the gate stay owned by persona tier. -
rides the host dispatch — Claude Code agent-defs (
Tasksubagent_type+descriptionrouting) and Antigravity'sSKILL.md+start_subagent;install.shlearnspersonas/. -
composes Memory beneath — the always-on
brain(memory system) sits under every adoption. - points up at persona tier (build-part 3) and the agentm HLD §Personas; the crickets side of the wiring is composition.
-
At lift (docs): repoint persona tier's build-part-3
[PENDING-IMPL]to name this design as its specification; add apersona-activationseeding row under theagentm/personasarea in the area-taxonomy (no new area — it joins persona-tier there). -
At build: rename the persona file
personas/brain.md→personas/brain.md(with its test fixture and the reference pages that name it); extendcheck-personas.pyfor the four axes; write the adoption path (persona_resolve/adopt); teachinstall.shto dispatchpersonas/; add the four axes to the two existing manifests (the brain,team-coordinator) and author the rest of the roster as it lands. -
Status honesty: as activation ships, flip persona-tier's build-part-3 and the neighbor
[PENDING-IMPL]markers to as-built; until then, the Planner seed and the ≥4-deep board depth stay hand-maintained.
- Buildability illusion. Activation is the third link in the github-projects ≥4-deep stack (board depth → Planner → activation → opinion registry); each dependent reads "designed" while leaning on this unbuilt seam. Until it ships, the board depth decays and is hand-maintained; no dependent should claim "done" on an unactivatable seed.
-
Auto-detection is an open design problem. Mid-conversation stance-swap has no trigger grammar, confidence gate, false-switch ceiling, or cost budget — so it stays research-open, split from the explicit + workflow-step path; marking it
[PENDING-IMPL]would re-introduce the hazard. -
Per-host asymmetry. Detection-via-
triggers:is enforceable only on the sub-agent/description path; in-session stance-swap and model choice are advisory on both hosts. A reader should not assume symmetric enforcement in interactive sessions. - Coupled bet. The roster, automatic adoption, and tier-enforcement all stand on this one seam — sequence them as one Wave-B leader feeding Wave-D adopters; none ships independently.
- Resist the persona-zoo. Activation makes adding a persona cheap; add the next one only when a real cross-capability concern with no single-plugin home appears.
-
Re-audit triggers: flip persona-tier build-part-3 + the neighbor
[PENDING-IMPL]markers at ship; design the in-session detection mechanism before promoting auto-detection off research-open; re-pin the host-seam details if a host changes its dispatch surface.
-
Selection ships explicit + workflow-step; auto-detection stays research-open (operator ruling) — the
triggers:field is authored and bound on the sub-agent/description path; automatic in-session stance-swap stays research-open. -
Selection policy (operator) — the phase spec is authoritative for a workflow step (
triggers:feeds only sub-agent routing); precedence is explicit > workflow-step > auto-detection; no default opinionated persona (the brain alone); operator-initiated switching ships, automatic switching stays research-open; one opinionated stance at a time with the brain beneath (multi-persona by dispatch). See §Selection policy. - Memory beneath is automatic — every persona is Memory + a stance; the brain composes under every adoption as a pipeline step the manifest never declares.
- Bindings resolve through their own resolvers, one-way and never-raise — activation applies the result; a missing binding degrades, it does not fail adoption.
- Activation is persona-tier's build-part 3 — it owns the load-and-surface path; the primitive and the gate stay with persona-tier.
-
No per-host runtime adapter — a persona compiles down to the host's native agent-def /
SKILL.md; the installer learns to walkpersonas/and emit each persona in the host's form. -
The adoption logic is hybrid (operator ruling) — the sub-agent path compiles at install time (riding the host's description-routing); a runtime
adopt()serves the interactive / loop / goal modes that inject context.persona_resolvestays pure, mirroringcapability_resolver/opinion_resolve.
-
The resolver precedents (built):
scripts/capability_resolver.py(the one-wayenhances:resolver) ·scripts/governs_resolver.py(the markdown-data, never-raise shape) -
The gate to extend:
scripts/check-personas.py(the built persona validator —kind/requires⊆ substrate / no-always-load) -
The host dispatch to ride:
harness/agents/*.md(the agent-defsinstall.shdispatches;subagent_type/description/model:are the Claude-Code dispatch form the compile step produces) ·install.sh(the agent-dispatch path + the AntigravitySKILL.mdwrap) -
The seeds that run today:
personas/brain.md(the degenerate always-on persona) ·personas/team-coordinator.md(the Planner (TPM) seed + its built capability scripts) - Up: persona tier (build-part 3) · personas (the roster + adoption) · agentm HLD §Personas
- Calls / composes: opinion registry · model + effort routing · memory system (Memory beneath) · composition (the crickets wiring)
Newest first. Collapses to one ≤2-paragraph entry at finalization; git holds the granular history.
-
2026-06-26 — authored, reviewed, and finalized. The fourth Bucket-A substrate sub-design (after runner, reporting, and the opinion registry), specifying persona-tier's build-part 3 — the step that puts a persona on at runtime: it picks a persona, loads its file on demand, sets its model + standards + tools through their own resolvers, composes the brain beneath, and runs it in its mode. Built to the resolver shape agentm already has (pure, one-way, never-raise); uses each host's own agent-launch (Claude Code agent-def +
Task; AntigravitySKILL.md+start_subagent); extends the builtcheck-personasgate for four new manifest axes (tier:/opinions:/modes:/triggers:). Operator calls: selection = explicit + workflow-step (auto-detection research-open) plus the five-part selection policy (phase-authoritative · explicit-wins · brain-only default · operator-switching-only · one-stance-with-the-brain-beneath); Memory beneath automatic; bindings one-way + never-raise; activation is build-part 3 (the primitive + gate stay with persona-tier); no per-host adapter; hybrid adoption (install-time compile + runtimeadopt()); the always-on persona is named the brain. Re-audit: flip persona-tier build-part-3 + neighbor[PENDING-IMPL]at ship; design in-session detection before promoting auto-detection.