Skip to content

docs(skills): point skills at llms.txt for field contracts; surgical slim on creative-agent#762

Merged
bokelley merged 3 commits into
mainfrom
slim-skills-pointer-to-llms
Apr 22, 2026
Merged

docs(skills): point skills at llms.txt for field contracts; surgical slim on creative-agent#762
bokelley merged 3 commits into
mainfrom
slim-skills-pointer-to-llms

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

With `docs/llms.txt` now carrying per-tool response contracts (#761) and strict dev-default validation rejecting drift with field paths (#727/#757), every `build-*-agent/SKILL.md` can stop re-stating the wire schema inline.

All 8 skills get a canonical-contracts callout at the top of their "Tools and Required Response Shapes" section:

Canonical field contracts: every tool's full request + response field list lives at `docs/llms.txt` under a `#<tool_name>` anchor (e.g. `#create_media_buy`). Strict response validation (dev default) rejects drift with the exact field path. This skill covers handler patterns, gotchas, and domain-specific examples — not field-by-field contracts.

Anchor examples are customized per skill (brand-rights → `#acquire_rights`, governance → `#check_governance`, retail-media → `#sync_catalogs`, etc.).

build-creative-agent gets a surgical slim: the verbose response-shape code blocks (duplicated verbatim from the schemas that llms.txt now indexes) are collapsed into a compact handler-binding table. Gotchas and anti-patterns stay; field enumerations move to llms.txt. Net -94 lines (760 → 666), same actionable signal.

Other 7 skills: pointer line only — deeper surgical slims deferred until the pattern is validated. Skill file sizes stay ~flat (prettier reflow absorbs the pointer line).

Why

Matrix runs kept surfacing the same drift: agents hallucinated field names (`creative_deliveries` → `creatives`), dropped required fields (`format_id`, `currency`), or conflated nearby tool shapes (`sync_creatives` fields leaking into `build_creative` responses). Every skill redundantly documented the shape, and when upstream added a required field, nothing forced the skill to update. The skill → schema → llms.txt drift loop was three-way.

With this PR, llms.txt is the canonical field contract (auto-regenerated from schemas on every `sync-schemas`), skills are narrative + gotchas, and strict validation catches any remaining drift at the call site.

Test plan

  • `npm run typecheck` clean
  • All 8 skills have the pointer callout with a per-skill anchor example
  • Matrix v12 (post-merge) measures whether the drift-failure buckets shrink

Follow-ups

  • Per-skill surgical slims for the remaining 7 skills, if the creative-agent pattern lands cleanly.
  • `outputSchema` on MCP tool definitions so any MCP client can introspect response contracts directly (no llms.txt fetch needed).

Each tool section now emits a "Response (success branch)" block with the
required + optional fields, mirroring the existing request block. Pulled
straight from the bundled JSON schemas; zero new source of truth.

Closes the drift path matrix runs kept surfacing — agents dropped
required response fields (missing format_id on creative_manifest, plural
hallucinations like creative_deliveries for creatives, missing top-level
currency) because the skill prose documented intent but the full
per-field contract lived in the generated schemas and was never indexed
in the llms.txt file Claude actually reads.

Anchored sections let skills point at docs/llms.txt#<tool> instead of
embedding the contract inline — keeps skills lean.
Every build-*-agent skill's "Tools and Required Response Shapes"
section now opens with a canonical-contracts pointer directing Claude
at the anchored llms.txt section for per-tool request + response
fields — one source of truth, refreshed on every schema sync.

build-creative-agent gets a surgical slim: the verbose response-shape
blocks (which duplicate llms.txt verbatim now that #761 landed) are
collapsed into a compact handler-binding table. Gotchas and anti-
patterns stay; field enumerations move to llms.txt. Net -94 lines,
same signal. The other 7 skills get the pointer line only — follow-up
passes can do per-skill surgical slims once the pattern is validated.

With strict response validation default in dev (#727/#757), drift
between a skill example and the schema now fails immediately at the
call site with the exact field path. The skill's job is to document
patterns/gotchas; the schema's job is to enforce shape. This
separation was muddied when every skill tried to re-state the shape
inline.
Experts flagged the passive "contracts live at X" wording — Claude
doesn't follow pointers without an imperative trigger. Rewrote to lead
with "Before writing any handler's return statement, fetch
docs/llms.txt and grep for #### \`<tool_name>\`" and reframed the
validation safety-net from threat to permission. Applied to all 8
skills.

Added a per-row Contract column to the creative-agent handler-binding
table with direct anchor links — more reliably followed than a general
pointer three lines up.

Regenerated schemas/types (upstream context-object shift) and widened
si-session-manager.ts generateInitialResponse signature from string to
unknown so the overrides accept the new ContextObject shape. Unblocks
CI's Validate generated files check.
@bokelley bokelley merged commit 275fa70 into main Apr 22, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant