How to Build a Perfect Agent Skill: A Step-by-Step SEO Audit Tutorial
I used to think agent skills were just glorified prompt templates—until I watched one fail silently in production because its description was too vague to trigger correctly. That experience sent me down a rabbit hole of the Agent Skills specification, and what I found changed how I approach skill design entirely. A well-crafted skill isn't documentation; it's a behavioral contract with explicit inputs, outputs, and trigger boundaries. In this tutorial, I'll walk you through building a real, production-grade SEO audit skill from scratch, using the exact same specification that powers over 47,000 skills across 6,300 repositories. By the end, you'll understand every structural decision—from YAML frontmatter to progressive disclosure—and have a complete, testable skill you can deploy today.

Why Most Agent Skills Fail Before They Start
When I look at the SkillsBench dataset, the numbers are staggering: over 47,000 unique skills scattered across 6,300+ repositories. Yet when I dig into how teams actually validate these skills before deployment, I see the same pattern everywhere. Most organizations skip structured testing entirely. They run a few manual prompts, decide the output "feels right," and ship it to production. I view this as the equivalent of deploying code without unit tests—except here, the bugs don't throw exceptions; they silently misroute user requests or fail to trigger at the exact moment they're needed. What makes this worse is that the majority of these skills appear to be AI-generated artifacts that were never put through a regression suite.
The Silent Failure Mode of Behavioral Triggers
Skills aren't passive libraries. They function as behavioral triggers that intercept intent and route it to executable logic. When a skill misfires, it doesn't necessarily log a noisy error. Instead, it either sits dormant while the agent hallucinates a workaround, or it hijacks a conversation it was never meant to handle. Both failure modes are expensive. In my analysis of production agent systems, silent misrouting consistently burns more tokens and erodes user trust than explicit crashes because the system appears to be working while actually drifting off course. You won't catch this with a five-minute vibe-check in a playground environment. The failure only surfaces under real routing pressure with ambiguous user prompts.
The root cause is almost always the same: the description field is treated as an afterthought. Teams write vague, marketing-style summaries like "This skill helps with customer support," which tells the routing layer almost nothing about activation boundaries.
Why the Description Field Controls Everything
I want to emphasize how mechanically important this field is. The description isn't just documentation for humans; it's L1 metadata—roughly ~100 tokens per skill—that gets injected directly into the system prompt at startup. The agent's router relies on this metadata to perform discovery and intent matching. If the description doesn't precisely define when the skill should activate and, just as importantly, when it should not, the matching algorithm is essentially guessing.
This explains why vague descriptions create a double-edged reliability problem:
- False negatives: The skill fails to trigger when the user explicitly needs its capability.
- False positives: The skill activates inappropriately, pulling the conversation into the wrong execution path.
Both outcomes stem from the same engineering oversight: imprecise scope definition in the most critical 100 tokens of the skill file. I see teams obsess over the implementation logic while treating these 100 tokens as a creative writing exercise, which is completely backwards.
What Systematic Evaluation Actually Looks Like
The Interactions API skill case study gives us a concrete benchmark for what happens when we stop trusting vibe-checks. Before structured evaluation, the skill was only passing 66.7% of test cases. After applying systematic evaluation and targeted fixes, the pass rate jumped to 100%.
When I examine what changed, the improvements weren't magic. The team eliminated token waste by tightening the description so the router stopped spinning up the skill for irrelevant queries. They prevented deprecated API usage by clarifying the exact SDK version and call patterns in the skill's scope definition. They also ensured consistent SDK adoption because the description now explicitly signaled which toolkit the agent should reach for.
That jump from two-thirds to perfect passing isn't a fluke. It shows that skill design is an engineering discipline, not a creative writing exercise. The description field is your interface contract. If you wouldn't ship an API with an undefined schema, you shouldn't ship a skill with a vague description.

