Compose agent personas and context
agent-compose composes the persona and context an agent harness loads. It selects a role, the personality meld that role carries, the skills that role can see, and the tool inventory it gets, then materializes one immutable bundle of plain files. Claude Code, Codex, Goose, and OpenCode all take the same bundle.
The bundle is context and nothing executable. Permissions, runtime facts, and
lifecycle stay with whatever launches the agent, so a role slug travels without
authority attached to it. You can read and diff every file before a run, and
verify reports the bundle complete before you do.
roster:core is the zero-config default. It describes thirteen seats and offers ten,
because three are archived. Each one answers to its own
creature (no pronoun - a seat is not a person), a charter, and a meld of two
personality traits that shape how it writes and what it reaches for first.
- 🪢🪨 Beetle-Ox - Platform Engineer - builds and lands the foundational software the rest of the estate is built on. Tenacious and grounded.
- 🛡️🪨 Turtle-Ox - Systems Administrator - operates the real hosted systems and release surfaces. Protective and grounded.
- 🛡️🪨 Turtle-Ox - Junior Sysadmin - diagnoses hosted systems and hands mutating commands to the human. Protective and grounded.
- 🛡️🪨 Turtle-Ox - Access Sysadmin - owns agent permission and harness configuration values across the estate. Protective and grounded; launches on Codex or Goose.
- 🧪🪨 Frog-Ox - Applied Scientist - measures how agents, models, and inference actually behave on real hardware. Empirical and grounded.
- 🎨🌈 Imp-Dragonfly - Frontend Engineer - shapes and builds the surfaces a person navigates. Playful and imaginative.
- 🤿🌈 Whale-Dragonfly - Game Developer - ships playable games, the code and the assets and the build that carries both. Immersed and imaginative.
- ✂️🔭 Griffin-Goose - Portfolio Director - decides what the portfolio does next, and carries each decision to its gate. Decisive and outward.
- ✂️🔭 Griffin-Goose - Project Manager - keeps the tracker true and hands decisions to the director. Decisive and outward.
- 🕯️🔭 Panda-Goose - Developer Advocate - turns real work and audience evidence into accurate content and informed commitments. Warm and outward.
- 🪞🪢 Snake-Beetle - AI Risk Analyst - archived - assessed whether an AI system was fit to ship, named the exclusions, and stood behind the file that proved it. Suspicious and tenacious.
- 🕯️🛡️ Panda-Turtle - Behavioral Psychologist - archived - stayed with what a person actually brought, and named the thing they were steering around before offering relief. Warm and protective.
- 🪢🔭 Beetle-Goose - Investigative Reporter - archived - worked out who an unmet party was from what they published, and said whether to approach them at all. Tenacious and outward.
The catalogue lists eleven traits. Five belong to one seat alone (🪞 suspicious, ✂️ decisive, 🧪 empirical, 🤿 immersed, 🎨 playful) and six are bonds two or more seats share: 🪨 grounded across the builders and sysadmin twins, 🌈 imaginative across the two makers, and 🔭 outward, 🪢 tenacious, 🕯️ warm and 🛡️ protective across the rest.
Each personality carries a color, an emblem, a motif, and a body written in
prose, which is where the creature art comes from and what a voice melds along
with the role's own. See docs/identity.md and
docs/personality.md. just palette-serve renders the
whole catalogue locally.
Selection is exclusive. An external person package contributes its own roles,
seats, personality definitions, and evaluation context, and it replaces
roster:core wholesale rather than merging with it. An external-only policy
makes that boundary fail closed across the machine. See
docs/person-packages.md.
From the public internet, with Go 1.25.5 or newer:
git clone https://github.com/coilyco/agent-compose.git
cd agent-compose
go install ./cmd/agent-compose
mkdir -p ~/.agent-compose && cp -R seed/roster ~/.agent-compose/roster
agent-compose catalog rolesThe binary carries no roster, so the copy is required. Skip it and the first
catalog roles reports no roster is mounted, naming every path it tried.
go install writes to GOBIN, by default $(go env GOPATH)/bin, which needs to be on your
PATH. agent-compose version reports the build you are running.
Releases publish to this project's canonical forge, forgejo.coilysiren.me, which resolves
only on the tailnet, and the GitHub mirror trails it with no roster asset. On the tailnet, the
Homebrew tap, Scoop bucket and raw release binaries install acompose and the roster too. The
commands are in guides/quickstart.md.
acompose # converge the host from the local catalogue
acompose -- <command> # refresh context, then exec the command
agent-compose launch <role> <harness> # launch one harness with an assigned roleNew here? guides/quickstart.md goes from an empty terminal to a composed role, and the role guides beside it cover when to reach for each seat.
--reapply rewrites the host compose layout even when it is already current,
and --verbose prints every source => destination mapping it places.
--explain adds the role briefing, the credits, the expression vocabulary,
and the full decision tree to the summary.
When you want to see what a bundle actually decided rather than trust it,
describe renders its stored decision tree, diff reports the semantic change
between two bundles, and verify checks one is complete and safe to consume.
Composition adapters can project a verified bundle into an empty staged home
and wrap it in their own schema. See
docs/staged-home.md.
The evaluation board is derived from the roster rather than written beside it.
challenges.yaml holds the cases the roster implies:
boundaries and their owners produce the pairs, adjacency produces the role-fit
targets, and each role's meld produces the personality cases. Add a boundary,
flip an adjacency edge, or swap a personality, and the challenge list moves with
it. Every case corresponds to something in the roster, and every roster change
moves what gets tested.
The hard cases are generated on purpose. Role adjacency names each role's two likeliest absorptions, and those reasons become the descriptors a generator uses to build exactly the confusion a seat is most at risk of.
Three parties and none of them holds two seats: a generator authors the cases, a
subject answers them through a model gateway, and a human grades them. The grading
half ships separately as housecast grade, so it holds no runner and no model
client, and grading never spends a token or touches a deployed system.
Details in docs/evaluation.md.
Two pieces of the eval half come from outside this repository. housecast is pinned by tag, and the subject answers through a model gateway, an internal transport, so running the board yourself means supplying a model transport in its place.
The composer stands on its own. The bundle, the roster, the cascade, describe,
diff, and verify all work with the eval stack absent, which is the half you
get from brew install alone.
Dev verbs are recipes in the justfile. just test runs the Go tests
plus the full hook sweep. just smoke builds the real acompose entry point and
converges an isolated temporary home twice, covering roster, cascade, skills,
load points, and idempotence without touching live host state or the network.
just palette-serve starts the local personality palette explorer.
Every push to canonical main validates and publishes the next minor release.
The canonical forge is the source of truth and the GitHub mirror is verified.
MIT. See LICENSE.
- guides/quickstart.md - install, configure, converge.
- AGENTS.md - agent-facing operating rules.
- docs/FEATURES.md - inventory of what ships today.
- docs/architecture.md - the composition boundary.
- docs/ownership.md - who owns which boundary, and why.
- docs/evaluation.md - the generator, subject, and grader split.
- docs/release.md - the automatic release pipeline.
- justfile - development recipes.
