# Skill Body — Best Practices Source: https://agentskills.io/skill-creation/best-practices ## Core principle: start from real expertise Ask an LLM to generate a skill without domain context → vague, generic output. Feed it real runbooks, API specs, code review comments, incident reports → specific, valuable skill. Good source material: - Internal documentation, runbooks, style guides - API specifications, schemas, configuration files - Code review comments and issue trackers - Version control history — patches and fixes reveal real patterns - Real-world failure cases and their resolutions --- ## Content principles ### Add what the agent lacks — omit what it knows Focus on what the agent *wouldn't* know without your skill: - Project-specific conventions - Domain-specific procedures - Non-obvious edge cases - The specific tools or APIs to use **Too verbose:** ```markdown ## Extract PDF text PDF (Portable Document Format) files are a common file format that contains text, images, and other content. To extract text from a PDF, you'll need to use a library. pdfplumber is recommended because it handles most cases well. ``` **Better:** ```markdown ## Extract PDF text Use pdfplumber. For scanned documents, fall back to pdf2image + pytesseract. ``` Ask: "Would the agent get this wrong without this instruction?" If no → cut it. ### Provide defaults, not menus When multiple tools could work, pick one and mention alternatives briefly. ```markdown You can use pypdf, pdfplumber, PyMuPDF, or pdf2image... Use pdfplumber: import pdfplumber For scanned PDFs requiring OCR, use pdf2image + pytesseract instead. ``` ### Favor procedures over declarations Teach the agent *how to approach* a class of problems, not what to produce for one specific instance. ```markdown Join the `orders` table to `customers` on `customer_id`, filter where `region = 'EMEA'`, and sum the `amount` column. 1. Read the schema from `references/schema.yaml` to find relevant tables 2. Join tables using the `_id` foreign key convention 3. Apply filters from the user's request as WHERE clauses 4. Aggregate numeric columns and format as a markdown table ``` --- ## Effective patterns ### Gotchas section The highest-value content in many skills. Environment-specific facts that defy reasonable assumptions — concrete corrections to mistakes the agent will make without being told. ```markdown ## Gotchas - The `users` table uses soft deletes. Always include `WHERE deleted_at IS NULL` or results will include deactivated accounts. - The user ID is `user_id` in the database, `uid` in the auth service, and `accountId` in the billing API. All three refer to the same value. - The `/health` endpoint returns 200 even if the database connection is down. Use `/ready` to check full service health. ``` Keep gotchas in `SKILL.md` — not in a reference file. The agent must read them before encountering the situation. **When to add a gotcha:** whenever an agent makes a mistake you have to correct, add the correction here. ### Output format template When the agent must produce a specific format, provide a template. More reliable than describing the format in prose — agents pattern-match well against concrete structures. Short templates → inline in `SKILL.md`. Long templates or conditional-only templates → `assets/` and reference them: ```markdown ## Report structure Use this template (full template in `assets/report-template.md`): # [Analysis Title] ## Executive summary [One-paragraph overview] ## Key findings - Finding 1 with supporting data ## Recommendations 1. Specific actionable recommendation ``` ### Checklist for multi-step workflows An explicit checklist helps the agent track progress and avoid skipping steps. ```markdown ## Progress - [ ] Step 1: Analyze the form (run `scripts/analyze_form.py`) - [ ] Step 2: Create field mapping (edit `fields.json`) - [ ] Step 3: Validate mapping (run `scripts/validate_fields.py`) - [ ] Step 4: Fill the form (run `scripts/fill_form.py`) - [ ] Step 5: Verify output (run `scripts/verify_output.py`) ``` ### Validation loop Instruct the agent to validate its own work before moving on. ```markdown ## Editing workflow 1. Make your edits 2. Run validation: `python scripts/validate.py output/` 3. If validation fails: - Review the error message - Fix the issues - Run validation again 4. Only proceed when validation passes ``` ### Plan-validate-execute (for batch/destructive operations) Have the agent create an intermediate plan, validate it against a source of truth, then execute. ```markdown ## Form filling workflow 1. Extract form fields: `python scripts/analyze_form.py input.pdf` → `form_fields.json` 2. Create `field_values.json` mapping each field name to its intended value 3. Validate: `python scripts/validate_fields.py form_fields.json field_values.json` (checks that field names exist, types are compatible, required fields are present) 4. If validation fails, revise `field_values.json` and re-validate 5. Fill: `python scripts/fill_form.py input.pdf field_values.json output.pdf` ``` --- ## Calibrating prescriptiveness Not every step needs the same specificity. Match it to the fragility of the task. **Give the agent freedom** when multiple approaches are valid and variation is acceptable: ```markdown ## Code review process 1. Check all database queries for SQL injection (use parameterized queries) 2. Verify authentication checks on every endpoint 3. Look for race conditions in concurrent code paths 4. Confirm error messages don't leak internal details ``` **Be prescriptive** when operations are fragile or exact sequence matters: ```markdown ## Database migration Run exactly this sequence: \```bash python scripts/migrate.py --verify --backup \``` Do not modify the command or add additional flags. ``` Most skills have a mix — calibrate each section independently. --- ## Sizing and progressive disclosure - Keep `SKILL.md` under **500 lines / 5,000 tokens** — just core instructions the agent needs on every run - Move detailed reference material to `references/` files - Tell the agent *when* to load each file: "Read `references/api-errors.md` if the API returns a non-200 status code" — not a generic "see references/ for more" - Design coherent units: a skill that queries a database and formats results may be one coherent unit; one that also covers DB administration is probably too broad --- ## Refining with real execution 1. Run the skill against real tasks 2. Read the execution traces (not just final outputs) — wasted steps reveal vague instructions; wrong approaches reveal instructions that don't apply 3. Add missed corrections to the gotchas section 4. Feed failed results + current `SKILL.md` to an LLM and ask for improvements When prompting for improvements: - Generalize from feedback — fix the underlying issue, not the specific test case - Keep the skill lean — fewer better instructions outperform exhaustive rules - Explain the why — "Do X because Y tends to cause Z" works better than "ALWAYS do X" - Bundle repeated work — if the agent reinvents the same helper script every run, add it to `scripts/` --- ## .gitignore conventions Every skill with a `scripts/` directory **must** have a `scripts/.gitignore`. One file, scoped to where the build output lives: ```gitignore # Node / pnpm node_modules/ dist/ .pnpm-store/ # Environment .env .env.local .env.*.local # Python virtual environments .venv/ __pycache__/ *.pyc # OS .DS_Store ``` Place it at `/scripts/.gitignore`. Git traverses the tree and picks it up regardless of where the repo root is — no need for a skill-root `.gitignore` with `scripts/node_modules/` path prefixes. **Rule:** Before the first `pnpm install` or `tsc` run, create `scripts/.gitignore`. Copy `scripts/.gitignore` from this skill as the canonical template.