Turn production agent architecture into a reusable skill. 16 module references with machine-verified provenance, plus a working stdlib-only agent core you can lift.
agent · llm-agent · agent-architecture · claude-code · agent-skill
· tool-use · reverse-engineering
npx skills add alfredzhang98/agent-creator-skill --skill agent-creatorThen tell your coding agent (Claude Code, Codex, Cursor, …): "Using the agent-creator skill, build me an agent that does X."
Most agent knowledge is trapped inside working codebases: the loop invariants, the guardrail constants, the failure modes someone already paid to discover. This repository extracts that knowledge from two production agents into an installable skill — so your next agent is designed against patterns known to survive production, instead of reinventing a fragile ReAct loop.
Not a prompt collection, and not a framework. A design reference with verifiable sources, and a reference implementation that runs.
It has also been used for real: worldsense was generated from a single sentence with this skill, and after light debugging turns one prompt into a physically-simulated, walkable Isaac Sim scene whose objects are Articraft rigid bodies. The two field reports that run produced drove every release from v0.9.0 to v0.13.0 — including two new invariants and eight bugs found in this repository. More below.
Ask for an agent and you get all sixteen of these designed together, not a loop with tools bolted on:
| # | Capability | What it actually does |
|---|---|---|
| 01 | Turn loop | Two streak ladders that both actually end the run — reword, demand, exit — plus stall detection on the failure signature and an authorless-failure exit that never wastes a retry. A state machine with a closed set of named exits and named continuations, so "why did this stop?" is a value, not an investigation. Recovery ladders for context overflow, truncated output and model failover — each rung fires once, then surfaces. |
| 02 | Tool layer | A declarative tool contract whose safety predicates are functions of the input. Seven-stage dispatch gauntlet. Every failure returns as data the model can correct from — never an exception. Results cap per tool and per message, overflowing to disk instead of truncating. |
| 03 | Verifier | Gating (refuses the exit) or advisory (reports without blocking), chosen deliberately. The advisory tier is attribution-scoped and report-once, so the model is told what its edit broke rather than what the repository already had wrong. |
| 04 | Sandbox | An OS-level boundary contract for anything the model generates — filesystem allow/deny, network allowlists, process caps — with a fail-closed default. Isolation is what buys the agent autonomy. |
| 05 | Provider layer | One seam over N backends, a preflight that resolves the model ID against the account's live catalogue instead of the model's memory (and refuses a family name rather than picking a variant), plus the five-stage context ladder: per-message result budget → snip → microcompact → collapse → summarise, cheapest and most reversible first. |
| 06 | Prompt assembly | Prompt-as-code with memoised sections, an explicit cacheable/volatile boundary, and cache-breaking that must be justified at the call site. |
| 07 | Cost control | Preconditions before the first paid call (free, and they stop a run that could never work), N named cost axes with pre-call reservation for costs that are not money, hard USD cap checked before and after each call, per-model ledgers with cache tokens broken out, and unknown pricing that estimates-and-flags rather than silently disabling the cap. |
| 08 | State | Append-only transcript, atomically written metadata, staging-then-promote for artifacts, and tolerant readback that repairs orphaned tool calls on resume. |
| 09 | Orchestration | Declarative subagents with per-class capability restriction, worktree isolation, and allowlists that replace rather than extend so parent approvals cannot leak into a child. |
| 10 | Action space | The root decision: constrain what the model may produce, because everything downstream — validation, error messages, mechanical QC — is only possible if you did. |
| 11 | Progressive disclosure | Skills and tool schemas that cost one line each until invoked. Index → body → directory. Plus the rule that pays for itself: nothing volatile in a cached prefix. |
| 12 | Hooks | 27 lifecycle events, an exit-code and JSON reply protocol, most-restrictive-wins aggregation, and an unconditional trust gate. Other people extend your agent without forking it. |
| 13 | Permissions | A numbered consent ladder where some decisions are immune to "skip all prompts", and unknown always means ask. This is what says "no" when no compiler can. |
| 14 | Memory | Cross-session memory defined by non-derivability, recalled through a cheap-model pass over a manifest, with staleness carried alongside the content. |
| 15 | Planning | Plan mode as an enforced read-only permission mode, a plan written to disk before approval, and progress tracked with exactly one task in flight. |
| 16 | Skill acquisition | Search the open registry before writing a tool. Two independent gates — who published it, then what its prose tells your model to do — because a library you call and a skill calls you. Plans commands instead of running them, and pins content the ecosystem cannot version. |
The load-bearing shape: the model never reaches the world directly. Every tool call walks the same seven gates, and every failure inside them comes back as data rather than an exception. The loop — not the model — owns the exit.
Diagrams are draw.io files. The
.drawio.svgrenders here and re-opens for editing; the matching.drawioindocs/diagrams/loads into draw.io, the VS Code extension, or next-ai-draw-io for AI-assisted editing. Both are generated from one spec bytools/make_diagrams.py, so they cannot drift.
templates/agentkit/ is a working
agent core, not pseudocode. Stdlib only, no dependencies:
python3 skills/agent-creator/templates/agentkit/selftest.py # worked example
python3 skills/agent-creator/templates/agentkit/tests.py # 391 assertionsAudited. An independent multi-agent review (docs/AUDIT.md) reproduced 33 defects in an earlier version of this code — three security inversions, one flagship feature that could never work, and ten claims in the references that misread their own sources. All are fixed and covered by regression tests. The audit is published rather than quietly folded in, because the most useful finding was methodological: the original self-test passed 14/14 by asserting up to the point where each bug began.
Still true: this code has never run against a live model.
| Module | What it gives you |
|---|---|
contract.py · registry.py · pipeline.py |
Tool contract with fail-closed defaults, cache-stable pool assembly, the seven-stage gauntlet |
provider.py · prompts.py · orchestration.py |
Backend seam and compaction policy; prompt build matrix and cache boundary; run lifecycle, staged exits and declarative subagents |
permissions.py · hooks.py |
Consent ladder with bypass-immune classes; 27-event hook protocol |
loop.py · verifier.py · state.py |
Typed-transition loop, attribution-scoped verifier, transcript + staging + resume repair |
memory.py · planner.py · skills_loader.py · result_store.py |
Recall ladder, plan-mode phase machine, progressive disclosure, overflow-to-disk |
skill_acquisition.py |
Registry queries that reach terms of art, two-gate trust, install plans instead of subprocesses, content pins |
tools/ |
Read · Write · Edit · Patch · Glob · Grep · TodoWrite · AskUserQuestion · Shell · ToolSearch · Skill · Delegate |
Read selftest.py:build_agent
first — it is the shortest honest example of wiring the pieces together.
skills/agent-creator/
├── SKILL.md # entry point: anatomy, build order, invariants
├── references/ # one deep-dive per agent module
│ ├── 00-agent-anatomy.md # the module map & how modules interlock
│ ├── 01-agent-loop.md # turn lifecycle, typed exits, recovery ladders
│ ├── 02-tools.md # declarative tools, errors-as-data, result caps
│ ├── 03-evaluator-verifier.md # gating vs advisory, typed signals
│ ├── 04-sandboxed-execution.md# OS isolation vs process supervision
│ ├── 05-providers.md # multi-LLM seam, the five-stage context ladder
│ ├── 06-prompts.md # prompt-as-code, cache boundary, attachments
│ ├── 07-cost-guardrails.md # pricing tables, dual ledgers, hard caps
│ ├── 08-state-persistence.md # staging→promote, transcripts, tolerant resume
│ ├── 09-orchestration.md # entry points, subagents, fork/rerun
│ ├── 10-action-space-sdk.md # shaping what the model may produce
│ ├── 11-skills-… # progressive disclosure: skills, deferred tools
│ ├── 12-hooks-and-extension.md# lifecycle events, blocking protocol, trust
│ ├── 13-permission-… # the consent ladder; what says "no"
│ ├── 14-memory.md # non-derivability, recall ladder, staleness
│ └── 15-planning.md # plan mode, approval gate, progress tracking
├── templates/
│ ├── agentkit/ # a WORKING agent core (stdlib only, runs)
│ └── *.py # per-pattern skeletons (verifier, cost, sandbox)
└── case-studies/
├── README.md # how to distill the next agent
├── articraft.md # case 01: agentic 3D-asset generator
├── claude-code.md # case 02: general-purpose coding agent
└── claude-code-tool-catalog.md # its 42 tools, annotated: steal these
Every module reference (01-15) follows one contract: why the module exists →
how real agents implement it (with file:line) → design decisions with
tradeoffs → production constants with the reason for each number → a reusable
pattern → pitfalls → checklist. Where the two agents disagree, a comparative
section says who does what, and why.
Building a scene agent — one sentence to an explorable 3D space you can open and walk around, with its objects generated by delegating to Articraft. The library prescribes a build order and never shows it carried through; that document does, on a domain neither case study covers.
It is also the configuration the case studies lack. Physics is a genuine
oracle, so the verifier gates rather than advises and the loop exits on a
check instead of on a person. It carries two lessons that generalise past 3D:
grade the artifact, never one rendering of it — a single hero frame teaches
the agent to make everything behind the camera garbage — and a second cost
axis (GPU-seconds) has to be estimated before the call, which
cost_meter.py does not yet model.
- "Using the agent-creator skill, design an agent that writes and verifies SQL migrations."
- "Add a hard cost cap to my agent — follow reference 07."
- "Review my agent loop against the pitfalls in references 01 and 03."
- "My agent keeps asking permission for everything. Fix it using reference 13."
Tagged by evidence strength, because it differs — mechanical follows from the API or OS contract, converged means both distilled agents independently arrived at it (strong, but n=2), and single-source means one agent does it well and you should question it in your domain:
- Success is verified, never self-reported (converged) — revision-gated fresh verify, or an advisory verifier plus a human. Never zero authorities.
- Tool errors are data, not exceptions (mechanical) — a raised exception
leaves a dangling
tool_use_idand breaks the next call. - One primary issue at a time (single-source: Articraft) — a priority ladder over N failures. Claude Code reports all new findings instead and keeps the list short by attribution-scoping. Pick per domain.
- Budgets are enforced in the loop (mechanical) — USD cap pre-call and post-usage.
- Never execute generated code without an isolated sandbox (mechanical: a security property) — a child process is killable isolation, not a boundary.
- A failure with no author terminates the run (mechanical) — invariant 2 is right about failures the model wrote and wrong about the rest. A missing model, a revoked key, a spent quota: no edit clears them, so every retry is spend against a wall. Classify conservatively — unrecognised means authored.
- A streak is loop control, not a prompt (mechanical) — counting failures to word the advice more strongly still runs to the turn cap. Reword, demand, then exit; and an identical failure twice is a stall, not a streak.
And one corollary from the second case study: anything volatile belongs in the mutable tail, never in a cached prefix. One interpolated list inside a tool description cost a production fleet ~10.2% of its cache-creation tokens.
- Articraft — text → articulated 3D assets; ~20k lines read and verified. Contributes references 00–10 and the compile-feedback verifier pattern.
- Claude Code 2.1.88 —
a general-purpose coding agent with a human in the loop; ~377k lines of
non-UI source read and verified. Contributes references 11–15, the
typed-transition loop, the five-stage context ladder, the whole of
agentkit/, and an annotated catalogue of its 42 tools.
The two were chosen to disagree. Articraft's success is decided by a compiler; Claude Code's by a person. That single difference explains why one invests in a verifier and the other in a permission system — and the comparative sections it produces are the most useful pages in the library.
Known limits, stated plainly: n=2, both from one ecosystem, both producing artifacts. The constants come from one pinned version. The agentkit passes its own tests but has not been run against a live model. Treat the patterns as very good defaults, not laws.
All 946 file:line citations point at pinned source trees — Claude Code
2.1.88 and Articraft.
tools/verify_citations.py checks them and records
a content anchor — a fingerprint of the lines actually cited — in
tools/citations.lock.json:
python3 tools/verify_citations.py # check against the lockfile
python3 tools/verify_citations.py --update # re-anchor after editing docs
python3 tools/verify_citations.py --source <newer-tree> --version 2.2.0Both distilled agents are covered. That matters because an earlier version of this library cited Articraft ~500 times against a tree no reader had, which a review correctly called unauditable — the claims were right, but nobody could tell.
The anchors are the point. A checker that only confirms "this file has enough
lines" passes happily on a citation whose target has been refactored away; this
one reports DRIFTED and shows the divergence. The lockfile is committed and
the source tree is not, so the library can be re-checked against a version it
was never written against.
What this does not prove: that the claim built on a citation was a correct reading in the first place. Anchors catch drift and typos, not misinterpretation.
worldsense — one sentence in, an interactive physically-parameterised scene out, in NVIDIA Isaac Sim. Every object in it is generated by Articraft as a real rigid body: a material, a mass, friction and restitution, and real joints where it has moving parts.
uv run worldsense "a small study with a standing desk by the window"It was generated from a single sentence using this skill. After light debugging the whole workflow ran end to end, and from then on one prompt produces a scene — not a picture of one. The study in its README cost $4.46 and took one verify pass; the desk in it is 32.8 kg of oak and powder-coated steel, the lamp has three posable hinges, and the mug slides if you push it.
What is worth looking at is how much of the anatomy above shows up in its file tree without anyone arranging it to:
| worldsense | this skill |
|---|---|
agent/loop.py, agent/tools.py |
the typed loop and the tool contract — 01, 02 |
sdk/geometry.py |
the action space: a scene vocabulary, raw USD forbidden — 10 |
compiler/sandbox.py, compiler/worker.py |
model-authored code executed behind a boundary — 04 |
| an approval gate showing a plan and a price before anything is generated | consent, and preconditions before spending — 13, 07 |
| a physics gate: Isaac Sim opens the stage, runs gravity, sweeps a standing capsule along the route the layout claimed | a decisive gating verifier — 03 |
nothing reaches scene/ until the last gate passes; until then it sits in stage/ |
staging, then promote — 08 |
budget.py, record.py, prompts/ |
cost, persistence, prompt assembly — 07, 08, 06 |
More than the design transferring, which is the easy part to claim. Running it produced two field reports, and those reports drove every release from v0.9.0 to v0.13.0 — the git history is the evidence:
- invariant 6, because a doubled run-directory path killed a compile worker and the harness politely asked the model to repair plumbing it could not see. Seventeen identical failures, forty turns, at the cap.
- invariant 7, because the streak escalation this skill described only ever changed the wording of the advice. Implemented exactly as written, it ran to the cap anyway.
- preflight, because the run was configured against a model ID that does
not exist, and because
import build123dwas dead on the target machine — which a real run would have discovered only after taking the human's approval. - "test the defaults, not just the fixtures", because sixty-four tests
passed while the shipped default wrote every artifact to
runs/<id>/runs/<id>/. Auditing this repository for the same class then found eight live instances of it here.
A skill that has never been used is a set of assertions. This is the run that turned some of them into findings, and several of them into corrections.
worldsense is an independent implementation that follows this skill; it does
not import templates/agentkit/. So the guidance has been through a real
build and the reference code has not — 391 assertions and a scripted model are
not a live one. That limitation stands until someone drives the templates
themselves against an API.
This repository is documentation plus a working agent harness. The harness
ships no execution engine: there is no exec, eval, compile, subprocess,
or process spawn in any module an agent would import. The one exception is
agentkit/tests.py, which does two things no shipped module does: it re-runs
one function in a fresh interpreter to prove memory recall is deterministic
across processes, and it execs the code blocks in this repository's own
documentation that are marked ````python exec`. Both are test helpers, not part
of the harness, and the second exists because a documented example once shipped
broken — prose does not run, so the suite runs it.
The three places an agent executes something are all Protocols with refusing defaults:
agentkit/skill_acquisition.pynever installs anything. It builds thenpxcommand, audits what landed on disk afterwards, and hands the command back when noSkillIndexis wired in. Searching is network and installing is a subprocess; both belong to the host.agentkit/preflight.pynever calls a provider. It builds the catalogue request, resolves an ID against whatever list it is given, and prints thecurlwhen noModelCatalogueis wired in.templates/sandbox_backend.pydefines the contract for running model-generated code — aSandboxPolicy(network disabled, isolated workspace, no inherited env, non-root, process cap), theSandboxBackendinterface, and a default that refuses to execute anything with an actionable error.templates/agentkit/hooks.pydefines the contract for running user-configured hooks, and its default refuses too. Hooks run commands from settings files that may arrive with a cloned repository; where the trust gate belongs is a deployment decision.
templates/agentkit/tools/ does touch the filesystem — Read, Write, Edit, Glob
and Grep are real implementations, and large tool results are written to disk
rather than truncated. That is the point of shipping them: these are the tools
you were going to write anyway, with the preconditions (read-before-write,
staleness detection, uniqueness-or-error) already in place.
The governing rule, spelled out in reference 04:
A child process is a reliability boundary, not a security sandbox.
Automated scanners flag this skill for REMOTE_CODE_EXECUTION /
PROMPT_INJECTION because its subject matter is building agents that process
untrusted input and run generated artifacts. That is a description of the
topic, not of behavior in this repository. Read the code — it is short,
stdlib-only, and its self-test tells you exactly what it does.
Apache-2.0. Case-study knowledge is distilled from Articraft (Apache-2.0) and from a published npm artifact of Claude Code; see each case study for its source attribution.