Back to Blog
Mastering Skills: How Custom AI Instructions Elevate Code Consistency
Photo from Unsplash

Article content

What Are AI Skills?

Every AI agent starts with zero context about your project. Without guidance, it'll use npm when you use yarn, write CSS-in-JS when your team uses SCSS modules, and name files however it feels right in the moment. On a real project I watched an agent spend 40 minutes building a working feature, then fail review because it created UserProfile.jsx in a codebase that has used .tsx exclusively for two years. The code was correct. The convention violation cost more review time than the feature took to build.

A Skill (or AGENTS.md / CLAUDE.md file) is the mechanism that fixes this: a persistent, project-specific set of instructions that travels with the codebase. It's not documentation for humans; it's a system prompt for machines, read fresh at the start of every session, before the agent writes a single line.

It's the difference between an agent that works in your project and one that works for your project. The gap between those two states, in practice, is measured in review cycles: a well-tuned skill file turns a 3-round PR review (wrong package manager, wrong file location, missing error boundary) into a 1-round review (does the logic work).

What a Real Skill Looks Like

Here's a simplified version of the agent instructions used on this portfolio:

# AGENTS.md — mirzaa.dev
 
## Stack
- Next.js 16 App Router, TypeScript, SCSS Modules
- Use `yarn` — never npm
- All components in `src/components/`, co-located with their `.module.scss`
 
## Mandates
- Always run `yarn build` before marking a task complete
- Use `Space Grotesk` for headings, `Inter` for body text
- CSS tokens live in `src/tokens/brand.json` — never hardcode hex values
- All new blog posts must include a `published: false` flag until reviewed
 
## Code Patterns
- Prefer React Server Components — only add `'use client'` when state or browser APIs are needed
- New API routes go in `src/app/api/` as Route Handlers, not the `pages/api/` directory
- Error boundaries required on all dynamic page segments

This file sits in the project root. Every agent session that reads it behaves consistently: the same naming conventions, the same build tooling, the same architectural constraints, regardless of who or what is doing the work. On multi-repo setups, a top-level AGENTS.md plus a scoped one inside apps/web/AGENTS.md lets you keep global mandates (package manager, commit style) separate from app-specific ones (this app uses SCSS Modules, that one uses Tailwind) without duplicating either.

The Three Layers of an Effective Skill

A well-structured skill has three distinct layers:

  • Mandates: non-negotiable rules with zero tolerance for deviation. Package manager, file naming, build commands.
  • Context: project knowledge that the agent can't infer from code alone. Design token locations, font choices, what branch to target.
  • Procedures: step-by-step workflows for recurring tasks. "When adding a new blog post, do X then Y then Z."

The mandates stop the mistakes. The context stops the guesswork. The procedures stop the inconsistency. Each layer fails differently when it's missing: skip mandates and you get inconsistent tooling across every PR; skip context and the agent asks (or worse, guesses) the same three questions every session; skip procedures and every recurring task gets reinvented slightly differently each time, which is its own kind of drift.

A good test for whether a rule belongs in the mandates layer: would you block a PR over it? "Always use yarn" is a mandate because a PR with a package-lock.json gets rejected. "We generally prefer composition over inheritance" is not a mandate, it's a preference, and preferences belong in code review comments, not in a file the agent treats as law. Mixing the two teaches the agent that mandates are negotiable, which defeats the point of having them.

Keeping the Skill File From Going Stale

The failure mode nobody warns you about isn't a missing skill file, it's a stale one. Six months in, the file still says "use Jest" three sprints after the team migrated to Vitest. An agent reading it faithfully installs jest alongside your existing vitest config and writes tests that don't run in CI. Nobody notices until the PR fails a check nobody remembers configuring.

Treat the skill file like a dependency: it needs the same lifecycle discipline as package.json. Two practices catch drift before it compounds:

  1. Add a mandate review to your migration checklist. Any PR that changes tooling (test runner, linter, package manager, framework version) also touches AGENTS.md in the same commit. This is a one-line addition to a PR template, not a new process.
  2. Grep the file for tool names during a quarterly audit. Run grep -E "jest|npm run|webpack" AGENTS.md against your actual package.json dependencies. Any mismatch is a stale mandate.
# Quick staleness check: do the tools named in AGENTS.md
# still exist in package.json?
grep -oE '`[a-zA-Z0-9_-]+`' AGENTS.md | tr -d '`' | sort -u | \
  while read -r tool; do
    grep -q "\"$tool\"" package.json || echo "Possibly stale: $tool"
  done

This isn't a perfect check (it'll flag false positives on tools mentioned as "don't use this"), but run quarterly it catches the drift that silently degrades agent output over months.

Skills and Multi-Agent Handoffs

The pattern gets more valuable, not less, once more than one agent touches the same codebase. A team running a planning agent, a coding agent, and a review agent in sequence needs all three reading the same mandates, or the handoffs introduce their own inconsistency: the planning agent proposes a REST endpoint, the coding agent builds it as a Route Handler under pages/api/ because that's what its training data favors, and the review agent flags it because the skill file (which it actually read) says Route Handlers live under src/app/api/. The fix isn't a smarter review agent, it's making sure every agent in the chain reads the same file before it starts. This is also the pattern behind an MCP server exposing project context as a resource rather than each agent independently guessing; if you're building agent-to-agent workflows, this is worth understanding in more depth (see the post on MCP and AI agent integration).

Skill files also pair naturally with documentation-as-code practices: if your architecture decisions already live in versioned markdown next to the code they describe, promoting the load-bearing subset of that into AGENTS.md is a small step rather than a new discipline (more on structuring that documentation in Documentation as Code).

Practical Takeaway

Start with the mistakes you've already caught, not a hypothetical comprehensive policy. Every time an agent does something you have to undo this week (wrong package manager, wrong naming convention, wrong file structure), add one mandate line to your Skill file the moment you catch it, not at the end of the sprint. After two weeks of this discipline, open AGENTS.md and read it as if you'd never seen the codebase: if a rule in there still surprises you, it's specific enough to be useful. If every rule reads as generic advice ("write clean code," "follow best practices"), you haven't captured your project's actual constraints yet, and the file isn't pulling its weight.


Sources & References

  • OpenAI Prompt Engineering Guide — official documentation on structuring instructions for consistent model behavior
  • Gemini CLI (Google) — open-source reference implementation of AGENTS.md-style custom instructions
  • Anthropic Prompt Engineering Guide — official documentation on system prompts and persistent context
Newer Post

The Semantic Foundation: Why High-Performance CSS Still Rules Enterprise SEO

Older Post

The Open Standard for AI Tool Integration: How MCP Is Reshaping Agent Architecture

Suggested Reading

Architectural Note: Research, drafting, and code for this post were augmented by Gemini (Google DeepMind), directed and verified by Maas Mirzaa. How this workflow works →