Structure

Astragentic is not a runtime and it is not a method. It sits between the two: underneath it, Claude Code running a model; above it, your real repository; and the method comes from mattpocock-skills. What Astragentic writes itself is the coordination, and only that.

I split it into four layers because each one answers a different question, and the question decides who owns which file. The runtime layer answers “what is this agent running on.” The harness layer answers “what is it allowed to do.” The coordination layer answers “where is every agent.” The last one answers “what is this project actually,” and that is the part Astragentic must never answer on your behalf.

Four Layers, One Harness An architecture diagram generated by Archify. Claude Code · runtime · RUNTIME Claude Code runtime Codex · cross-vendor arm · RUNTIME Codex cross-vendor arm Grok Build · junior pane (optional) · RUNTIME Grok Build junior pane (optional) Roles · Thomas · Shaper · Builder · QA · Junior · HARNESS Roles Thomas · Shaper · Builder · QA · Junior Skills · 18 packaged skills · HARNESS Skills 18 packaged skills Memory / Ledger · what actually happened · HARNESS Memory / Ledger what actually happened Hooks · 4 lifecycle hooks · HARNESS Hooks 4 lifecycle hooks Tracker · GitHub · Jira · Linear · COORDINATION Tracker GitHub · Jira · Linear herdr · one pane per agent · COORDINATION herdr one pane per agent git worktrees · one checkout per ticket · COORDINATION git worktrees one checkout per ticket Your Project · repo · GLOSSARY.md · ADR · YOUR PROJECT Your Project repo · GLOSSARY.md · ADR Thomas asks frontier Builder claims worktree blocks a dangerous command RUNTIME HARNESS COORDINATION YOUR PROJECT Legend Frontend Backend Database Security External

Scroll sideways for the whole diagram

Open the full diagram ↗opens in a new tab
Role colours in this figure

Click a box to open its page.

Claude Code · Codex

Runtime

One runtime, and the model and effort each role runs at is a row in .agents/orchestrator.md, your own file, never overwritten by an upgrade. Claude Code is the runtime: agents in every role run here. A Builder may hand the typing to a junior pane on another runtime (Grok first), set per project in the same file; review, simplify and the handback stay the Builder’s.

Codex is not a runtime for any role. It is there to be a witness: the cross-vendor arm needs a model from a different vendor to read the diff back, so without it that arm does not exist.

Trade-off. One runtime keeps enforcement even for every role, but a junior pane on another runtime sits outside it. The dispatch mod and hook-git-guard.py read a Claude tool name, so a junior’s boundaries are its own to keep, and the Builder checks the log. Claude itself may also be running with hooks disabled. So the cleanup-ordering rule has to live in the contract first and in the hook second. The hook comes after, not a fence.

Roles: 5 · Skills: 16 · Hooks: 4 · Ledger

Harness

install.sh brings into your repo five roles, sixteen skills, four hooks, and the failure ledger. Roles are split by session lifetime rather than by seniority, because session lifetime decides what a role can still remember.

  • Thomas. Resident.
  • Shaper. Exactly one unbroken session.
  • Builder. One session per ticket.
  • Rin. One session per milestone.
  • QA. One session per walk.

Each role has two files, and where a rule sits matters more than what it says. .claude/agents/<role>.md is the system prompt and carries four lines. .agents/roles/<role>.md is the full contract, and it enters the session through the Read tool, so it lives in context as a tool result.

That difference decides which rules survive a compaction: what sits in the system prompt does, what sits outside it does not, and the agent has no way of knowing it just lost a rule. That is not an attention failure, it is the context budget behaving exactly as built. So those four lines stay fixed at four, and the rest is re-armed by a hook rather than by a reminder.

Tracker · herdr panes · git worktrees

Coordination

Three things keep several agents running at once without a collision: the tracker, herdr’s panes, and git worktrees. What they have in common is that all three sit outside an agent’s context. Anything that exists only in one session’s context disappears when that session compacts, and nobody finds out that it went.

  • The tracker holds work state. Astragentic ships no tracker of its own; it ships adapters for GitHub Issues, Jira and Linear, so you keep the board you already run. State living there means “which ticket is ready” is a query rather than a memory.
  • herdr holds the pane. Each Builder gets a visible pane, and that is not cosmetic: I measured a dispatch that was narrated in text and never actually called, with no liveness signal to tell the two apart. A pane is something you can count.
  • git worktrees hold the write boundary. One checkout per ticket, and the Builder is the sole writer in it. Another measurement showed the opposite: agents sharing one checkout move HEAD under each other, and even a read-only reviewer managed to git switch somebody else’s checkout.