The Anatomy of a Skill Directory
When I examine the Anthropic Agent Skills Spec v1.0, the directory contract is stricter than it first appears. At minimum, a skill is just a folder containing a SKILL.md file. But a complete implementation—like the seo-audit/ example—typically expands into four distinct zones: SKILL.md for the core instruction set, scripts/ for executable code the agent can invoke, references/ for documentation that loads on demand, and assets/ for templates and data files. Only the markdown file is mandatory; the rest are optional, yet the parser expects this exact layout when they are present.
The SKILL.md Parsing Pipeline
The SKILL.md file operates under a rigid parsing contract. It must begin with YAML frontmatter delimited by triple dashes, followed immediately by Markdown body content. The extraction logic relies on the regex /^---\n([\s\S]*?)\n---\n([\s\S]*)$/ to separate metadata from instructions. If that pattern fails to match—perhaps because of a missing newline or an extra space—the consequence is not an error message. The skill is silently ignored.
After regex extraction, the YAML block is parsed and validated against SkillFrontmatterSchema using Zod. A schema violation produces the same silent death: no warning, no fallback, the skill simply does not exist to the agent. However, the validator is permissive in one respect: unknown frontmatter fields are ignored rather than rejected, so extra metadata will not break loading.
One constraint I watch carefully is that the parent directory name must match the name field declared in the frontmatter. A mismatch between the folder seo-audit/ and a frontmatter name value means the discovery logic will never bind them together.
Skill Discovery and Resolution Paths
Agents locate skills through filesystem scanning rather than a centralized index. The search looks for subdirectories containing a SKILL.md file, probing up to two levels deep from configured root paths. This search spans multiple roots in parallel. Project-local roots are discovered by walking upward from the current working directory toward the git worktree root, checking .opencode/skills/, .claude/skills/, and .agents/skills/ along the way. Global roots include ~/.config/opencode/skills/ and ~/.config/crush/skills/.
This multi-root design lets me keep project-specific audit logic inside a repository while maintaining a personal library of reusable skills in my home directory. But the two-level depth limit is unforgiving—nest a skill too deeply under a category folder, and the scanner never sees it.
Why Silent Failures Define the Architecture
What stands out to me is the system's deliberate preference for invisibility over noisy errors. A regex mismatch, a Zod validation failure, or a misnamed directory all produce the same outcome: the skill disappears without a trace. When I assemble these directories, I treat the frontmatter as a binary API boundary. The triple-dash delimiters must be exact, the YAML must pass SkillFrontmatterSchema, the name key must sync with the folder name, and the file must live at precisely the right depth. The optional folders—scripts/, references/, assets/—add operational power, but every feature depends on SKILL.md surviving that initial parser gate.

Step 1: Crafting the Frontmatter — Name and Description
The YAML frontmatter functions as both the skill’s identity card and its trigger mechanism, so I approach it as a strict behavioral contract rather than decorative metadata. According to the Anthropic Agent Skills Spec v1.0, six recognized fields govern this contract, yet only name and description are mandatory. Everything else layers guardrails around runtime behavior and discoverability.
Examining the field table, I notice the name field carries the tightest constraints. It must satisfy the regex ^[\p{Ll}\p{N}-]+$u, which locks it to lowercase alphanumeric characters and hyphens, capped at 64 characters. The description field allows up to 1,024 characters, but that space is deceptive—every byte competes for the model’s attention during invocation routing. Optional fields like license (expecting a valid SPDX identifier), compatibility (declaring runtime targets such as opencode or claude), metadata (a Record<string, string> key-value map), and allowed-tools (a string array of permitted tool names) give me fine-grained control without polluting the core trigger logic.
When I translate these constraints into a production-ready SEO audit skill, the YAML becomes a study in intentional restriction:
---
name: seo-audit
description: >
Performs a comprehensive SEO audit on a given URL or page content. Checks E-E-A-T signals (author bylines, reviewer blocks, review dates), structured data (JSON-LD schema for Article, FAQPage, BreadcrumbList), technical SEO (meta tags, canonical URLs, heading hierarchy), and content freshness. Use this skill when asked to evaluate, review, or improve a page's search engine optimization. Do NOT use for keyword research or competitive analysis.
metadata:
category: seo
version: "1.0.0"
---
I see several deliberate architectural choices here. The name seo-audit uses kebab-case, stays well under the 64-character ceiling, and mirrors the directory name—this alignment prevents path-resolution errors when the runtime discovers and loads the skill. The description does not merely list capabilities; it explicitly defines boundaries by stating what the skill does not do. By excluding keyword research and competitive analysis, the frontmatter reduces false-positive triggers. Models follow explicit directives more reliably than they parse passive implications, so the phrase "Do NOT use" functions as a negative trigger guard rather than a polite suggestion.
The metadata block operates as a flexible categorization layer. Because it accepts arbitrary key-value string pairs, I can inject versioning and taxonomy data without touching the formal spec fields. This keeps the skill discoverable in filtered toolchains while leaving the description field free for behavioral instruction rather than administrative bloat.
Field Constraints and Type Safety
name: Regex^[\p{Ll}\p{N}-]+$u enforces lowercase letters, hyphens, and digits only. No underscores, no camelCase, no spaces.description: 1–1,024 characters. I treat this as a behavioral API contract, not a marketing blurb.allowed-tools: String array that acts as a runtime capability whitelist. If omitted, the skill may inherit broader tool access than intended.
Directives vs. Passive Language
When I write the description, I avoid passive phrasing like "This skill is designed to…" and instead use imperative commands: "Performs…", "Checks…", "Use this skill when…", "Do NOT use…". The Anthropic spec rewards directness because the invocation model scores intent against active verb patterns. Every character in that 1,024-character budget should either expand capability or tighten guardrails—never both, and never neither.
If I inflate the description with passive filler, I waste tokens on ambiguity and increase the risk of the model selecting the wrong tool for a user query. That is why I front-load the action verbs and close with explicit exclusions. The result is a frontmatter block that triggers precisely when the user needs an SEO audit, and stays silent when they ask for keyword volume or competitor gap analysis.

