Write an AI agent skill your team can rely on
By Randy Olson, Co-Founder & CTO, Goodeye
Most skills fail one of three ways: the agent never loads them, teammates run different copies, or nobody can say whether the output was right. Triage the trigger in order (is the skill on disk where the tool reads it, is its frontmatter valid, is the description specific, is another skill winning), then host it in Goodeye so one version is the version, grade it with `goodeye skills audit`, and tune the trigger with `goodeye skills optimize-description`.
You write a skill. It reads well. Then one of three things happens: the agent never loads it, because the trigger description was too vague to match anything a person actually types. Or it loads and produces something different on your teammate's machine, because their copy is four edits behind yours. Or it runs end to end and nobody can say whether the result was any good, because the skill never defined what good meant. This guide is about writing the kind that survives all three: a skill that fires when it should, runs the same for everyone, and can be judged against something other than vibes.
Anthropic's own posts on Agent Skills cover what a skill is and how the format works, and they cover it well. This page picks up where that leaves off: what changes when a team depends on the thing.
Goodeye, our product, runs through the commands below. It is a hosted service that holds your agent skills, keeps one version of each in sync across everyone's machines, and grades them against checks you can name. You reach it with the goodeye CLI or an MCP server, and the CLI needs an account and a one-time sign-in, both covered in getting started. The reasoning in each section stands on its own; the commands are how Goodeye does that step.
Why your skill never triggers
This is the most common failure, and the reason you arrive here is that you cannot see why it happened: the agent simply did something else. So do not start by rewriting the description. Work these four in order; they are ordered by how often each turns out to be the cause.
1. Is the skill even loaded?
Confirm the agent could have found it before you change a word of it.
Agents that read skills from disk expect a directory per skill: <skills-directory>/<slug>/SKILL.md, not a loose markdown file dropped at the top level. That is also exactly the shape Goodeye's sync writes. So look in the directory your tool actually reads (~/.claude/skills for Claude Code, ~/.agents/skills for Codex, ~/.cursor/skills for Cursor), and confirm a folder named for your skill is there with a SKILL.md inside it.
If the skill is hosted in Goodeye and mirrored down, one command answers this without touching anything:
goodeye skills sync status
It signs in and reads only: it lists what the registry holds and compares that against disk, without downloading a skill body or writing anything on either side. You get a row per skill and target directory with a state and the action that would reconcile it.
Two readings answer this step. No row at all for the target your tool reads means the skill was never pulled there, which is a different bug from a weak description and has a different fix. A row reading behind-server means the copy on disk is older than the hosted one, so pull. The remaining states describe drift rather than a missing skill: clean, modified-local (you edited the local copy), conflict (both sides moved), deleted-on-server (gone from the registry, still on your disk), and untracked (a local skill directory Goodeye does not know about yet).
2. Is the front-matter valid?
A skill needs a name and a description. Miss either and there is nothing to register under and nothing to match a prompt against, so it fails silently rather than firing weakly. Goodeye requires both on save too: supply them as YAML front-matter in the body, or as --name / --description flags on goodeye skills publish, where the flags win when both are present. Everything else, including tags and outcome, is optional and changes nothing about whether the skill loads. The skills reference has the field list.
3. Is the description specific enough?
This is the one people expect, and it is the real cause often enough to earn its reputation.
The description is what the agent matches your prompt against before it decides whether to load the skill, competing with the agent's own default instinct to just start working. A vague description loses that competition every time.
Vague, and it will never fire:
description: Helps with code review.
Specific, and it will:
description: Use when reviewing a pull request or a diff in this repo's Python
services. Checks naming, error handling, structured logging, and test coverage
against the team's conventions. Triggers on "review this PR", "check this diff",
or a request to look over changes before merge.
Three things changed. It names the situation (reviewing a PR or diff), the artifacts (this repo's Python services), and the phrases a person actually types. A description written for a human reader describes what the skill does; a description written for an agent describes when to reach for it. Those are different documents.
Goodeye has a command for tuning exactly this, and it changes only the description (body, tags, and files carry forward untouched):
goodeye skills optimize-description my-code-review
It returns a prompt pack your agent runs locally with you, iterating on the description for trigger accuracy: firing on the prompts it should and staying quiet on the look-alikes. It defaults to 10 iterations (--max-iterations to change it) and does not draw on your credits. Nothing is saved until you approve the result. See optimizing a trigger description for the reference, and optimize_description for the same thing over MCP.
4. Is another skill winning?
Two skills whose descriptions cover overlapping situations compete for the same prompt, and nothing guarantees the one you had in mind wins. This shows up as a skill that triggers sometimes, or as the wrong one loading on a phrase you thought you had claimed. The fix is not to make your description longer but to make the boundary between the two explicit: narrow each one to the situation only it should own, then re-run optimize-description on the pair so each is tuned against the other's prompts as look-alikes.
Watch for the duplicate-by-accident version of this too: a skill you copied into a second directory months ago and forgot, now shadowing the hosted one. sync status from step 1 surfaces that as an untracked local skill.
And one mundane cause, listed last but quick enough to rule out first: you asked mid-task. If the agent was already several steps into work when you typed, ask again at the start of a fresh turn before concluding the skill is at fault.
The anatomy of a skill that holds up
Once it fires, four parts do the work. Keep them short; the skills reference has the full detail.
The description and the verifier reference are the two most people skip, and they are the two that decide whether the skill works for anyone but its author. You have just done the description. The verifier reference is further down.
One more trigger-adjacent point first: a skill that lives only on your laptop cannot trigger on anyone else's.
Make the agent follow your team's conventions
The usual approach is that everyone pastes the team's rules into their own local agent config. It works for about a week. Then someone tightens the error-handling rule, tells the team in Slack, and three people update their file. Two months later, four engineers have four different definitions of the team's conventions and the agent is confidently enforcing all of them.
The honest fix is not a better paste. It is to write the convention down once as a skill, host it, and have everyone's agent pull the current version. That is the Always in sync property: the same skill in Claude Code, Codex, and Cursor and on every machine, updated once.
Save the skill you already have on disk. An agent skill directory is already the right shape, a SKILL.md plus siblings:
goodeye skills publish ~/.claude/skills/python-review
Then point a sync target at the directory each tool reads, so the hosted skill stays the source of truth:
goodeye skills sync target add --preset claude # ~/.claude/skills
goodeye skills sync target add --preset codex # ~/.agents/skills
goodeye skills sync target add --preset cursor # ~/.cursor/skills
goodeye skills sync pull
goodeye skills sync status reports drift between disk and hosted without writing anything, and automatic sync keeps a configured target current after that. Full detail in syncing a bundle locally.
For the rest of the team, grant the skill to a team handle rather than to each person:
goodeye skills grant python-review @my-team view
Onboarding a new engineer is then one goodeye teams add-member and their acceptance of the invitation it creates. Membership is not imposed on someone: the invitation has to be accepted before they join and inherit the team's skills. Roles, version floors, and revoking are covered in sharing a skill privately and revoking access, and the invitation flow in the teams reference; no need to repeat them here. The point for this page is narrower: the convention now has one canonical version, and "update your config" stops being a thing anyone has to say.
Skills and MCP servers are different layers
Worth clearing up, because the two get conflated constantly and it changes what you should be writing.
An MCP server gives an agent new capabilities: tools it can call. Query the warehouse, open a pull request, read a ticket. Before the server, the agent could not do it at all.
A skill is the runbook telling the agent how to do a job well. Ordered steps, the conventions to follow, the checks the result must pass. It may call the tools an MCP server provides, and a good skill often names the ones it expects.
Capability versus procedure. They compose. Adding an MCP server does not make an agent good at your job any more than giving someone database access makes them a good analyst, and a skill with no tools behind it can still be the difference between a usable result and a plausible-looking one. Goodeye itself is reachable both ways, through a CLI and an MCP server, so an agent can fetch and run a hosted skill through whichever surface it already speaks.
How to tell if a skill is any good
Here is where most skill-writing advice stops, and it is the part that matters when someone else's work depends on yours.
Goodeye grades a skill against two named authoring checks, and you can run that grading on a skill of your own right now:
goodeye skills audit python-review
An audit is a prompt pack your agent runs locally. It reads the skill body along with every sibling file that directs behavior, then hands back findings ranked by how much they matter (P0 for a blocker, P1 for a recommendation, P2 for polish), quoting the text at fault and putting one concrete fix beside it. Nothing is applied unless you approve it. Omit the id and it grades a skill file on disk that is not hosted anywhere yet. The reference is in auditing skills, and the same thing is available as the audit_skill MCP tool.
The report is organized around the two checks:
- Runnable: can an agent actually carry this out? Steps in an order, and a stated contract for what goes in and what comes back.
- Well-formed: will anyone else find it, read it the way you meant it, and be able to tell when it worked? That means a trigger description that names its situation, terminology used consistently, a definition of a correct output in terms you could check, and at least one specific verifier rather than a blanket "is this good overall?" judgement.
That last clause is the opinionated one, and it is the claim worth arguing for: a skill that cannot say what a correct output looks like in checkable terms is not a finished skill. It is a suggestion. "Make it high quality" is not a standard; "every figure in the summary traces to a line in the source document" is. The first cannot fail. The second can, which is the entire point. A verifier is a rubric you write, deployed once, so a pass means the same thing on your machine and your teammate's. See verifier references for how a skill binds one, and verify AI agent output before it ships for why the check belongs inside the agent's loop rather than in a report afterward.
One practical detail that decides whether the check ever runs: name the check in the skill body. Binding a verifier with --verifier name=verifier_id records the dependency on the hosted skill, and an agent that fetches the whole skill record does see those bindings, but sync writes only the body to disk, so the body is the part that reaches your teammate's editor on every path. Write the step in ("run the summary-grounding verifier on the draft and do not proceed unless it passes"), and the agent runs the check on its own output as part of following the runbook instead of producing something nobody checked. The call itself is the run_verifier MCP tool, or goodeye verifiers run for an agent working from a shell.
Vet a skill someone else wrote
Same command, different reason. Read the body, then audit it rather than trusting it. If the report says there is no defined output contract and no real verifier, you have learned something specific enough to send back.
The safety scan is a third check, and it is a separate call that behaves differently from the audit in two ways. It runs on Goodeye rather than as a local prompt pack, so it needs the skill saved first: goodeye skills check-safety <id-or-name> takes a Goodeye skill id or slug, not a path, and unlike the audit it draws on your credits. And it returns a status rather than a report: clean, flagged when it raises an advisory concern about the content, or blocked when it finds something that would be rejected outright.
Publishing is what turns a skill into a template: a public listing in Goodeye's catalog, which displays all three checks so a reader can see how a skill was written before deciding to run it. Publishing also runs that same safety scan. A blocking finding stops the publish; an advisory one flags the version and lets it publish with the flag attached, which is why a listing can read flagged rather than simply not being there.
Design a new one
Starting from scratch, goodeye design prints a guided design session that produces a skill plus its verifiers:
goodeye design > prompt.md
Pipe it into your agent and work through it. Worth stating the philosophy, because it is deliberate: like audit and optimize-description, design returns a prompt pack your agent runs locally with you, and nothing is written anywhere until you approve the result and save it with goodeye skills publish -, where the - reads the finished skill from stdin instead of from a file. The session does not go off and generate a skill you then have to review. You are in the loop while it is being made, which is the only point at which your actual standard is available to be captured.
Where to go next
The short version: triage the trigger before you rewrite it, host the skill so one version is the version, and give it at least one real check so "is this good?" has an answer that is not an opinion.
The check is the piece most teams have not written yet. Run a rubric check on AI output from the CLI walks through authoring that rubric, deploying it, and running it against real output. Then bind it to the skill with --verifier name=verifier_id on your next save, and name it in the body so the agent runs it. If you are setting Goodeye up for the first time, start at getting started; the verifiers reference has the full detail on deploying and running one.
Frequently asked questions
Why does my Claude Code skill never trigger, and what tools help fix it?
Check four things in order. First, that the skill is on disk where the tool reads it: agents load skills as `<skills-directory>/<slug>/SKILL.md`, and `goodeye skills sync status` reports which hosted skills are mirrored to which directory, and which are stale, without writing anything. Second, that the front-matter has both a `name` and a `description`: a skill missing either has nothing to register. Third, that the description is specific: it is what the agent matches your prompt against, so "helps with code review" loses to the agent's default instinct to just start working. Goodeye's `goodeye skills optimize-description <id-or-name>` returns a prompt pack that tunes only the description for trigger accuracy. Fourth, that no second skill with an overlapping description is winning the same prompt.
How do I make an AI coding agent follow my team's conventions?
Write the convention down once as a skill, host it, and have every teammate's agent pull the current version instead of each person pasting rules into their own local config. In Goodeye a skill is the hosted runbook your AI follows, and `goodeye skills sync target add --preset claude` (or `--preset codex` / `--preset cursor`) mirrors it into the directory each tool reads, so one edit reaches everyone on the next pull. Grant it to a team handle so joiners get it once they accept the team invitation, and reference a verifier so the convention is checked, not just described.
What tools benchmark or grade AI agent skills?
Every public template displays three named checks, so you can see how a skill is written before you run it: the two authoring checks Goodeye grades a skill against (Runnable and Well-formed), plus Safety, which the platform stamps at publish time. Run `goodeye skills audit <id-or-name>` on a hosted skill (or omit the id to audit a skill file on disk) and you get a priority-ranked report tagged P0, P1, or P2 against those two authoring checks, each finding quoting the text to change and stating one concrete fix. The audit does not run the safety screen; that is the separate `goodeye skills check-safety` call. The authoring checks grade how the skill is written; a verifier grades what it produces.
How do I vet an AI agent skill someone else wrote before my team uses it?
Read the body, then grade it rather than trusting it. With Goodeye, run `goodeye skills audit <id-or-name>` against the hosted skill, or omit the id to grade a skill file sitting on disk before you save it anywhere, for a priority-ranked report on whether it has clear ordered steps, a defined input and output contract, and at least one real verifier. The platform safety scan is a separate call that needs the skill saved first: `goodeye skills check-safety <id-or-name>` takes a Goodeye skill id or slug rather than a path, and unlike the audit it draws on your credits. A skill that cannot say what a correct output looks like in checkable terms is the one to send back.
What's the difference between MCP servers and agent skills?
An MCP server gives an agent new capabilities: tools it can call, like querying your database or filing a ticket. A skill is the runbook telling the agent how to do a job well, which may use those tools. Capability versus procedure: they compose rather than compete, and a good skill often names the MCP tools it expects. Goodeye is reachable both ways: a `goodeye` CLI and an MCP server at `https://mcp.goodeye.dev/mcp`, so your agent can fetch and run a hosted skill through whichever surface it already speaks.