A lot of multi-agent setups still look like this:
one parent chat |- researcher agent |- architect agent |- implementer agent `- reviewer agent
That shape breaks when context bloats and subagents inherit stale assumptions.
Also when crashed worker disappears into the transcript and provider quota issue kills the whole run.
Follow-up questions replay tokens against a chat history that should have been state.
Puppetmaster takes a different position:
Agents should share durable state.
And that is the whole idea.
It is a provider-neutral control plane for agent swarms.
It runs agent workers as independent processes, coordinates them with leases, stores their results as typed SQLite artifacts, routes each task to the cheapest sufficient model, and stitches the final answer from structured outputs instead of raw chat logs.
You do not build a new agent from primitives but put a supervisor in front of the agent tools you already use: Cursor, Claude Code, OpenAI/Codex, Hermes, or a direct provider API through the built-in agentic worker.
Let’s have a look at why durable state beats shared transcript.

The problem Puppetmaster is solving
Agentic software engineering creates an infrastructure problem.
The workflow includes:
- long repo investigations
- conflicting hypotheses
- multiple tool-capable workers
- provider fallback
- patch attribution
- live progress inspection
- approval gates
- reusable memory
- cost controls
- repeatable routing decisions
Native IDE subagents help with parallel exploration, and tools like Claude Code now support custom subagents, hooks, MCP, skills, and parallel work.
Subagents have independent contexts that preserve the main conversation and can be routed to cheaper models for specific task types.
That is useful but Puppetmaster goes one layer lower and one layer wider.
Instead of asking one host product to manage every child agent inside its own session, Puppetmaster turns the host agent into an operator and moves the real coordination into a local runtime.
The control flow becomes:
Cursor / Claude Code / OpenAI / Codex / Hermes / agentic / shell | v Puppetmaster supervisor -> task-aware model router | v independent worker processes -> SQLite artifacts, events, memory | v live artifact board -> stitched summary -> zero-token follow-up reads
That is closer to Gunicorn, Redis, or a local workflow engine than a group chat and the important word is runtime.

Puppetmaster treats a swarm run as a job and a job contains tasks.
Tasks are claimed by workers through leases, workers emit artifacts., and artifacts include payload, evidence, confidence, and hash integrity.
Then the stitcher reads artifacts and writes the final summary.
The core objects are:
Job: one swarm run and user goal Task: a role-specific unit of work, optionally dependent on other tasks AgentRun: one attempt by one worker process Artifact: structured worker output with evidence, confidence, payload, and sha256 MemoryRecord: promoted facts that future workers can retrieve
This sounds much more useful in practice.
Editor’s note: To celebrate reaching 10,000 community members on Medium, who relentlessly design, ship, and iterate on agents every day, we’re also making the full repository available for free, which is part of our Agent Foundry program.
Why durable state beats shared transcript
The common parent chat plus subagents model creates hidden coupling.
In a chat swarm, every follow-up re-sends the whole transcript, so turn n processes roughly n turns’ worth of context.
Per turn that’s linear but cumulatively it’s quadratic, O(n²).

Your tenth follow-up isn’t a little more expensive than your first, the running total is an order of magnitude higher, and it’s invisible because it hides inside the context window.
Durable state turns a follow-up into a bounded read instead of a replay, which is what the article means by zero-token follow-up reads.

The actual source model makes this explicit.
In puppetmaster/models.py, artifacts are typed records:
class ArtifactType(StringEnum):
FINDING = "finding"
DECISION = "decision"
PATCH = "patch"
VERIFICATION = "verification"
RISK = "risk"
MEMORY_SUMMARY = "memory_summary"
ROUTING = "routing"
GATE = "gate"@dataclass(frozen=True)
class Artifact:
job_id: str
task_id: str
type: ArtifactType
created_by: str
payload: dict[str, Any]
confidence: float
evidence: list[str]
id: str = field(default_factory=lambda: new_id("artifact"))
created_at: str = field(default_factory=now_iso)
sha256: Optional[str] = None
def validate(self) -> None:
if not 0 <= self.confidence <= 1:
raise ValueError("artifact confidence must be between 0 and 1")
if not self.payload:
raise ValueError("artifact payload must not be empty")
if not self.evidence:
raise ValueError(f"{self.type} artifacts require evidence")A worker result must have evidence and a patch is not just “I changed the code.”
Also routing decision is not hidden inside logs and verification result is first-class state.
So basically do not make the model transcript your system of record, use the transcript for reasoning and use durable state for coordination.
How Puppetmaster fits with MCP, LangGraph, Claude Code and Codex
The agent ecosystem is crowded, so the positioning matters, and Puppetmaster is not trying to replace any of these existing layers.
It is a supervisor over them.
- If you are building a custom product agent, use LangGraph, CrewAI, OpenAI Agents SDK, or your own framework.
- If you are coordinating agentic engineering work across the CLIs your team already uses, Puppetmaster is the missing control plane.
Full-edit workflows with Claude Code
For real edits, Puppetmaster can drive Claude Code in non-interactive mode.
The full-edit config is explicit about the risk surface:
{
"lease_seconds": 10,
"workers": [
{
"role": "claude-implement",
"instruction": "Use Claude Code to implement the requested change and leave a reviewable diff.",
"adapter": "claude-code",
"payload": {
"prompt": "Implement the requested change, run focused verification, and keep the result easy to review.",
"cwd": ".",
"permission_mode": "acceptEdits",
"allowed_tools": ["Read", "Edit", "MultiEdit", "Write", "Bash"],
"output_format": "json",
"timeout_seconds": 900,
"allow_dirty": false
}
}
]
}The allow_dirty: false default is important.

If a write-capable agent starts from a dirty working tree, you lose attribution.
Was that diff produced by the agent, by you, or by yesterday’s half-finished refactor?
Puppetmaster refuses dirty trees by default so patch artifacts stay meaningful.
For serious use, run implementation in a dedicated worktree:
git worktree add /tmp/puppetmaster-work -b puppetmaster-work
python -m puppetmaster claude "Implement the approved fix" \
--cwd /tmp/puppetmaster-work \
--permission-mode acceptEditsThen inspect before merging:
python -m puppetmaster diff
python -m puppetmaster show $(python -m puppetmaster last)
python -m puppetmaster approve <job_id>
# or
python -m puppetmaster reject <job_id> --reason "Needs narrower scope"Do not skip this gate.
Autonomous coding agents are useful because they can act and they are risky for the same reason.
Model routing: the part managers will care about
Puppetmaster ships a task-aware model router.
The router uses a user-owned registry in ~/.puppetmaster/models.json.
You define model IDs, adapter names, pricing, billing posture, and capability scores.
The routing logic has three pillars:
- a user-owned model registry
- a transparent classifier that estimates required capability from role, instruction, and payload
- policies like
balanced,cheap,quality, andescalating
Every routing decision is stored as a ROUTING artifact.
That means you can inspect the selected model, estimated cost, rejected alternatives, and the reason each alternative was rejected.
Dry-run a decision before spending anything:
python -m puppetmaster models init
python -m puppetmaster models list
python -m puppetmaster route "Security audit across every endpoint" --role auditThe docs show the shape of the output:
picked: claude-code/opus-4-8 (adapter=claude-code, model_name=claude-opus-4-8) policy: balanced capability needed: 99 chosen capability: 99 estimated tokens: in=510 out=5000 estimated cost: $0.127550 why: policy=balanced: cheapest model whose capability_score (99) >= needed (99) rejected:
- cursor/composer-2-5: capability_score 55 < needed 99
- cursor/gpt-5-5: capability_score 78 < needed 99
- openai/gpt-5-4-mini: capability_score 70 < needed 99
For an easy task:
python -m puppetmaster route "Format these files" --role verify-runtimeExpected shape:
picked: cursor/composer-2-5 (adapter=cursor, model_name=composer-2.5) capability needed: 20 chosen capability: 55 estimated cost: $0.000000
This is where the economics get interesting.
Most teams do not need the frontier model for every worker.
Exploration, formatting, basic verification, and small summaries can route to cheaper or plan-billed models.
Security audits, cross-file refactors, and ambiguous architecture decisions can route higher.

The model decision becomes auditable infrastructure.
The live artifact board is the real UX
Puppetmaster workers write artifacts and events as they run.
Cursor can inspect status, logs, live artifacts, partial summaries, and the final stitched summary.
The local dashboard is also zero-dependency:
puppetmaster dashboard [<job_id>]This gives you a live web board over the local state store.
It is a pragmatic local view: task graph, artifacts, costs, fallback events, and alerts.
Where I would be cautious
Puppetmaster is still daily-driver beta software.
The runtime contract is real, tests are automated, SQLite is the default backend, jobs fail closed, and validated full-edit adapters exist.
It is not yet a hosted multi-user production service, and take that literally.
Do not point it at sensitive repos without understanding provider data handling and do not assume the router is always right.