Practical guide
Writing skills for AI agents, once, for every agent.
What a skill is, how to create one, where Claude Code, Codex, opencode and Hermes look for it, when to split one into two, how to design skills for review, security, code and requirements, and how to validate and test them.
O que é uma skill e o que ela fazWhat a skill is and what it does
Uma skill é uma pasta com um arquivo SKILL.md: um cabeçalho YAML (nome e descrição) e, abaixo, instruções em Markdown. Ela ensina ao agente um procedimento repetível (como revisar um PR, como escrever requisitos, como fazer um release) e só entra no contexto quando a tarefa pede. O formato é um padrão aberto, o Agent Skills, e a mesma pasta funciona no Claude Code, no Codex, no opencode e no Hermes (cada um acrescenta extras, veja onde ficam).A skill is a folder with a SKILL.md file: a YAML header (name and description) and, below it, instructions in Markdown. It teaches the agent a repeatable procedure (how to review a PR, how to write requirements, how to cut a release) and only enters the context when the task calls for it. The format is an open standard, Agent Skills, and the same folder works in Claude Code, Codex, opencode and Hermes (each adds extras, see where they live).
O truque é a divulgação progressiva: no início o agente lê só o nome e a descrição de cada skill (cerca de 100 tokens por skill, segundo a especificação). Se a tarefa casa com a descrição, ele carrega o corpo do SKILL.md. Arquivos de apoio só são lidos se o corpo mandar. Assim você pode ter dezenas de skills instaladas sem encher o contexto.The trick is progressive disclosure: at the start the agent reads only the name and description of each skill (about 100 tokens per skill, per the specification). If the task matches the description, it loads the SKILL.md body. Supporting files are read only if the body says so. That way you can have dozens of skills installed without filling the context.
| MecanismoMechanism | Quando entraWhen it enters | Serve paraWhat it is for |
|---|---|---|
| AGENTS.md / CLAUDE.md | SempreAlways | Fatos curtos que valem em toda tarefa (“rode pnpm test”).Short facts that hold for every task (“run pnpm test”). |
| Skill | Quando a descrição casa, ou você chamaWhen the description matches, or you call it | Um procedimento com passos, formato de saída e, às vezes, scripts.A procedure with steps, an output format and sometimes scripts. |
| Ferramenta / MCPTool / MCP | Quando o modelo chamaWhen the model calls it | Uma ação que o modelo não faz sozinho (veja a nota de MCP).An action the model cannot do alone (see the MCP note). |
| SubagenteSubagent | Quando o agente principal delegaWhen the main agent delegates | Trabalho volumoso que não deve poluir o contexto principal.Bulky work that should not pollute the main context. |
A comparação completa, com RAG e hooks, está na nota de harness. A regra prática: fato curto e sempre válido vai no AGENTS.md; procedimento vai numa skill; ação vai numa ferramenta.The full comparison, with RAG and hooks, is in the harness note. The practical rule: a short, always-valid fact goes in AGENTS.md; a procedure goes in a skill; an action goes in a tool.
O que uma boa skill faz, e o que não fazWhat a good skill does, and what it does not
- Traz o que o agente não sabe: as convenções do seu projeto, os passos na ordem certa, as armadilhas (“a tabela
usersusa exclusão lógica”). Não explica o que o agente já sabe, como o que é um PDF ou um SQL injection.Brings what the agent does not know: your project's conventions, the steps in the right order, the traps (“theuserstable uses soft deletes”). It does not explain what the agent already knows, like what a PDF or a SQL injection is. - Fixa o formato da saída com um modelo (template): o agente segue estruturas concretas melhor do que descrições em prosa.Fixes the output format with a template: the agent follows concrete structures better than prose descriptions.
- Entrega scripts quando um passo precisa ser idêntico a cada vez. O script roda e só a saída gasta contexto.Ships scripts when a step must be identical every time. The script runs and only its output costs context.
- Não é um sandbox nem uma permissão. A skill roda com o acesso que o agente já tem; ela é instrução, e instrução pode ser ignorada ou enganada. O que precisa valer sempre vai em hook, permissão ou rede (veja segurança).It is not a sandbox or a permission. The skill runs with the access the agent already has; it is instruction, and instruction can be ignored or tricked. What must always hold goes in a hook, a permission or the network (see security).
Como criar uma skill, passo a passoHow to create a skill, step by step
- Faça a tarefa uma vez, com o agente, sem skill. Dê o contexto, corrija os desvios, diga as preferências. Depois olhe: quais passos funcionaram, quais correções você fez, que formato de entrada e saída apareceu. É isso que vira a skill. As boas práticas oficiais alertam: pedir a um modelo uma skill “do nada” gera procedimentos genéricos (“siga as boas práticas”); o valor está no que é seu.Do the task once, with the agent, with no skill. Give context, correct the drift, state preferences. Then look at it: which steps worked, which corrections you made, what input and output format showed up. That is what becomes the skill. The official best practices warn: asking a model for a skill “out of thin air” yields generic procedures (“follow best practices”); the value is in what is yours.
- Crie a pasta e o arquivo. O nome da pasta é o nome da skill, e o arquivo chama-se
SKILL.mdexatamente assim, em maiúsculas.Create the folder and the file. The folder name is the skill name, and the file is calledSKILL.mdexactly like that, in capitals. - Escreva a descrição. É o campo mais importante (veja regras): o que a skill faz e quando usá-la, com as palavras que o usuário usaria.Write the description. It is the most important field (see rules): what the skill does and when to use it, with the words the user would use.
- Escreva o corpo como um procedimento: passos numerados, uma seção de armadilhas (gotchas), o modelo de saída. Curto: tudo que está lá fica no contexto enquanto a skill estiver ativa.Write the body as a procedure: numbered steps, a gotchas section, the output template. Keep it short: everything in it stays in context while the skill is active.
- Mova o que é longo ou raro para arquivos de apoio (
references/,assets/) e diga no corpo quando ler cada um. Ponha emscripts/o que precisa ser determinístico.Move what is long or rare into supporting files (references/,assets/) and say in the body when to read each one. Put inscripts/what must be deterministic. - Valide e teste (veja o laboratório): o formato com um linter, e o disparo com perguntas reais.Validate and test (see the lab): the format with a linter, and the triggering with real prompts.
Exemplo completo: uma skill de revisão de código. Estrutura:A complete example: a code review skill. Structure:
reviewing-code/
├── SKILL.md # obrigatório: metadados + procedimento
├── scripts/changed-files.sh # roda, não é lido: lista os arquivos alterados
└── references/security-checklist.md # só é lido se a mudança tocar em segurança
---
name: reviewing-code
description: Reviews a code change (a diff, branch or pull request) and reports findings ranked by severity. Use when the user asks to review code, a PR or a diff, or says "look over my changes", even if they never say "review".
---
# Reviewing code
## Steps
1. Get the change: run `scripts/changed-files.sh` and read every listed file in full, not only the diff lines.
2. Check in this order: correctness bugs, security, tests, readability.
- If the change touches authentication, input parsing, SQL, file paths or secrets, read `references/security-checklist.md` first.
3. Report with the template below. Do not edit files unless the user asks.
## Gotchas
- Lockfiles, `dist/` and generated code are not reviewed; say they were skipped.
- A missing test is a finding only if the changed behaviour is observable. Do not demand tests for renames.
- Never mark something "critical" without naming the input that triggers it.
## Output template
```markdown
## Summary
[one sentence: what the change does and your verdict]
## Findings
- **[critical|major|minor] file:line** — what is wrong, the input that triggers it, a suggested fix
## Not reviewed
[files skipped and why]
```
- A descrição diz o que faz (“revisa uma mudança e reporta por severidade”) e quando usar, inclusive quando o usuário não diz a palavra “review” (“olha as minhas mudanças”).The description says what it does (“reviews a change and reports by severity”) and when to use it, including when the user does not say the word “review” (“look over my changes”).
- Os passos dão uma ordem (bugs, segurança, testes, legibilidade) e um gatilho para o arquivo de apoio: “se a mudança toca autenticação, SQL, arquivos ou segredos, leia
references/security-checklist.md”. É melhor do que um genérico “veja references/”.The steps give an order (bugs, security, tests, readability) and a trigger for the supporting file: “if the change touches authentication, SQL, files or secrets, readreferences/security-checklist.md”. That beats a generic “see references/”. - As armadilhas são correções concretas (“lockfiles não se revisam”, “nunca marque como crítico sem dizer a entrada que dispara”). Sempre que você precisar corrigir o agente numa revisão, acrescente a correção aqui: é o jeito mais direto de melhorar uma skill.The gotchas are concrete corrections (“lockfiles are not reviewed”, “never mark critical without naming the triggering input”). Whenever you have to correct the agent in a review, add the correction here: it is the most direct way to improve a skill.
- O modelo de saída garante que toda revisão tenha o mesmo formato.The output template guarantees every review has the same format.
description: Cuts a release: bumps the version é inválido (“mapping values are not allowed here”): o segundo : abre um mapa. Reescreva sem dois-pontos ou ponha a descrição entre aspas. Foi um erro real que o linter da atividade 2 pegou ao montar os exemplos. Não verifiquei como cada agente reage a um YAML inválido (a documentação do Claude Code só afirma que campos não reconhecidos são ignorados sem erro), então valide antes de confiar que a skill foi carregada.Beware of colons in the description. The header is YAML, and description: Cuts a release: bumps the version is invalid (“mapping values are not allowed here”): the second : opens a map. Rewrite without a colon or put the description in quotes. It was a real mistake that the activity 2 linter caught while I built the examples. I did not check how each agent reacts to invalid YAML (the Claude Code documentation only states that unrecognised fields are ignored without an error), so validate before trusting that the skill was loaded.Onde ficam e o que cada agente acrescentaWhere they live and what each agent adds
O núcleo é o mesmo em todos: name e description obrigatórios, mais license, compatibility, metadata e allowed-tools (este experimental, com suporte variável). Muda onde cada agente procura as pastas e o que ele permite configurar além do núcleo:The core is the same everywhere: name and description required, plus license, compatibility, metadata and allowed-tools (the latter experimental, with varying support). What changes is where each agent looks for folders and what it lets you configure beyond the core:
| AgenteAgent | Onde procuraWhere it looks | Extras além do núcleoExtras beyond the core |
|---|---|---|
| Claude Code | ~/.claude/skills/ (pessoalpersonal), .claude/skills/ (projeto, vai no Gitproject, goes in Git), plugins, política da organização; também pastas aninhadas em monoreposplugins, organisation policy; also nested folders in monorepos | Campos como disable-model-invocation (só você chama), user-invocable (só o modelo chama), allowed-tools, context: fork (roda num subagente), paths (só carrega para certos arquivos), arguments e $ARGUMENTS; /nome chama na mão; blocos !`comando` rodam antes de o modelo ver a skill.Fields such as disable-model-invocation (only you call it), user-invocable (only the model calls it), allowed-tools, context: fork (runs in a subagent), paths (loads only for certain files), arguments and $ARGUMENTS; /name calls it by hand; !`command` blocks run before the model sees the skill. |
| Codex | .agents/skills/ no diretório atual e em cada pai até a raiz do repoin the current directory and each parent up to the repo root; ~/.agents/skills/; /etc/codex/skills/ (máquinamachine); skills do sistema (inclui o skill-creator)system skills (including skill-creator) | Arquivo opcional agents/openai.yaml: interface (nome e ícone no app), policy.allow_implicit_invocation: false (só dispara com $skill explícito) e dependencies.tools (servidores MCP exigidos). $skill-creator cria uma skill conversando.Optional agents/openai.yaml file: interface (name and icon in the app), policy.allow_implicit_invocation: false (fires only on an explicit $skill) and dependencies.tools (required MCP servers). $skill-creator creates a skill through conversation. |
| opencode | .opencode/skills/, ~/.config/opencode/skills/, e também lêand also reads .claude/skills/ eand .agents/skills/ (projeto e globalproject and global) | Só o núcleo (campos desconhecidos são ignorados). O controle fica em opencode.json: permission.skill com padrões allow / deny / ask (por exemplo "internal-*": "deny"), por agente.Only the core (unknown fields are ignored). Control lives in opencode.json: permission.skill with allow / deny / ask patterns (for example "internal-*": "deny"), per agent. |
| Hermes | ~/.hermes/skills/ (a fonte da verdadethe source of truth), skills.external_dirs no config.yamlin config.yaml; .hermes/skills/ ouor .agents/skills/ do projeto só depois de hermes skills trustof the project only after hermes skills trust | version, platforms, metadata.hermes.* (tags, categoria, ativação condicional por requires_toolsets / fallback_for_tools), required_environment_variables. Toda skill vira um comando /nome, e o próprio agente pode criar e remendar skills (skill_manage), com aprovação opcional.version, platforms, metadata.hermes.* (tags, category, conditional activation through requires_toolsets / fallback_for_tools), required_environment_variables. Every skill becomes a /name command, and the agent itself can create and patch skills (skill_manage), with optional approval. |
Dica de portabilidade: escreva a skill só com o núcleo da especificação, guarde-a em .agents/skills/ (que Codex, opencode e Hermes leem) e crie um symlink em .claude/skills/ para o Claude Code. As documentações do Claude Code e do Codex dizem expressamente que aceitam uma pasta de skill que seja symlink. O que for específico de um agente (disable-model-invocation, agents/openai.yaml, metadata.hermes) acrescente só quando precisar: os outros agentes ignoram campos que não conhecem (o opencode diz isso expressamente), mas a documentação do Claude Code avisa que empacotar uma skill para o claude.ai com campos fora do conjunto aberto falha.Portability tip: write the skill with only the specification's core, keep it in .agents/skills/ (which Codex, opencode and Hermes read) and create a symlink in .claude/skills/ for Claude Code. The Claude Code and Codex documentation both say they accept a skill folder that is a symlink. Add what is specific to one agent (disable-model-invocation, agents/openai.yaml, metadata.hermes) only when you need it: other agents ignore fields they do not know (opencode says so explicitly), but the Claude Code documentation warns that packaging a skill for claude.ai with fields outside the open set fails.
mkdir -p .agents/skills .claude/skills
cp -r reviewing-code .agents/skills/
ln -s ../../.agents/skills/reviewing-code .claude/skills/reviewing-code
name (as duas aparecem), e o opencode exige nomes únicos entre todos os locais. Como o opencode lê .claude/skills e .agents/skills, o symlink da dica acima pode fazer a mesma skill aparecer duas vezes lá. Se isso acontecer, é o primeiro lugar para olhar.Duplicate names. Codex does not merge skills with the same name (both appear), and opencode requires unique names across all locations. Since opencode reads .claude/skills and .agents/skills, the symlink in the tip above may make the same skill show up twice there. If that happens, it is the first place to look.Quando dividir uma skill em duas (ou juntar)When to split a skill in two (or merge)
A especificação compara a escolha ao desenho de uma função: uma skill deve ser uma unidade coerente de trabalho que se combina bem com as outras. Estreita demais, e várias skills precisam carregar para uma só tarefa, com custo de contexto e instruções que se contradizem. Larga demais, e fica difícil de ativar com precisão (o exemplo oficial: uma skill que consulta um banco e formata o resultado é uma unidade; se ela também faz administração do banco, está tentando fazer demais).The specification compares the choice to function design: a skill should be a coherent unit of work that composes well with the others. Too narrow, and several skills must load for a single task, costing context and giving contradicting instructions. Too broad, and it becomes hard to activate precisely (the official example: a skill that queries a database and formats the result is one unit; if it also does database administration, it is trying to do too much).
| SinalSignal | FaçaDo | ExemploExample |
|---|---|---|
| Dois gatilhos diferentesTwo different triggers A descrição virou uma lista de “e/ou” de intenções que não se parecem.The description became an “and/or” list of intents that do not resemble each other. | Divida por intenção.Split by intent. | reviewing-code (“olhe minhas mudanças”) e writing-functional-requirements (“o que isso deve fazer?”): o usuário pede coisas diferentes, em momentos diferentes.reviewing-code (“look at my changes”) and writing-functional-requirements (“what should this do?”): the user asks for different things, at different moments. |
| Risco ou permissão diferentesDifferent risk or permissions | Divida por risco.Split by risk. | reviewing-security só lê (allowed-tools: Read Grep); releasing-version publica e usa disable-model-invocation: true, para só rodar quando você pedir. Misturar as duas obrigaria a dar à revisão os poderes do release.reviewing-security only reads (allowed-tools: Read Grep); releasing-version publishes and uses disable-model-invocation: true, so it only runs when you ask. Mixing them would force giving the review the release's powers. |
| Quem chama é diferenteA different caller | Divida por modo de uso.Split by mode of use. | Um workflow que você dispara (/handoff) e um conhecimento que o modelo aplica sozinho (convenções de código) têm descrições e riscos diferentes.A workflow that you trigger (/handoff) and knowledge the model applies on its own (code conventions) have different descriptions and risks. |
| Corpo grande, mas uma só intençãoA big body, but one intent | Não divida a skill: divida o conteúdoDo not split the skill: split the content | Passe de 500 linhas? Mova o detalhe para references/ por tema (references/finance.md, references/sales.md) e diga no corpo quando ler cada um. A skill continua uma só.Past 500 lines? Move the detail into references/ by topic (references/finance.md, references/sales.md) and say in the body when to read each. The skill stays one. |
| Duas skills sempre carregam juntasTwo skills always load together | Junte.Merge. | Se formatting-report nunca roda sem querying-database, é uma unidade só.If formatting-report never runs without querying-database, it is a single unit. |
| Instruções que se contradizem entre skillsInstructions that contradict across skills | Junte, ou deixe uma delas fora do disparo automático.Merge, or take one out of automatic triggering. | Duas skills de “commit” com convenções diferentes: escolha uma e remova a outra, ou desligue o disparo automático de uma.Two “commit” skills with different conventions: pick one and remove the other, or turn off automatic triggering for one. |
Um teste rápido para a descrição: se você precisa de “e” para dizer quando usar a skill, e os dois lados do “e” não costumam aparecer na mesma conversa, provavelmente são duas skills. Se o “e” está no procedimento (consulta e formata), provavelmente é uma.A quick test for the description: if you need “and” to say when to use the skill, and the two sides of the “and” do not usually show up in the same conversation, they are probably two skills. If the “and” is in the procedure (queries and formats), it is probably one.
Skills por tema: o que muda em cada umaSkills by theme: what changes in each
O formato é o mesmo, mas o desenho muda com o tema. Duas perguntas orientam: quão frágil é a tarefa? (frágil pede passos exatos e scripts; flexível pede um critério e um modelo de saída) e qual o risco? (leitura apenas, ou ação com efeito). As boas práticas oficiais chamam o primeiro ponto de “calibrar o grau de liberdade”: uma ponte estreita com abismos dos dois lados pede instruções exatas; um campo aberto pede só a direção.The format is the same, but the design changes with the theme. Two questions guide it: how fragile is the task? (fragile asks for exact steps and scripts; flexible asks for a criterion and an output template) and what is the risk? (read only, or an action with effects). The official best practices call the first point “calibrating the degree of freedom”: a narrow bridge with cliffs on both sides calls for exact instructions; an open field only needs a direction.
| TemaTheme | O que a skill contémWhat the skill contains | LiberdadeFreedom | Risco e cuidadosRisk and cautions |
|---|---|---|---|
| Código e convençõesCode and conventions | Estrutura do projeto, comandos de build e teste, padrões de nomes, armadilhas do repositório (“o ID é user_id no banco e uid no auth”).Project structure, build and test commands, naming patterns, repository traps (“the ID is user_id in the database and uid in auth”). | MédiaMedium | Baixo. Mantenha curto: o que vale em toda tarefa vai no AGENTS.md; a skill é para tarefas específicas.Low. Keep it short: what holds in every task goes in AGENTS.md; the skill is for specific tasks. |
| Review | Ordem de verificação, o que ignorar (arquivos gerados), escala de severidade, modelo de saída. Exemplo da seção de criação.Order of checks, what to ignore (generated files), severity scale, output template. Example in the creation section. | Alta nos critérios, baixa no formatoHigh on criteria, low on format | Baixo se só reporta. Diga “não edite arquivos a menos que peçam”.Low if it only reports. Say “do not edit files unless asked”. |
| SegurançaSecurity | Pontos de entrada, o que cada um confia, o que verificar (validação, autenticação, injeção, segredos), e a regra de ouro: achado sem gatilho concreto é nota, não achado.Entry points, what each one trusts, what to check (validation, authentication, injection, secrets), and the golden rule: a finding with no concrete trigger is a note, not a finding. | Média, com formato fixoMedium, with a fixed format | Somente leitura: restrinja allowed-tools a leitura e busca, e diga “não altere, não rode, não use a rede”. A skill de segurança não deve ter poder de corrigir; separe a correção em outra.Read only: restrict allowed-tools to reading and search, and say “do not change, run or use the network”. The security skill must not have the power to fix; split the fix into another one. |
| Requisitos funcionaisFunctional requirements | Perguntas de esclarecimento (poucas), modelo de requisito numerado, critérios de aceitação Given/When/Then, lista de perguntas em aberto. Sem desenho nem código.Clarifying questions (few), numbered requirement template, Given/When/Then acceptance criteria, an open-questions list. No design or code. | Baixa no formato, alta no conteúdoLow on format, high on content | Baixo. O valor está nas proibições (“não proponha solução”, “não adivinhe respostas”) e no modelo em assets/.Low. The value is in the prohibitions (“do not propose a solution”, “do not guess answers”) and in the template in assets/. |
| TestesTests | Como rodar a suíte, onde ficam os testes, o padrão de nomes, o que mockar e o que nunca mockar.How to run the suite, where tests live, the naming pattern, what to mock and what never to mock. | MédiaMedium | Médio: rodar testes executa código. Liste os comandos permitidos, não “qualquer comando”.Medium: running tests executes code. List the allowed commands, not “any command”. |
| Release e deployRelease and deploy | Uma sequência exata, com verificação a cada passo e parada na primeira falha.An exact sequence, with a check at each step and a stop at the first failure. | Mínima: scripts e “rode exatamente isto”Minimal: scripts and “run exactly this” | Alto. Tem efeito no mundo: só você deve disparar (disable-model-invocation: true no Claude Code; allow_implicit_invocation: false no Codex) e sempre com confirmação.High. It has effects on the world: only you should trigger it (disable-model-invocation: true in Claude Code; allow_implicit_invocation: false in Codex) and always with confirmation. |
| Documentação e commitsDocs and commits | Formato (por exemplo Conventional Commits), tom, e exemplos de entrada e saída.Format (for example Conventional Commits), tone, and input and output examples. | Baixa no formatoLow on format | Baixo. Exemplos concretos ensinam o estilo melhor do que descrições.Low. Concrete examples teach the style better than descriptions. |
Dois exemplos testadosTwo tested examples
Requisitos funcionais. Repare nas proibições e no limite de perguntas, que impedem os dois erros típicos (interrogar demais e já sair desenhando):Functional requirements. Note the prohibitions and the question limit, which prevent the two typical mistakes (interrogating too much and starting to design right away):
---
name: writing-functional-requirements
description: Turns a feature idea into numbered functional requirements with acceptance criteria. Use when the user describes a feature, asks for requirements, a spec or user stories, or says "what should this do", before any code is written.
---
# Writing functional requirements
1. Ask at most five clarifying questions, only about things that change the behaviour (who, trigger, data, failure case, limits). If the user already answered, skip them.
2. Write each requirement as one observable behaviour, using the template in `assets/requirement-template.md`.
3. Give every requirement acceptance criteria in Given / When / Then form.
4. End with an "Open questions" list. Do not guess answers to them.
5. Do not propose a design, a database schema or code.
## Gotchas
- "Fast", "easy" and "secure" are not requirements until they have a number or a test.
- One requirement, one behaviour: split any requirement that contains "and".
Segurança, somente leitura. Os campos opcionais license, compatibility e allowed-tools da especificação deixam o limite explícito, e o corpo repete a regra em palavras, porque allowed-tools tem suporte variável entre agentes:Security, read only. The specification's optional license, compatibility and allowed-tools fields make the limit explicit, and the body repeats the rule in words, because allowed-tools has varying support across agents:
---
name: reviewing-security
description: Audits code or configuration for security weaknesses and reports them without changing anything. Use when the user asks for a security review, threat check, or whether something is safe to expose, or touches authentication, secrets, uploads or user input.
license: MIT
compatibility: Read-only. Needs only file reading and search; no network access.
allowed-tools: Read Grep
---
# Reviewing security
Report only. Never edit files, run the application or contact the network.
1. List the entry points (routes, handlers, CLI arguments, files read) and the data each one trusts.
2. For each, check: input validation, authentication and authorisation, secrets handling, injection (SQL, shell, path), and error messages.
3. Rank findings by exploitability: name the exact input or request that triggers each one. A finding without a trigger is a "note", not a finding.
4. End with what you could not check.
Note que ela repete a restrição no texto (“Report only. Never edit files…”). É um cinto e suspensório: o campo pede ao agente que restrinja as ferramentas, e o texto diz ao modelo o que fazer mesmo onde o campo não é respeitado. Nenhum dos dois é uma garantia (veja segurança).Note that it repeats the restriction in the text (“Report only. Never edit files…”). It is belt and braces: the field asks the agent to restrict tools, and the text tells the model what to do even where the field is not honoured. Neither is a guarantee (see security).
Regras que fazem uma skill funcionarRules that make a skill work
| RegraRule | Por quê, e comoWhy, and how |
|---|---|
| A descrição carrega o disparoThe description carries the trigger | É o único texto sempre carregado, e o agente decide por ela. Diga o que faz e quando usar, descreva a intenção do usuário (não a mecânica interna), liste contextos em que se aplica mesmo sem a palavra óbvia, e seja “insistente” sem passar de 1024 caracteres (no Claude Code, description e when_to_use juntos são cortados em 1536 na listagem: ponha o caso principal primeiro). Bom: “Extrai texto e tabelas de PDFs… Use quando o usuário mencionar PDFs, formulários ou extração de documentos.” Ruim: “Ajuda com PDFs.”It is the only text always loaded, and the agent decides by it. Say what it does and when to use it, describe the user's intent (not the internal mechanics), list contexts where it applies even without the obvious word, and be “pushy” without going past 1024 characters (in Claude Code, description and when_to_use together are truncated at 1,536 in the listing: put the main case first). Good: “Extracts text and tables from PDFs… Use when the user mentions PDFs, forms or document extraction.” Bad: “Helps with PDFs.” |
| Uma convenção de voz, mantidaOne voice convention, kept | As duas fontes oficiais divergem num detalhe: a especificação aberta sugere o imperativo (“Use esta skill quando…”); o guia da Anthropic pede terceira pessoa (“Processa arquivos Excel…”), porque a descrição é injetada no prompt do sistema. Escolha uma e use em todas as suas skills.The two official sources differ on one detail: the open specification suggests the imperative (“Use this skill when…”); Anthropic's guide asks for third person (“Processes Excel files…”), because the description is injected into the system prompt. Pick one and use it across all your skills. |
| Só o que o agente não sabeOnly what the agent does not know | Para cada trecho, pergunte: “o agente erraria sem isto?”. Se não, corte. Explicar o que é um PDF gasta contexto e não ajuda.For each piece, ask: “would the agent get this wrong without it?”. If not, cut it. Explaining what a PDF is costs context and does not help. |
| Padrões, não cardápiosDefaults, not menus | Escolha uma ferramenta e cite as alternativas em uma linha. “Use pdfplumber; para PDFs escaneados use pdf2image com pytesseract” funciona; uma lista de cinco bibliotecas iguais não.Pick one tool and mention the alternatives in a line. “Use pdfplumber; for scanned PDFs use pdf2image with pytesseract” works; a list of five equal libraries does not. |
| Procedimentos, não respostasProcedures, not answers | Ensine como abordar uma classe de problemas (leia o esquema, junte pelas chaves _id, filtre, agregue), não a resposta de um caso (“junte orders com customers…”).Teach how to approach a class of problems (read the schema, join on the _id keys, filter, aggregate), not the answer to one case (“join orders with customers…”). |
| Armadilhas dentro do SKILL.mdGotchas inside SKILL.md | São o conteúdo de maior valor: correções concretas a erros que o agente cometeria. Deixe no corpo, não num arquivo separado, porque o agente pode não reconhecer o momento de abrir o arquivo.They are the highest-value content: concrete corrections to mistakes the agent would make. Keep them in the body, not in a separate file, because the agent may not recognise the moment to open the file. |
| Validação e plano antes de agirValidation and a plan before acting | Em tarefas em lote ou destrutivas: gerar um plano, validar contra a fonte da verdade com um script que dá erro claro (“campo X não existe; disponíveis: …”), e só então executar. Para tarefas longas, uma lista de verificação que o agente marca.In batch or destructive tasks: generate a plan, validate it against the source of truth with a script that gives a clear error (“field X not found; available: …”), and only then execute. For long tasks, a checklist the agent ticks off. |
| Scripts que resolvemScripts that solve | O script trata os erros e diz o que fazer (como o changed-files.sh, que avisa “passe uma branch”) em vez de falhar e deixar o agente adivinhar. Diga se o agente deve rodar ou ler o script. Se você vê o agente reinventando a mesma lógica a cada execução, é hora de empacotar um script testado.The script handles errors and says what to do (like changed-files.sh, which says “pass a branch”) instead of failing and leaving the agent to guess. Say whether the agent should run or read the script. If you see the agent reinventing the same logic every run, it is time to bundle a tested script. |
| Arquivos a um nívelOne level of files | Link direto do SKILL.md a cada arquivo de apoio, sem cadeias (A aponta para B que aponta para C): o agente pode ler só o começo de arquivos aninhados. Arquivos com mais de 100 linhas ganham um sumário no topo. Nomes descritivos (form_validation_rules.md, não doc2.md) e barras normais nos caminhos.Link directly from SKILL.md to each supporting file, with no chains (A points to B which points to C): the agent may read only the start of nested files. Files over 100 lines get a table of contents at the top. Descriptive names (form_validation_rules.md, not doc2.md) and forward slashes in paths. |
| Nada que envelheceNothing that ages | Evite “antes de agosto use a API antiga”. Escreva o método atual e deixe o legado numa seção “padrões antigos”. Use um termo para cada conceito, sempre o mesmo.Avoid “before August use the old API”. Write the current method and leave the legacy in an “old patterns” section. Use one term per concept, always the same. |
| Nomes e tamanhoNames and size | Nome em minúsculas com hífens, igual à pasta, e descritivo (reviewing-code, não helper); o guia da Anthropic sugere o gerúndio. Corpo abaixo de 500 linhas e de cerca de 5000 tokens.Lowercase hyphenated name, equal to the folder, and descriptive (reviewing-code, not helper); Anthropic's guide suggests the gerund. Body under 500 lines and about 5,000 tokens. |
Segurança: uma skill é código que o agente executaSecurity: a skill is code the agent runs
Instalar uma skill é entregar ao agente instruções e, às vezes, scripts que ele vai seguir com o acesso que você já deu a ele. Uma skill de origem duvidosa pode mandar o agente ler segredos, rodar comandos ou enviar dados para fora, e o texto da skill é só mais um texto para o modelo obedecer. Os próprios agentes trazem controles; use-os:Installing a skill hands the agent instructions and sometimes scripts that it will follow with the access you already gave it. A skill of doubtful origin can tell the agent to read secrets, run commands or send data out, and the skill's text is just more text for the model to obey. The agents themselves ship controls; use them:
| AgenteAgent | Controle (segundo a documentação)Control (per the documentation) |
|---|---|
| Claude Code | Regras de permissão Skill(nome) e Skill(nome *) para permitir ou negar skills; disable-model-invocation para só você disparar; allowed-tools estreito (por exemplo Bash(git status *), não uma permissão ampla). Leia o allowed-tools das skills de um repositório antes de rodar o Claude Code nele, se você não confia no repositório. Os blocos !`comando` rodam antes de o modelo ver a skill, e a configuração disableSkillShellExecution os desliga.Skill(name) and Skill(name *) permission rules to allow or deny skills; disable-model-invocation so only you trigger; a narrow allowed-tools (for example Bash(git status *), not a broad grant). Read the allowed-tools of a repository's skills before running Claude Code in it, if you do not trust the repository. !`command` blocks run before the model sees the skill, and the disableSkillShellExecution setting turns them off. |
| Codex | policy.allow_implicit_invocation: false para só disparar por $skill; [[skills.config]] com enabled = false no config.toml para desligar uma skill.policy.allow_implicit_invocation: false so it only fires on $skill; [[skills.config]] with enabled = false in config.toml to turn a skill off. |
| opencode | permission.skill com allow, ask ou deny por padrão de nome; uma skill em deny fica escondida do agente; dá para desligar a ferramenta skill por agente.permission.skill with allow, ask or deny per name pattern; a skill set to deny is hidden from the agent; you can turn off the skill tool per agent. |
| Hermes | Skills de projeto (.hermes/skills, .agents/skills) só carregam depois de hermes skills trust; skills instaladas de um hub passam por um scanner (exfiltração, injeção de prompt, comandos destrutivos) e têm nível de confiança (builtin, official, trusted, community); com skills.write_approval: true, o que o agente escreve como skill fica numa fila de revisão (/skills pending, /skills approve).Project skills (.hermes/skills, .agents/skills) only load after hermes skills trust; skills installed from a hub pass through a scanner (exfiltration, prompt injection, destructive commands) and carry a trust level (builtin, official, trusted, community); with skills.write_approval: true, what the agent writes as a skill goes into a review queue (/skills pending, /skills approve). |
- Leia antes de instalar: o
SKILL.mdinteiro e cada script. Prefira origens conhecidas, fixe a versão (um commit) e guarde as suas skills no Git, para ver o que mudou.Read before installing: the wholeSKILL.mdand every script. Prefer known sources, pin the version (a commit) and keep your skills in Git, to see what changed. - Não ponha segredos numa skill. Ela é um arquivo de texto, lido pelo modelo e talvez compartilhado. Chaves vêm de variáveis de ambiente (o Hermes tem
required_environment_variablespara declarar quais a skill precisa, sem guardar o valor).Do not put secrets in a skill. It is a text file, read by the model and perhaps shared. Keys come from environment variables (Hermes hasrequired_environment_variablesto declare which ones the skill needs, without storing the value). - Instrução não é barreira. “Nunca apague arquivos” numa skill reduz a chance, mas não impede. O que precisa valer sempre vai fora do modelo: permissões, hooks e isolamento de rede. Veja a nota de harness (guardrails) e a nota de IA privada (camadas de autoridade).Instruction is not a barrier. “Never delete files” in a skill lowers the chance but does not prevent it. What must always hold goes outside the model: permissions, hooks and network isolation. See the harness note (guardrails) and the private AI note (layers of authority).
Praticar: criar, validar e testarPractise: create, validate and test
skills-ref.What I ran and what I did not. I created this note's four example skills and validated them with the activity 2 linter (real output below, including the colon error). I did not run the skills inside an agent: activity 3 (triggering) and the tuning ones are scripts for you to run in your own agent. The linter is mine and follows the open specification; the official validator is skills-ref.Atividade 0: criar a estruturaActivity 0: create the structure
mkdir -p skills/reviewing-code/{scripts,references}
mkdir -p skills/writing-functional-requirements/assets
mkdir -p skills/reviewing-security skills/releasing-version
# coloque em cada pasta o SKILL.md dos exemplos da nota (e os arquivos de apoio)
chmod +x skills/reviewing-code/scripts/changed-files.sh
Atividade 1: escrever uma skill suaActivity 1: write a skill of your own
Escolha uma tarefa que você repete (revisar, escrever commits, montar um relatório). Faça-a uma vez com o agente, anote as correções que você teve de fazer e escreva o SKILL.md com: descrição (o quê e quando), passos, armadilhas (suas correções) e um modelo de saída. Menos de 100 linhas é um bom começo.Pick a task you repeat (reviewing, writing commits, building a report). Do it once with the agent, note the corrections you had to make and write the SKILL.md with: a description (what and when), steps, gotchas (your corrections) and an output template. Under 100 lines is a good start.
Atividade 2: validar o formato (executada)Activity 2: validate the format (run)
Este linter (só biblioteca padrão e PyYAML) confere o que a especificação exige: nome, descrição, tamanhos, links de apoio.This linter (standard library and PyYAML only) checks what the specification requires: name, description, sizes, supporting links.
#!/usr/bin/env python3
"""Minimal Agent Skills linter (follows agentskills.io/specification). Not the official skills-ref."""
import re, sys, pathlib
import yaml
SPEC_FIELDS = {"name", "description", "license", "compatibility", "metadata", "allowed-tools"}
def lint(d):
errors, warns = [], []
f = d / "SKILL.md"
if not f.is_file():
return [f"{d}: SKILL.md not found (name it exactly SKILL.md)"], []
text = f.read_text()
m = re.match(r"---\n(.*?)\n---\n(.*)", text, re.S)
if not m:
return [f"{f}: frontmatter must start on line 1 between --- markers"], []
try:
fm = yaml.safe_load(m.group(1)) or {}
except yaml.YAMLError as e:
return [f"{f}: invalid YAML: {e}"], []
body = m.group(2)
name, desc = fm.get("name"), fm.get("description")
if not isinstance(name, str) or not re.fullmatch(r"[a-z0-9]+(-[a-z0-9]+)*", name) or len(name) > 64:
errors.append(f"name {name!r}: 1-64 chars, lowercase letters/digits, single hyphens, no leading/trailing hyphen")
elif name != d.name:
errors.append(f"name {name!r} must match the folder name {d.name!r}")
if not isinstance(desc, str) or not desc.strip():
errors.append("description: required and non-empty")
elif len(desc) > 1024:
errors.append(f"description: {len(desc)} chars, max 1024")
if "compatibility" in fm and not (isinstance(fm["compatibility"], str) and 1 <= len(fm["compatibility"]) <= 500):
errors.append("compatibility: 1-500 chars")
if "metadata" in fm and not (isinstance(fm["metadata"], dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in fm["metadata"].items())):
errors.append("metadata: must map strings to strings")
for k in fm.keys() - SPEC_FIELDS:
warns.append(f"field '{k}' is not in the open spec (fine if one agent uses it, ignored or rejected by others)")
if isinstance(desc, str) and not re.search(r"\b(use when|use this|when the user|use only when)\b", desc, re.I):
warns.append("description: no 'use when ...' trigger found (heuristic)")
if len(text.splitlines()) > 500:
warns.append(f"SKILL.md has {len(text.splitlines())} lines: keep under 500 (move detail to references/)")
for link in re.findall(r"\]\(([^)#]+)\)", body):
if not link.startswith(("http", "mailto")) and not (d / link).exists():
errors.append(f"link to '{link}' does not exist")
return errors, warns
bad = 0
for p in sys.argv[1:]:
d = pathlib.Path(p).resolve()
errs, warns = lint(d)
print(f"{'FAIL' if errs else 'ok '} {d.name}")
for e in errs: print(f" error: {e}")
for w in warns: print(f" warn: {w}")
bad += bool(errs)
sys.exit(1 if bad else 0)
$ python3 validate.py skills/*
ok releasing-version
warn: field 'disable-model-invocation' is not in the open spec (fine if one agent uses it, ignored or rejected by others)
ok reviewing-code
ok reviewing-security
ok writing-functional-requirements
$ python3 validate.py bad/Bad_Name # um exemplo deliberadamente errado
FAIL Bad_Name
error: name 'Bad_Name': 1-64 chars, lowercase letters/digits, single hyphens, no leading/trailing hyphen
error: link to 'docs/guide.md' does not exist
warn: field 'extra-field' is not in the open spec (fine if one agent uses it, ignored or rejected by others)
warn: description: no 'use when ...' trigger found (heuristic)
# e o erro real do dois-pontos, na descrição "Cuts a release: bumps the version ...":
FAIL releasing-version
error: ...SKILL.md: invalid YAML: mapping values are not allowed here
O aviso do disable-model-invocation é esperado: o campo é do Claude Code, não da especificação aberta. Para a verificação oficial, use o skills-ref validate ./minha-skill do repositório da especificação.The disable-model-invocation warning is expected: the field is Claude Code's, not the open specification's. For the official check, use skills-ref validate ./my-skill from the specification repository.
Atividade 3: testar o disparo (roteiro, não executada)Activity 3: test triggering (script, not run)
Uma skill só ajuda se for ativada. A orientação oficial é montar cerca de 20 perguntas reais, metade que devem disparar a skill e metade que não devem, e rodar cada uma algumas vezes (o modelo não é determinístico). As mais valiosas são as quase-erros: perguntas que compartilham palavras com a skill, mas pedem outra coisa. Exemplo para reviewing-code:A skill only helps if it is activated. The official guidance is to assemble about 20 real prompts, half that should trigger the skill and half that should not, and run each a few times (the model is not deterministic). The most valuable are the near-misses: prompts that share words with the skill but ask for something else. Example for reviewing-code:
[
{ "query": "can you look over my changes on the feat/login branch before I open the PR?", "should_trigger": true },
{ "query": "anything wrong with this diff? it's the retry logic in src/queue.ts", "should_trigger": true },
{ "query": "my manager wants a second pair of eyes on the payment PR, thoughts?", "should_trigger": true },
{ "query": "write a commit message for the staged changes", "should_trigger": false },
{ "query": "explain what this function does line by line", "should_trigger": false },
{ "query": "review the wording of this README paragraph", "should_trigger": false }
]
Rode cada pergunta no seu agente e veja se ele carregou a skill (no Claude Code, a chamada da ferramenta Skill aparece na saída; nos outros, veja o log de ferramentas). Separe cerca de 60% das perguntas para ajustar a descrição e 40% para conferir se o ajuste vale para perguntas novas, senão você ajusta a descrição às suas frases e ela falha nas dos outros. Se perguntas que deviam disparar não disparam, a descrição está estreita; se as quase-erros disparam, está larga. O repositório anthropics/skills traz uma skill skill-creator que automatiza esse ciclo.Run each prompt in your agent and see whether it loaded the skill (in Claude Code, the Skill tool call shows in the output; in the others, check the tool log). Set aside about 60% of the prompts to tune the description and 40% to check that the tuning holds for new prompts, otherwise you tune the description to your own phrases and it fails on other people's. If prompts that should trigger do not, the description is too narrow; if the near-misses trigger, it is too broad. The anthropics/skills repository ships a skill-creator skill that automates this loop.
Atividade 4: comparar com e sem a skill (roteiro)Activity 4: compare with and without the skill (script)
Rode a mesma tarefa real duas vezes, em sessões novas: sem a skill e com ela. Compare o resultado e o rastro (as ferramentas que o agente usou, não só a resposta final). Se a versão sem a skill já saiu boa, a skill não está agregando valor, e você pode apagá-la. Se o agente perde tempo, as instruções estão vagas, ou não se aplicam, ou oferecem opções demais sem um padrão. Cada correção que você fizer à mão vira uma linha na seção de armadilhas.Run the same real task twice, in fresh sessions: without the skill and with it. Compare the result and the trace (the tools the agent used, not just the final answer). If the version without the skill already came out well, the skill is not adding value, and you can delete it. If the agent wastes time, the instructions are vague, or do not apply, or offer too many options with no default. Each correction you make by hand becomes a line in the gotchas section.
Atividade 5: dividir e juntarActivity 5: split and merge
Junte reviewing-code e releasing-version numa única skill git-helper e observe o que acontece com a descrição (ela ganha um “e” entre intenções que não se parecem) e com o risco (a revisão herda o poder de publicar). Depois separe de novo. Em seguida, pegue uma skill sua com mais de 300 linhas e mova os trechos raros para references/, com um gatilho no corpo (“se o erro for X, leia references/x.md”).Merge reviewing-code and releasing-version into a single git-helper skill and watch what happens to the description (it gains an “and” between intents that do not resemble each other) and to the risk (the review inherits the power to publish). Then split them again. Next, take a skill of yours with over 300 lines and move the rare parts into references/, with a trigger in the body (“if the error is X, read references/x.md”).
Cola e revisãoCheat sheet and review
ColaCheat sheet
| AssuntoTopic | RegraRule |
|---|---|
| O que éWhat it is | Pasta com SKILL.md (YAML + Markdown). Padrão aberto; funciona em Claude Code, Codex, opencode e Hermes.A folder with SKILL.md (YAML + Markdown). Open standard; works in Claude Code, Codex, opencode and Hermes. |
| Como carregaHow it loads | Metadados sempre (~100 tokens) → corpo quando casa (< 500 linhas) → arquivos de apoio quando o corpo manda.Metadata always (~100 tokens) → body when it matches (< 500 lines) → supporting files when the body says so. |
| Frontmatter | name (1 a 64, minúsculas e hífens, igual à pasta) e description (1 a 1024). Opcionais: license, compatibility, metadata, allowed-tools. Cuidado com dois-pontos sem aspas.name (1 to 64, lowercase and hyphens, equal to the folder) and description (1 to 1024). Optional: license, compatibility, metadata, allowed-tools. Mind unquoted colons. |
| DescriçãoDescription | O que faz + quando usar + palavras do usuário; caso principal primeiro; uma convenção de voz.What it does + when to use it + the user's words; main case first; one voice convention. |
| CorpoBody | Passos, armadilhas, modelo de saída; só o que o agente não sabe; padrões, não cardápios.Steps, gotchas, output template; only what the agent does not know; defaults, not menus. |
| ApoioSupport | scripts/ (determinismo, roda sem ser lidodeterminism, runs without being read), references/ (lido sob demandaread on demand), assets/ (modelostemplates); a um nível do SKILL.md.one level from SKILL.md. |
| OndeWhere | Claude Code .claude/skills; Codex, opencode e Hermes .agents/skills; fonte única + symlink.Claude Code .claude/skills; Codex, opencode and Hermes .agents/skills; single source + symlink. |
| DividirSplit | Por intenção (gatilhos diferentes) e por risco (permissões diferentes). Tamanho se resolve com references/. Junte o que sempre carrega junto.By intent (different triggers) and by risk (different permissions). Size is solved with references/. Merge what always loads together. |
| TemasThemes | Review e segurança: só leitura. Requisitos: proibições e modelo. Release: passos exatos, só você dispara. Código: curto, o resto no AGENTS.md.Review and security: read only. Requirements: prohibitions and a template. Release: exact steps, only you trigger. Code: short, the rest in AGENTS.md. |
| TestarTest | Linter de formato; ~20 perguntas (metade quase-erros); repetir; separar treino e validação; comparar com e sem a skill.Format linter; ~20 prompts (half near-misses); repeat; split train and validation; compare with and without the skill. |
| SegurançaSecurity | Skill = instruções e scripts com o acesso do agente. Leia antes, fixe versão, sem segredos, e use os controles do agente; instrução não é barreira.A skill = instructions and scripts with the agent's access. Read first, pin the version, no secrets, and use the agent's controls; instruction is not a barrier. |
Perguntas de revisãoReview questions
- Em que uma skill difere do AGENTS.md, de uma ferramenta MCP e de um subagente? Dê um caso para cada.How does a skill differ from AGENTS.md, an MCP tool and a subagent? Give a case for each.
- O que são os três níveis da divulgação progressiva e por que a descrição é o campo mais importante?What are the three levels of progressive disclosure and why is the description the most important field?
- Reescreva a descrição “Ajuda com commits” para uma que diga o que faz e quando usar. Por que “Corta um release: sobe a versão” pode quebrar o YAML?Rewrite the description “Helps with commits” into one that says what it does and when to use it. Why can “Cuts a release: bumps the version” break the YAML?
- Uma skill tem 700 linhas e uma única intenção. Você a divide em duas skills? O que faz em vez disso?A skill has 700 lines and a single intent. Do you split it into two skills? What do you do instead?
- Por que
reviewing-securityereleasing-versiondevem ser skills separadas, mesmo que ambas mexam com “código”?Why shouldreviewing-securityandreleasing-versionbe separate skills, even though both touch “code”? - Como você escreveria uma skill de requisitos funcionais para impedir que o agente já proponha uma solução? E uma de segurança que só pode ler?How would you write a functional-requirements skill to stop the agent from proposing a solution right away? And a security skill that may only read?
- Como você montaria o teste de disparo de uma skill? O que são quase-erros e por que separar treino e validação?How would you set up the triggering test for a skill? What are near-misses and why split train and validation?
- Como guardar uma skill para Claude Code e Codex sem duplicar a pasta? O que você confere antes de instalar uma skill de terceiros?How do you store a skill for Claude Code and Codex without duplicating the folder? What do you check before installing a third-party skill?
- Agent Skills: specification · Best practices for skill creators · Optimizing skill descriptions · Evaluating skill output quality
- Claude Code: extend Claude with skills · Anthropic: skill authoring best practices · anthropics/skills (
skill-creator) - Codex: agent skills (redireciona para a documentação de skills da OpenAIredirects to OpenAI's skills documentation) · opencode: agent skills · Hermes Agent: skills system