Step 2: Writing Imperative Instructions for the SEO Audit
When I architect agent skills, I treat the L2 instruction layer as a deterministic control plane rather than a suggestion box. The Markdown body loaded on skill activation operates under hard constraints: <5,000 tokens and <500 lines in SKILL.md. Every byte in that budget must compel a specific action. I have observed that large language models follow explicit directives at significantly higher rates than they infer implications from passive guidance. If I write "the canonical link should be verified," the model treats it as background context. If I write "Verify the canonical link," it becomes a binding step in the execution chain.
The Imperative Verb Pattern
The SEO audit skill demonstrates this principle across five sequential phases. I structured each step as a command chain using high-friction verbs: Check, Verify, Flag, Confirm, Extract, and Produce. These are not stylistic choices; they are attention anchors.
- E-E-A-T Signal Verification demands that the model hunt for named author bylines, credential lists, and reviewer blocks. I used "Verify" because it forces a binary outcome: either the reviewer block exists with
[Name, Credentials]and[Date], or the model must flag a critical gap. - Structured Data Audit uses "Extract" and "Validate" to mandate JSON-LD parsing. I specifically instructed the model to flag
@type: OrganizationwherePersonis expected, closing a common schema loophole I see in YMYL content. - Technical SEO Checklist relies on "Verify" and "Check" to enforce character limits—<60 characters for titles, <155 characters for meta descriptions—and to confirm heading hierarchy with exactly one
<h1>.
This pattern eliminates ambiguity. The model does not debate whether a freshness assessment is optional; it executes the comparison between datePublished and dateModified because the instruction states: "Compare."
Keeping the L2 Layer Lean
I enforce a strict separation between commands and reference material. Detailed schema documentation, regex patterns, or extended examples live in the references/ directory, not in SKILL.md. This keeps the imperative surface clean. When the model loads the skill, it receives a compressed directive map, not a manual it must summarize.
Output Directives as Closure
The final phase of the audit skill reveals why imperative language matters for structured generation. I command the model to "Produce a structured audit report" with three explicit buckets: Critical Issues, Warnings, and Recommendations. Each issue must contain four fields: the element, expected state, actual state, and fix suggestion. By dictating the severity levels—Critical for indexing or E-E-A-T blockers, Warning for suboptimal states, Info for improvements—I remove guesswork from the model's formatting logic.
The result is predictable. When I feed a page into this skill, it does not summarize SEO best practices. It executes a deterministic audit sequence and returns a standardized defect report. That reliability is the difference between a skill that occasionally works and one that ships in production.