Trade-off. Three external dependencies: a tracker you have to configure, herdr you have to install, and disk for every worktree.

repo · GLOSSARY.md · ADR

Your project

The bottom layer is your repository, and the rule here is that Astragentic knows nothing about it beyond what you declare.

  • Tracker. docs/agents/issue-tracker.md names which tracker.
  • Runtime and model. .agents/orchestrator.md names which runtime and model the agent in each role runs on.
  • Domain vocabulary. GLOSSARY.md holds the shared domain vocabulary.
  • Settled decisions. The ADRs hold the decisions already settled.

No release overwrites any of them.

The most expensive place I learned this boundary was worktree cleanup. The harness knows exactly one thing every worktree can allocate: processes rooted in it. Everything else belongs to the project: a database, a port registration, a container, a broker, a lease on a shared cluster. The harness cannot name any of those without naming one project’s stack.

The concrete risk: a cleanup step hardwired to one project’s stack reads as correct on another one and releases nothing. Orphaned processes and leftover databases then pile up quietly until the machine runs out of room.

So the project now declares its own release step as an executable plug at .astraler/project/cleanup-worktree.sh, and release-worktree-resources.sh calls it after the reap. A project that allocates nothing beyond git still has to write a file saying so, because a silent no-op is indistinguishable from a successful release.

The five core mechanisms

The defect ledger: how the harness learns

Every time something breaks, the incident is written as one line in an append-only file, with a fixed id, never renumbered and never deleted. A line that yields a rule puts that rule into a file agents actually read, so the whole team behaves differently next time. A line that yields nothing yet stays in the table rather than being filtered out.

This is where the harness learns from its own failures: a failure does not fade with memory, it becomes either a rule or an open record.

The cross-vendor arm binds to one SHA

After Claude finishes, a model from a different vendor reads the diff back and leaves a receipt bound to the exact SHA it read. The reason is not variety for its own sake: a model re-reading its own diff re-reads its own assumptions along with it, and a model from another vendor does not carry those assumptions.

The tracker is the state substrate

Work state lives on the project’s own tracker, not in a plan file inside a branch. The difference is checkable: a plan file cannot answer “which ticket is ready right now,” and a query over blocking edges and assignees can.

The claim runs before the worktree

The order is: write the assignee on the tracker, read it back, and only then git worktree add -b. That is how two sessions see each other on the tracker itself instead of discovering the collision after both have written code, and it needs no lock file and no central dispatcher.

Review runs exactly one round

Every ticket passes three layers exactly once: code-review on both axes, Standards and Spec; then the simplify pass; then the cross-vendor read. Three bounded passes keep the rigour without letting the number of rounds multiply.

  • The ledger

    Every rule in the harness came from a measured failure, and the ledger line is still there to read.

    85 / 157measured lessons now enforced by a harness file

  • The cross-vendor arm

    Claude builds, Codex re-reads, and the receipt is bound to the SHA that was read.

    The Cross-Vendor Arm A sequence diagram generated by Archify. commit range <base>..HEAD adversarial-review --wait --base <ref> Focus text carries the owner intent blocking / non-blocking Only the output file is trustworthy, never the exit code arm(ticket): receipt Findings folded by class first; empty commit, parent is the tree the gate read branch, SHA, markers Fire the arm Verdict Receipt + handback Builder · own worktree · Sequence participant Builder own worktree Codex · adversarial-review · Sequence participant Codex adversarial-review Ticket Branch · HEAD · Sequence participant Ticket Branch HEAD Thomas · resident router · Sequence participant Thomas resident router Legend request return async trace default message

    Scroll sideways for the whole diagram

    Open the full diagram ↗opens in a new tab
    Role colours in this figure
  • The tracker is substrate

    State lives on the board. A session can die without taking anything with it.

  • Claim before worktree

    The assignee is written and read back before a branch exists, so two Builders cannot take one ticket.

  • One round of review

    Standards and Spec run exactly once over the whole increment, then stop. There is no second round to hide in.