AI coding assistants are good at writing generic code. The trouble is that real teams don’t run on generic code. We have opinions: how a Spring Boot service is wired, how a MongoDB collection should be indexed, what a durable workflow handler is allowed to do, and what a design document must contain before anyone writes a line of code.
For a while those opinions lived in wiki pages and in the heads of senior engineers. So I started writing them down in a form the assistant can actually use: GitHub Copilot Agent Skills. This post covers what a skill is, how I structure them for a Java, Spring Boot, MongoDB, Restate and GKE stack, and the mistakes that make skills quietly useless.
What an Agent Skill is
A skill is just a folder containing a SKILL.md file. In a repository it lives under .github/skills/ (Copilot also looks in .claude/skills/ and .agents/skills/), and personal skills can live in your home directory. Only SKILL.md is required; scripts/, references/ and assets/ are optional conventions for supporting material.
.github/skills/
restate-durable-services/
SKILL.md
references/
idempotency-and-retries.md
design-docs-hld-lld/
SKILL.md
assets/
hld-template.md
lld-template.md
SKILL.md starts with YAML frontmatter, followed by plain Markdown instructions. Two fields are required: name (lowercase letters, numbers and hyphens, matching the folder name) and description (what the skill does and when to use it, up to 1,024 characters).
The important design point is how skills get loaded. In agent mode, Copilot discovers the skills in your workspace and decides whether one is relevant to the request, based mainly on its description. Only then is the full body pulled in. That is the difference from a single, always-on instructions file.
Why not one big instructions file?
A single file that covers Java, MongoDB, Restate, Kubernetes and CI grows quickly, and everything in it competes for the model’s attention on every request, even when you’re only editing a GitHub Actions workflow. Splitting by concern gives you three things:
- Relevance. The Restate rules only load when you’re working on Restate handlers.
- Ownership. The person who knows MongoDB best owns the MongoDB skill and reviews changes to it like any other code.
- Small, reviewable diffs. A change to a team standard shows up as a pull request, not as an edit to a wiki page nobody notices.
How I split our stack
One skill per concern, named for the thing a developer is doing rather than the tool alone:
java-spring-boot-service: project layout, configuration properties, constructor injection, error handling, test conventions.mongodb-data-modeling: document shape, indexing, projections, and what not to do with unbounded arrays.restate-durable-services: what a handler may and may not do, idempotency, and how to model per-key state.gke-deployment: resource requests and limits, probes, config and secrets conventions.github-actions-ci: workflow structure, least-privilege permissions, how we pin third-party actions.design-docs-hld-lld: what a high-level and a low-level design document must contain, with templates.
A worked example: the Restate skill
Restate’s durable execution model is exactly the kind of thing an assistant gets subtly wrong. A handler can be re-executed from a journal after a failure, so code that looks fine in a normal service, such as calling an API, reading the clock or generating a random ID, can break the guarantees. That makes it a perfect candidate for a skill. Here is a trimmed version of the shape I use:
---
name: restate-durable-services
description: Conventions for writing Restate services, virtual objects and workflows in Java. Use when creating or editing Restate handlers, durable workflows, retries, timers, or per-key state.
---
# Restate handlers
## Rules
- Treat every handler as replayable. Anything non-deterministic
(HTTP calls, DB writes, clock, random IDs, UUIDs) must run inside
a durable side-effect wrapper such as `ctx.run(...)`, never bare.
- Make downstream calls idempotent. Pass a stable idempotency key
derived from the business identifier, not from the attempt.
- Use a virtual object when you need serialized access per key
(for example one order). Use a plain service when you don't.
- Keep handlers small. Orchestrate in the handler; put business
logic in plain, separately testable classes.
## Why
Restate re-executes handlers from a journal after failures. If a
side effect runs outside the wrapper it can run twice, or produce
a different result on replay.
## Checklist before finishing
- [ ] No bare network, DB, time or random calls in a handler
- [ ] Idempotency key present on every outbound call
- [ ] Handler logic covered by a unit test without the runtime
For retry and timeout policy see references/idempotency-and-retries.md
Notice three things. The rules are specific enough to check. There is a short why, which helps the model apply the rule to situations you didn’t list. And the long material (retry policy) is pushed into references/ so the main file stays well under the recommended 500-line ceiling.
Skills for documentation standards, not just code
Skills aren’t only for code. Design documents are a good candidate too. Teams argue less about what a design doc is once a template exists, and an assistant that knows the template can draft a first pass from a conversation or a ticket. The skill describes what belongs in an HLD (context, goals and non-goals, architecture, key decisions, risks) versus an LLD (data model, API contracts, sequence of calls, failure handling), and points to templates in assets/.
---
name: design-docs-hld-lld
description: Write or review high-level (HLD) and low-level (LLD) design documents. Use when asked to draft, outline or review a design doc, architecture proposal or technical spec.
---
When drafting a design document:
1. Ask which level is needed. If unclear, start with the HLD.
2. Start from assets/hld-template.md or assets/lld-template.md.
3. State goals AND non-goals. List the alternatives considered and
why each was rejected.
4. Every external dependency gets a failure-mode note: what happens
when it is slow, down, or returns bad data?
5. Flag open questions explicitly. Never invent requirements.
Writing descriptions that actually trigger
Because relevance is decided mostly from the description, it is the most important line in the file. A vague description (“Helps with backend code”) never fires, or fires on everything. A good one names the situations and the keywords a developer would actually use:
- Say what it does and when to use it (“Use when creating or editing…”).
- Include the nouns people type: handler, workflow, index, aggregation, Deployment, workflow file.
- Keep skills narrow. If one description needs five “or” clauses, it is probably two skills.
Pitfalls I’d avoid
- Don’t restate your linter. If Checkstyle or Spotless already enforces it, a skill is noise. Spend the space on judgment calls tools can’t check.
- Don’t write aspirations. “Write clean, maintainable code” changes nothing. “Inject dependencies through constructors, never fields” does.
- Don’t put secrets or client specifics in skills. They are committed to the repository and read by tools. Keep them about technique, not about any customer’s data or systems.
- Don’t let them rot. A skill that describes last year’s conventions is worse than none. Review skills in the same pull requests that change the conventions.
How to test a skill
Treat a skill like code: give it a test. Pick two or three realistic prompts (“add a Restate handler that charges a payment and sends a receipt”), run them in agent mode, and check two things. First, did the skill activate? Activated skills appear in the chat, so you can see it. Second, does the output follow the rules, including the ones you most care about? If it doesn’t activate, fix the description. If it activates but ignores a rule, make the rule more specific or add a short example of the right and wrong version.
Where this leaves us
Skills don’t make an assistant smarter. They make it better informed about your team. The real payoff is a side effect: writing a skill forces you to say, precisely and in one place, how you build software. Half the value is the conversation that produces the file.
If you try this, start small: one skill, for the area where reviews keep repeating the same comment. Test it on real tasks, and grow from there.
Reference: Copilot Agent Skills (Microsoft Learn) for folder locations and frontmatter fields.

Leave a Reply