Step 3: Building the Reference Layer with Progressive Disclosure
I see the progressive disclosure pattern as the most practical way to prevent context window bloat. When I look at how agent skills consume tokens, the difference between loading everything upfront and loading on demand is massive. The four-stage model handles this cleanly:
- Advertise (~100 tokens per skill): At startup, the agent only ingests the
nameanddescriptionfor every skill. This enables discovery without drowning the context in unused details. - Load (<5,000 tokens recommended): Once a skill matches the active task, the full SKILL.md body loads. I keep this stage under five thousand tokens to maintain responsiveness.
- Read resources (as needed): Files inside
references/,assets/, orscripts/enter the context only when the instructions explicitly point to them. - Run scripts (as needed): Scripts execute only when called, staying silent otherwise.
This staged approach means the agent never pays for knowledge it isn't actively using.
Structuring the SEO Audit Reference Layer
For the SEO audit skill, I moved the heavy reference material out of SKILL.md entirely. I noticed that stuffing signal-weight tables and JSON-LD examples directly into the main file quickly pushes it past the readability threshold. Instead, I split the domain knowledge into dedicated files under the references/ directory. This keeps the primary skill manifest lean while ensuring the agent can still pull surgical detail the moment it needs it.
The E-E-A-T Checklist as a Dedicated Reference
The file references/ee-at-checklist.md carries the full signal-weight logic that I do not want cluttering the main instruction set. It breaks down trust signals into clear tiers:
- Visible date + matching schema: High weight, rated as Strong if consistent by Google's trust models.
- Schema only (no visible date): Medium weight, Moderate trust level.
- Visible date contradicted by content: Low weight, often ignored entirely.
- Frequent date changes without content changes: Negative weight, carrying risk of potential trust erosion.
Beyond the table, the checklist enforces a rigid 3-signal minimum:
- Author byline with credentials
- Reviewer block for high-stakes content
- Review date visible on the page
I also included explicit anti-patterns because I know agents can drift into generic outputs without guardrails. I flagged "By Content Team" bylines, missing reviewer blocks on YMYL pages, and stale review dates older than 12 months. The warnings are strict: do not fabricate authors, because AI engines cross-check against LinkedIn and publication history, and fake authors get flagged. Reusing the same "Content Team" byline across 200 pages is another trap I called out, along with the mistake of setting a review date once and never touching it again.
JSON-LD Templates in Isolation
The second reference file, references/schema-templates.md, holds the ready-to-use structured data templates. I keep the Article schema with the full author + reviewer pattern here:
{
"@context": "https://schema.org",
"@type": "Article",
"author": {
"@type": "Person",
"name": "Patrick Schmid",
"url": "https://example.com/team/PatrickSchmid",
"jobTitle": "Co-Founder and CMO",
"sameAs": ["https://www.linkedin.com/in/patrick-schmid-563634132/"]
},
"reviewedBy": {
"@type": "Person",
"name": "Reviewer Name",
"url": "https://example.com/authors/reviewer"
}
}
The FAQPage template follows the same philosophy—clean, copy-pasteable JSON-LD that the agent can emit without hallucinating markup:
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "Example question?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Example answer..."
}
}]
}
I also included the BreadcrumbList schema. By isolating these blocks, I avoid forcing the agent to generate JSON from scratch, which in my experience reduces syntax errors and schema mismatches.
To wire this together, SKILL.md uses simple relative-path references: See [E-E-A-T checklist](references/ee-at-checklist.md) for detailed signal weights and anti-patterns. and Use the [schema templates](references/schema-templates.md) for generating correct JSON-LD. When the agent hits these links during execution, it pulls the exact file contents on demand. I found that this approach keeps SKILL.md comfortably under 500 lines, while the deep domain knowledge stays available exactly when the task requires it. The progressive disclosure model is not just an architecture preference to me—it is the mechanism that makes a large, complex skill actually usable inside a constrained context window.

