Domain-Driven Design Agent Skills
A library of Agent Skills teaching Eric Evans' and Vaughn Vernon's Domain-Driven Design, with a maintained Inspect AI eval suite to check whether a skill actually changes model behavior. The library is discovery-first: one root skill routes into pattern skills and two decision hubs.
Layout
skills/
domain-driven-design/SKILL.md # root: index of every pattern, how to route
domain-driven-design/patterns/<name>/ # 62 pattern skills (one DDD concept each)
SKILL.md
references/implementation.md # worked example + runnable pytest blocks
references/review-checklist.md # C1..Cn checks + verdict format
references/design-facilitation.md # optional, only if facilitation content is long
ddd-selecting-patterns/ # hub: pick a pattern for a codebase + scenario
ddd-collaborative-design/ # hub: facilitate DDD design with a human
docs/
catalog.md # authoritative skill name list, groups, source chapters
authoring-contract.md # binding shape/content rules for every skill
skill-best-practices.md # sourced rationale for the contract
tools/
check_skills.py # static contract checker (frontmatter, headings, code, links)
evals/
schema.py # pydantic schema for eval cases (Case, KeyItem, SkillCases)
cases/<skill>.yaml # 5 cases per skill: S1-S3 visible, H1-H2 holdout
ddd_skills.py # Inspect AI tasks (behavior eval + routing eval)
routing/ # routing-eval queries and distractor skills
tests/
test_static.py # runs tools/check_skills.py over every skill
test_cases.py # schema/coverage invariants over evals/cases/
hooks/ # SessionStart pointer: bootstrap.md text, Claude Code hook script
.pi/extensions/ # omp/pi SessionStart equivalent (reads hooks/bootstrap.md)
plugin.json # Agent Plugins 1.0.0 manifest
.claude-plugin/ # Claude Code manifest + local dev marketplace
package.json # omp/pi package manifest (skills + extension)
skills/ and docs/ are the shipped product. evals/ and tools/ are the maintenance harness.
.work/ is gitignored scratch (source book text, run logs, grading intermediates) — book text is
never in the repo; it only ever lives locally under .work/books/.
Source material
The skills and eval cases teach patterns from Eric Evans, Domain-Driven Design (2003), and Vaughn Vernon, Implementing Domain-Driven Design (2013). They are written in our own words and cite chapter and section; pattern and section titles are used by name. Neither book is included, and buying them is the best way to learn this material in depth.
Guardrail for contributors with a local copy of the book text in .work/books/:
uv run python tools/check_book_overlap.py (also run by tests/test_book_overlap.py) fails on any
run of 10+ consecutive words shared with either book, other than section titles.
Installing
The repo is an Agent Plugins package that also carries Claude Code
and omp manifests. All three discover exactly three skills (domain-driven-design,
ddd-selecting-patterns, ddd-collaborative-design); the 62 patterns are nested under the root
and reached through its index. A SessionStart hook adds the short pointer in
hooks/bootstrap.md (about 480 characters) to each session.
# Claude Code
claude plugin marketplace add sglyon/ddd-agents # or a local checkout path
claude plugin install ddd-skills@ddd-skills-dev
claude --plugin-dir /path/to/ddd-agents # one session, no install
# omp (oh-my-pi)
omp plugin marketplace add sglyon/ddd-agents
omp plugin install ddd-skills@ddd-skills-dev
omp plugin link /path/to/ddd-agents # local dev; `omp plugin uninstall ddd-skills`
# any agentskills.io harness without plugin support
cp -r skills/* ~/.agents/skills/
Validate packaging with claude plugin validate . --strict and uv run pytest tests/test_plugin.py
(manifest names, versions, and descriptions must agree; bump all of them together).
How agents drive it
An agent never loads all 62 pattern skills — it loads the root skill
(skills/domain-driven-design/SKILL.md), which indexes every pattern and routes by task:
- Implementing, verifying, or picking a single named pattern → load that pattern's
SKILL.mddirectly (root index linkspatterns/<name>/SKILL.md). - Choosing among several candidate patterns for a scenario → load
ddd-selecting-patterns. - Facilitating a live design conversation with a human from scratch → load
ddd-collaborative-design.
Each pattern skill then conditionally loads its own references/*.md (implementation detail,
review checklist, design facilitation) only when that mode is needed — see the "How to use this
skill" table in every SKILL.md.
Maintaining
Adding or editing a skill
- Read
docs/authoring-contract.mdin full — it is binding: exact frontmatter shape, section order and headings, line/word budgets, P-rule/C-check numbering, the verdict block format, and content rules (source fidelity, paraphrase-only, no URLs, no.work/references). - Read the catalog row in
docs/catalog.mdfor the skill's name, folded sub-concepts, and source chapters, anddocs/skill-best-practices.mdfor the sourced rationale behind the contract. - Write/edit the skill under
skills/domain-driven-design/patterns/<name>/(or the hub directory for the two hubs). - Run the static checker:
Drop
DDD_SKIP_SKILLS_REF=1 uv run python tools/check_skills.py <name>DDD_SKIP_SKILLS_REF=1to also run the externalskills-ref validatetool (needs network/uv tool runaccess). It writes a JSON report to.work/reports/check/<name>.json. - If the skill's name or index entry changed, also update
docs/catalog.mdand the rootSKILL.mdindex.
Adding or editing eval cases
Each skill has evals/cases/<skill>.yaml, validated by evals/schema.py
(SkillCases → Case → KeyItem). Every skill has exactly 5 cases:
| id | mode | split |
|---|---|---|
| S1 | implement | visible |
| S2 | verify | visible |
| S3 | select | visible |
| H1 | verify | holdout |
| H2 | design | holdout |
A Case has a prompt, a list of items (KeyItems: id, text, weight, required,
decoy), optional disqualifiers, and sources. Case.max_score is the sum of weights of
required items — never derived from grader output. decoy: true items are distractors a good
answer should correctly avoid flagging.
Holdout rule: authors and fixers of a skill must never read that skill's H1/H2 cases (see
docs/authoring-contract.md §8, Writer process). Holdout cases exist to catch skills that were
tuned to pass their own visible eval prompts rather than teaching the pattern in general.
Running static checks
DDD_SKIP_SKILLS_REF=1 uv run pytest -q
Runs tests/test_static.py (contract conformance via tools/check_skills.py, parametrized over
every catalog skill) and tests/test_cases.py (eval-case schema and coverage invariants).
uv run ruff check tools tests
Running evals
Behavior eval — does the skill change what the model does, for a given skill/case:
# baseline: no skills loaded
uv run inspect eval evals/ddd_skills.py@behavior -T skills=false -T split=visible
# with skills
uv run inspect eval evals/ddd_skills.py@behavior -T skills=true -T split=visible \
--model-role grader=<grader-model> --epochs 3
Swap -T split=visible for -T split=holdout to score against the cases authors never saw.
Routing eval — does the agent pick the right skill from the catalog without reading everything:
uv run inspect eval evals/ddd_skills.py@routing -T view=rooted # via the root skill's index
uv run inspect eval evals/ddd_skills.py@routing -T view=flat # all skills exposed flat
Inspect the transcripts/scores:
uv run inspect view
Two credential paths
| Path | Harness values | Auth | Isolation | Use for |
|---|---|---|---|---|
| API (default) | claude_code, codex_cli | provider API keys | Docker sandbox via inspect_swe | full benchmark runs on new models |
| Subscription | claude_local, codex_local, omp_local | CLI logins in an isolated eval HOME | host process, read-only tools, throwaway workdir | per-skill iteration |
One-time setup for the subscription path: tools/eval_home.sh creates
~/.local/share/ddd-agents/eval-home (override with DDD_EVAL_HOME), logs each installed CLI in
under it, and links the plugin for omp. Nothing from your own HOME (skills, plugins, CLAUDE.md)
is visible to these runs. The judge can use a subscription too through the cli model provider:
uv run inspect eval evals/ddd_skills.py@behavior -T harness=claude_local -T skill=ddd-aggregate \
--model-role grader=cli/codex --epochs 3 # agent on Claude, judge on Codex
uv run inspect eval evals/ddd_skills.py@behavior -T harness=claude_local -T skills=false ...
Local agents ignore --model; pick the CLI's model with -T agent_model=<name>.
Subscription runs consume plan usage limits; full runs (~4k agent runs + ~2k judgings) belong on
the API path.
New-model / new-harness release procedure
When a new model or harness ships:
- Run the baseline (
-T skills=false) and the with-skills (-T skills=true) behavior evals, both-T split=visibleand-T split=holdout,--epochs 3, against the new model/role. - Compare the new with-skills log against the previous with-skills log for the same split
(
uv run inspect viewside-by-side, or diff the exported scores). - Treat per-case score moves of ≤ 2 points as noise (epoch variance). Investigate and file an issue against the specific skill for any larger regression; a larger improvement vs. baseline is the expected signal that the skill still earns its place.
- Book text (
.work/books/) is never committed — it is local-only scratch needed only when authoring/editing skill content, not for running the eval suite.