docs(skills): point skills at llms.txt for field contracts; surgical slim on creative-agent#762
Merged
Merged
Conversation
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.
This was referenced Apr 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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
Follow-ups