Step 4: Adding Scripts for Deterministic SEO Checks
I prefer to keep agent skills lean, leaning on natural-language instructions whenever possible. But when I need an exact HTTP POST with a rigid JSON schema—like pinging the IndexNow API—I reach for a script. LLMs improvise well, but they should not be trusted to construct precise API payloads or handle raw socket errors on every run. That is where deterministic scripting comes in.
When to Swap Instructions for Code
The rule I follow is simple: use instructions for reasoning, scripts for determinism. Every script I add introduces a new file to maintain, a new dependency graph, and a new point of failure. For an SEO audit skill, most logic—interpreting crawl data, prioritizing fixes, formatting reports—belongs in the instruction layer. However, submitting URLs to IndexNow is not a reasoning task; it is a deterministic HTTP operation that must return the same structured JSON every time. Offloading this to a self-contained Python utility keeps the LLM focused on analysis while the script handles the wire protocol.
Anatomy of the IndexNow Script
Looking at scripts/check-indexing.py, I notice it is deliberately lightweight. It relies solely on the Python standard library—json, sys, and urllib.request—so I do not need to wrestle with pip or virtual environments in the skill runtime. The script accepts three argument groups from the command line:
host– the target domain.key– the IndexNow API key.urls– a variadic list of URLs to submit.
It then builds a strict payload dictionary with four required fields: host, key, keyLocation, and urlList. The keyLocation is dynamically assembled as https://{host}/{key}.txt, ensuring the API can verify ownership without me hard-coding paths. The request is sent via urllib.request.Request as a POST to https://api.indexnow.org/IndexNow with an explicit Content-Type: application/json header.
Error handling is minimal but functional. A successful submission returns {"status": response.status, "message": "URLs submitted successfully"}. If the API responds with an HTTP error, the except urllib.error.HTTPError block catches it and surfaces {"status": e.code, "message": str(e)}. I would personally want to extend this for network timeouts or malformed JSON in a production version, but the scaffold gives me a clean contract: stdout always contains parseable JSON.
Script Hygiene and Skill Integration
Because scripts live outside the LLM's context window, they must be self-documenting. I make sure each utility either bundles its own dependencies or explicitly lists them in a header comment. Error messages should explain what failed, not just that something failed. Edge cases—empty URL lists, invalid host strings, non-200 IndexNow responses—should degrade gracefully rather than dumping a stack trace into the agent's reasoning loop.
In SKILL.md, I reference the tool with a single, imperative sentence: Run scripts/check-indexing.py to submit URLs to IndexNow for rapid indexing. This tells the orchestration layer exactly which file to invoke via the run_skill_script tool. I also appreciate that the platform only advertises run_skill_script when a skill actually contains scripts. If I am building a simpler skill that lives entirely in instructions, the tool list stays clean and the agent is not tempted to hallucinate script calls that do not exist.
By keeping the script small, standard-library-only, and tightly scoped to the IndexNow wire format, I get deterministic SEO checks without bloating the skill's failure surface. The LLM keeps doing what it does best—reasoning about audit results—while the Python utility handles the mechanical work of talking to the search engine's indexing API.

Step 5: Testing and Evaluating Your Skill
When I look at the SkillsBench dataset, the scale of the problem jumps out immediately: out of more than 47,000 skills scattered across 6,300 repositories, the vast majority ship without any formal testing. Teams routinely deploy agents after nothing more than an informal "vibe-check," which is exactly how subtle regressions slip into production. I believe skill testing deserves the same rigor we demand from software testing, and that means wiring it directly into CI/CD pipelines so failures surface before end-users ever see them.
Capability vs. Preference: Why the Evaluation Goal Changes
Not all skills age the same way, so I always start by classifying what I am actually testing. Capability skills extend the agent into territory the base model cannot reliably handle on its own. When I evaluate these, I am watching for obsolescence: if the underlying model gets better at the task, the skill might become dead weight. Preference skills, on the other hand, encode specific team workflows or organizational standards. Here, evaluation is about compliance—does the output match our internal conventions every single time?
The Three Evaluation Layers for an SEO Audit Skill
For a concrete skill like the SEO audit, I break validation into three distinct layers.
Positive test cases confirm the skill fires when it should. I feed prompts such as "Audit this page for SEO issues," "Check the E-E-A-T signals on this article," and "Review the structured data on this URL," then verify two things: the skill activates, and it returns the expected structured output with Critical, Warning, and Info severity levels intact. If the severity mapping drifts, the entire downstream automation that relies on those labels breaks.
Negative test cases protect against over-triggering. I deliberately send requests like "Find keywords for my niche," "Analyze my competitor's backlink profile," and "Write a blog post about SEO." Because the skill description explicitly excludes keyword research and competitive analysis, these prompts should leave the skill dormant. If the skill jumps in anyway, the description is acting as a faulty trigger mechanism, and I tighten its boundaries.
Fidelity tests go deeper than on/off behavior. I check whether the audit consistently uses imperative language, whether it flags a missing author byline as Critical, whether it correctly separates datePublished from dateModified, and whether it pulls JSON-LD templates from the references directory rather than hallucinating new ones. These behavioral checks catch logic errors that simple activation tests miss entirely.
What Systematic Evaluation Actually Delivers
The Interactions API skill case study gives me a clear benchmark. By moving from ad-hoc checks to systematic evaluation, the team pushed pass rates from 66.7% to 100%. The fixes that closed that gap also eliminated wasted tokens, blocked deprecated API usage, and enforced consistent SDK adoption. The methodology is transferable: define measurable success criteria, automate the checks, detect regressions immediately, and measure improvements objectively rather than by gut feeling.
Running Tests Without Breaking Production
I treat the skill description itself as a trigger mechanism, so I write it with direct directives instead of passive language that invites misinterpretation. I keep negative test cases in the suite permanently to guard against drift, and I schedule re-evaluation whenever the base model updates—especially for capability skills that might suddenly become redundant. When I need to isolate a skill during testing, I use [[skills.config]] inside ~/.codex/config.toml and set enabled = false. That lets me disable the skill without deleting it, which keeps the test environment clean and reversible.

