Writing Effective Instructions in Skill Files
The quality of a skill file is determined by how well its instructions can be followed by an AI agent. Vague, ambiguous, or poorly structured instructions lead to incorrect or incomplete results. This skill teaches how to write instructions that are precise, unambiguous, and actionable — the difference between a skill that works and one that confuses. ## Key Points 1. Install dependencies: 2. Create a `.env` file with your database URL: 3. Run the database migration: 4. Verify migration succeeded: 1. [Precondition or setup] 2. [First action — specific command or change] 3. [Verification — how to confirm step 2 worked] 4. [Next action — builds on step 2] 5. [Final verification — end-to-end check] 1. Ensure Docker is running (`docker info` should show server info) 2. Pull the PostgreSQL image: 3. Verify the image was downloaded: ## Quick Example ``` After: ``` ``` Changes: - Added `async/await` (was missing, causing unhandled promise) - Added return type `Promise<User | null>` (type safety) - Selected specific columns instead of `*` (performance, security) - Return `null` instead of `undefined` for missing user (explicit) ```
skilldb get skill-writing-skills/writing-effective-instructionsFull skill: 378 linesWriting Effective Instructions in Skill Files
Purpose
The quality of a skill file is determined by how well its instructions can be followed by an AI agent. Vague, ambiguous, or poorly structured instructions lead to incorrect or incomplete results. This skill teaches how to write instructions that are precise, unambiguous, and actionable — the difference between a skill that works and one that confuses.
Principles of Effective Instructions
Clarity Hierarchy
Instruction Clarity Levels:
┌────────────────────────────────────────────────────┐
│ Level 4: Mechanical (best for AI) │
│ "Run `npm install express` then create a file │
│ called server.js with the following content:..." │
├────────────────────────────────────────────────────┤
│ Level 3: Procedural (good) │
│ "Install Express, create a server file, define │
│ a GET route for /, and start listening on port │
│ 3000." │
├────────────────────────────────────────────────────┤
│ Level 2: Descriptive (mediocre) │
│ "Set up a basic Express server that responds to │
│ HTTP requests." │
├────────────────────────────────────────────────────┤
│ Level 1: Abstract (poor) │
│ "Create a web server." │
└────────────────────────────────────────────────────┘
Rule: Write at Level 3-4 for implementation steps.
Use Level 2 for conceptual framing.
Never use Level 1.
The PRECISE Framework
P — Particular: Name exact technologies, versions, APIs
R — Reproducible: Same input → same output, every time
E — Explicit: State assumptions, prerequisites, constraints
C — Complete: Cover the full path from start to finish
I — Incremental: Build up complexity step by step
S — Specific: Use concrete values, not "appropriate" or "suitable"
E — Examinable: Include verification steps (how to check it worked)
Common Instruction Failures
Vague Language
VAGUE → PRECISE Transformations:
"Use an appropriate data structure"
→ "Use a HashMap<String, Vec<Order>> keyed by customer ID"
"Handle errors properly"
→ "Wrap the database call in try/catch. On connection error,
retry up to 3 times with exponential backoff (1s, 2s, 4s).
On query error, log the error and return HTTP 500."
"Configure the database connection"
→ "Set the connection pool size to 10, connection timeout
to 5 seconds, and idle timeout to 300 seconds."
"Make sure it's performant"
→ "Response time must be under 200ms at p95 for 100
concurrent users. Add an index on users.email."
"Add some tests"
→ "Write unit tests covering: successful login, login with
wrong password, login with non-existent email, and login
with expired account. Assert HTTP status and response body."
Ambiguous Pronouns and References
AMBIGUOUS:
"After creating the component, add it to the page.
Then style it to match."
CLEAR:
"After creating the `UserProfile` component, import it
in `app/dashboard/page.tsx` and render it below the
`<Header>` component. Apply the styles from
`styles/profile.module.css`."
AMBIGUOUS:
"If that doesn't work, try the other approach."
CLEAR:
"If the WebSocket connection fails (error event fires),
fall back to HTTP long-polling using the `/api/poll`
endpoint with a 5-second interval."
Missing Context
MISSING CONTEXT:
"Install the dependencies and run the migration."
WITH CONTEXT:
"Prerequisites: Node.js 20+, PostgreSQL 15+ running locally.
1. Install dependencies:
npm install
2. Create a `.env` file with your database URL:
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
3. Run the database migration:
npx prisma migrate deploy
4. Verify migration succeeded:
npx prisma db seed
# Expected output: 'Seeded 10 users, 50 posts'"
Instruction Patterns
The Stepwise Pattern
For procedures with a clear sequence:
Pattern:
1. [Precondition or setup]
2. [First action — specific command or change]
3. [Verification — how to confirm step 2 worked]
4. [Next action — builds on step 2]
5. [Final verification — end-to-end check]
Example:
1. Ensure Docker is running (`docker info` should show server info)
2. Pull the PostgreSQL image:
docker pull postgres:16-alpine
3. Verify the image was downloaded:
docker images | grep postgres
# Should show postgres:16-alpine
4. Start the container:
docker run -d --name mydb \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
postgres:16-alpine
5. Verify the database is accepting connections:
docker exec mydb pg_isready
# Expected: "accepting connections"
The Decision Tree Pattern
For instructions that branch based on context:
Pattern:
If [condition A]:
→ Do X
→ Then Y
If [condition B]:
→ Do Z instead
→ Then Y (same next step)
Otherwise:
→ Default action
Example:
Determine your package manager:
- If `package-lock.json` exists → use `npm`
- If `yarn.lock` exists → use `yarn`
- If `pnpm-lock.yaml` exists → use `pnpm`
- If none exist → use `npm` (default)
Then install dependencies:
- npm: `npm install`
- yarn: `yarn install`
- pnpm: `pnpm install`
The Before/After Pattern
For showing transformations:
Pattern:
Before (current state):
[Show existing code/config/state]
After (desired state):
[Show modified code/config/state]
What changed and why:
[Explain the diff]
Example:
Before:
```typescript
function getUser(id: string) {
return db.query('SELECT * FROM users WHERE id = $1', [id]);
}
After:
async function getUser(id: string): Promise<User | null> {
const result = await db.query(
'SELECT id, name, email FROM users WHERE id = $1',
[id]
);
return result.rows[0] ?? null;
}
Changes:
- Added
async/await(was missing, causing unhandled promise) - Added return type
Promise<User | null>(type safety) - Selected specific columns instead of
*(performance, security) - Return
nullinstead ofundefinedfor missing user (explicit)
### The Checklist Pattern
For verification and quality assurance:
Pattern: □ [Checkable assertion] □ [Checkable assertion] □ [Checkable assertion]
Example:
Before deploying, verify:
□ All tests pass: npm test exits with code 0
□ No TypeScript errors: npx tsc --noEmit exits with code 0
□ Linting passes: npm run lint reports no errors
□ Build succeeds: npm run build produces output in dist/
□ Environment variables documented in .env.example
□ Database migrations included in commit
□ Changelog updated with version and changes
## Writing for Different Audiences
### Writing for AI Agents vs. Humans
AI Agent Optimization: ├── Be explicit about file paths (absolute when possible) ├── Specify exact commands (not "install the package") ├── Include expected output for verification ├── State constraints upfront ("do not modify files in /config") ├── Use consistent terminology (don't alternate between synonyms) ├── Provide complete code blocks (agents can copy directly) └── Avoid idioms and metaphors ("bite the bullet", "low-hanging fruit")
Human Optimization: ├── Explain WHY, not just what ├── Provide context for decisions ├── Use analogies when introducing new concepts ├── Include visual aids (diagrams, screenshots) ├── Group related steps logically └── Offer alternatives when multiple approaches exist
Both: ├── Use consistent formatting ├── Break complex tasks into steps ├── Include error handling guidance ├── Provide verification methods └── Maintain logical flow from start to finish
### Skill Files Serve Both
Best Practice: Write instructions that work for both audiences.
Structure:
- Brief conceptual explanation (for humans understanding WHY)
- Concrete implementation steps (for AI agents executing HOW)
- Verification steps (for both to confirm correctness)
Example: "Database indexes speed up queries by creating sorted lookup structures, similar to a book's index. Without an index, the database must scan every row (sequential scan).
Add an index on the email column of the users table:
CREATE INDEX idx_users_email ON users (email);
Verify the index was created:
SELECT indexname FROM pg_indexes WHERE tablename = 'users';
-- Should include 'idx_users_email' in results
Verify the query now uses the index:
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
-- Should show 'Index Scan' not 'Seq Scan'
```"
Instruction Anti-Patterns
Anti-Patterns to Avoid:
1. "Obviously" / "Simply" / "Just"
└── If it were obvious, you wouldn't need to document it
└── These words dismiss complexity and frustrate readers
2. Forward references
└── "As we'll see later..." — reader needs info NOW
└── Either provide it now or restructure the document
3. Assumed knowledge without stating it
└── BAD: "SSH into the server and..."
└── GOOD: "Prerequisites: SSH access to the production server
(see operations wiki for credentials)"
4. Mixing instruction levels
└── Don't alternate between high-level overview and detailed
commands in the same section
5. Instruction without exit criteria
└── BAD: "Configure nginx"
└── GOOD: "Configure nginx... Verify: `curl localhost` returns
your application's homepage"
6. "Etc." in instructions
└── BAD: "Install Python, pip, virtualenv, etc."
└── GOOD: "Install Python 3.11, pip, and virtualenv"
└── Everything needed should be listed explicitly
7. Conditional steps without specifying the condition
└── BAD: "You may need to restart the service"
└── GOOD: "If the configuration file was modified, restart:
`sudo systemctl restart nginx`"
Editing and Refinement
Self-Review Process
Instruction Review Checklist:
1. Read each instruction as if you know nothing about the topic
└── Is every step self-contained?
2. Check every pronoun — does "it", "this", "that" have a clear referent?
3. Check every command — would copy-paste work?
4. Check every path — is it absolute or clearly relative to a stated root?
5. Check every assumption — is it stated as a prerequisite?
6. Check every outcome — can the reader verify it worked?
7. Read the entire sequence — does it flow logically?
8. Try to break it — what if a step fails? Is that addressed?
When to Apply This Skill
Use this skill when:
- Writing the implementation sections of any skill file
- Reviewing skill files for instruction clarity
- Converting informal notes into structured skill instructions
- Debugging why an AI agent isn't following a skill correctly
- Training others to write skill files
- Improving existing skills that receive poor feedback
Install this skill directly: skilldb add skill-writing-skills