The Complete SEO Audit Skill Assembled
I mapped out the directory structure first, because it reveals the design philosophy behind this skill before you even open a single file. The root SKILL.md acts as the entry point and orchestrator, while the subdirectories enforce a strict separation of concerns: executable logic lives in scripts/, domain knowledge in references/, and presentation templates in assets/. This is not accidental organization; it mirrors how production software projects separate binaries from configuration and static resources.
Frontmatter Constraints and Scope Guardrails
The frontmatter enforces rigid constraints that I find immediately reassuring. The name field uses kebab-case and stays under 64 characters, which prevents filesystem and parsing errors across different agent runtimes. The description is capped at 1,024 characters and explicitly scopes the skill's purpose—SEO auditing only—while explicitly excluding keyword research and competitive analysis. I see this as a hard guardrail against scope creep. When an agent loads this skill, there is no ambiguity about what it should and should not do.
The Six-Step Pipeline Architecture
The instructions follow a strict imperative style, which I consider critical for deterministic agent behavior. Each step builds on the previous one, creating a validation cascade:
- E-E-A-T Verification starts with identity signals. It demands full author names with credentials, active author page links, and for YMYL topics, a separate reviewer block with credentials and a visible review date. Missing any of these flags a critical gap—not a warning, but a hard stop.
- Structured Data Audit moves to machine-readable signals. The skill extracts all JSON-LD blocks and validates
@typedeclarations against specific schemas: Article, BlogPosting, FAQPage, and BreadcrumbList. It enforcesdatePublishedanddateModifiedparity with visible page content, and requires author schema to include@type: Personwithname,url, andjobTitle. - Technical SEO Checklist covers HTML-level mechanics. The constraints are precise: titles under 60 characters, meta descriptions under 155, exactly one
<h1>, logical heading nesting, and canonical link verification. It also checks social graph tags. - Content Freshness Assessment introduces temporal logic. It compares publication and modification dates, and flags a "Freshness Gap" when review dates exceed 12 months.
- Indexing Verification is where the enclosed script comes into play. The
check-indexing.pyscript handles IndexNow submissions, while the skill verifiessitemap.xmlaccessibility androbots.txtconfiguration. - Output Format standardizes reporting. Every issue must include the specific element, expected state, actual state, and fix suggestion, categorized by severity: Critical, Warning, or Info.
Progressive Disclosure and Reference Architecture
What stands out to me is the progressive disclosure pattern. The main SKILL.md does not bloat itself with the full E-E-A-T checklist or schema templates; instead, it points to references/ee-at-checklist.md and references/schema-templates.md. This keeps the instruction set scannable while allowing deep domain references to expand as needed. The audit report template in assets/audit-report-template.md functions similarly as a formatting contract, ensuring consistency across executions.
Cross-Platform Portability and the Skill Factory Pattern
I find the portability claims particularly interesting. By adhering to the agentskills.io specification, this skill becomes runtime-agnostic across Gemini CLI, Claude Code, Cursor, and OpenCode. The self-contained check-indexing.py script eliminates external dependencies that might break in isolated environments.
The Skill Factory pattern is where this gets architecturally clever. By embedding the Agent Skills specification and an example skill as references, the agent can generate spec-compliant variations at runtime. This means the SEO audit skill is not just a static tool—it becomes a template for generating other skills, provided they respect the same kebab-case naming, character limits, and imperative instruction structure.
Putting this together, I see a skill built with software engineering principles: strict interfaces, separation of concerns, deterministic execution order, and portable packaging. It treats the agent not as a black box but as a runtime that needs explicit constraints, clear entry points, and predictable output formats. For anyone building agent skills, this structure demonstrates that robustness comes from saying exactly what the agent must do, what it must never do, and where to look when it needs more detail.