How to create and test a Claude Agent Skill from scratch (and what breaks when you reuse it)
Anthropic turned reusable knowledge into directories with SKILL.md. The step by step to package it, install it in Claude Code and understand why the same Skill doesn't run the same way on the API.

Anthropic has been pushing a specific format to solve an annoying problem for anyone building with agents: how to stop repeating the same instructions, workflows and references in every conversation. The answer is Agent Skills, documented in Anthropic's official material. In practice, a Skill is just a directory with a SKILL.md file and, optionally, scripts and reference files. No magic: it's filesystem.
What makes this interesting for anyone already working with RAG and giant prompts is the progressive disclosure mechanism. Instead of dumping all the context at once, Claude loads information in layers, as it needs it. I'll show how to put together a working Skill, test it locally in Claude Code and, most importantly, what changes (and what gets stuck) when you try to take the same Skill to the API.
The three layers that define the context cost
The central point of the architecture is that each type of content enters the context window at a different moment. The documentation sums it up like this:
| Layer | When it loads | Token cost | Content | |---|---|---|---| | Metadata | Always, at startup | ~100 tokens per Skill | name and description from the YAML | | Instructions | When the Skill is triggered | Under 5k tokens | Body of SKILL.md | | Resources and code | On demand | Zero until accessed | Referenced files, scripts via bash |
In practice this means you can install dozens of Skills without paying a context toll: as long as a Skill isn't triggered, only the name and the description take up space. This is where the format beats the approach of stuffing everything into the system prompt.
The detail that makes a difference: scripts never enter the context. When Claude runs a validate_form.py via bash, only the script's output ("Validation passed" or an error message) consumes tokens. The code itself stays on disk. For deterministic operations, this is more reliable and cheaper than asking the model to generate the code on the spot.
Writing the SKILL.md
Every Skill needs a SKILL.md with YAML frontmatter. The minimum structure is this:
---
name: pdf-processing
description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction.
---
# PDF Processing
## Quick start
Use pdfplumber to extract text from PDFs:import pdfplumber
with pdfplumber.open("document.pdf") as pdf: text = pdf.pages[0].extract_text()
For advanced form filling, see FORMS.md.The field that matters most is description. It's what Claude compares against the user's request to decide whether to trigger the Skill. That's why the documentation insists: the description needs to say what the Skill does and when to use it. A vague description ("processes files") will make the Skill never fire or fire at the wrong time. The rules for name are strict: maximum 64 characters, only lowercase letters, numbers and hyphens, and it can't contain the reserved words "anthropic" or "claude".
When the Skill grows, you break the knowledge into separate files inside the directory:
pdf-processing/
SKILL.md (main instructions)
FORMS.md (form filling guide)
REFERENCE.md (detailed API reference)
scripts/
fill_form.py (utility script)The trick is that FORMS.md is only read if the task involves forms. If the user only wants to extract text, Claude runs cat pdf-processing/SKILL.md, sees that it doesn't need forms and never touches FORMS.md. Zero wasted tokens.
Testing locally in Claude Code
Here's the good part for anyone already using Claude Code: custom Skills are filesystem-based and require no upload. You just put the directory in the right place:
# Personal Skill, available in any project
mkdir -p ~/.claude/skills/pdf-processing
# Project Skill, versioned along with the repository
mkdir -p .claude/skills/pdf-processingMove your SKILL.md (and the auxiliary files) into that folder and Claude Code discovers and uses it automatically. There's no registration command, there's no API call. To check whether it's working, the path I would follow is to make a request that matches the description exactly and watch whether Claude runs the cat of SKILL.md in the middle of its reasoning: that's the sign that the instructions layer was triggered.
The distinction between ~/.claude/skills/ (personal) and .claude/skills/ (project) is useful in practice: putting the Skill in the repository means that everyone on the team inherits the same knowledge when cloning, with no manual setup. It's the cleanest way to distribute versioned organizational context.
What breaks when you reuse across surfaces
Here lies the catch this story is meant to expose. Skills don't sync across surfaces. The same directory that runs smoothly in Claude Code may simply not behave the same way on the API, and for concrete reasons, not because of a bug.
The first problem is distribution. The documentation is explicit:
Skills uploaded to one surface are not automatically available on others.
In practice:
- A Claude Code Skill lives in the filesystem and is separate from the API and from claude.ai.
- An API Skill has to be sent through the
/v1/skillsendpoints and is shared across the entire workspace. - A claude.ai Skill is sent as a zip via Settings > Features and is individual per user, with no centralized admin management.
In other words: if you developed and tested in Claude Code, taking it to the API is a new upload, not a folder copy and paste.
The second problem, more treacherous, is the execution environment. A Skill that depends on the network or on installing packages will break on the API even after being installed correctly. Compare:
| Restriction | Claude Code | Claude API | |---|---|---| | Network access | Full (like any program on the machine) | None: no external calls | | Installing a package at runtime | Allowed (locally, with caveats) | Blocked | | Dependencies | Whatever is on the machine | Only packages pre-installed in the container |
This is the concrete "it broke" case: a Skill that, in Claude Code, does a pip install of a lib or fetches data from an external URL works because it has the same network permission as any local process. On the API, the same Skill runs in a sandboxed container, with no network and no runtime installation, so the script that was downloading something or installing a dependency fails silently or throws an error. Anthropic's own recommendation is to plan the Skill to fit within these restrictions from the start, and not find out at deploy time.
When it isn't worth it
A Skill doesn't replace a prompt for a one-off task. If you're going to ask for something only once, the documentation makes it clear that the Skill's advantage (loading on demand, without repetition) disappears, and a direct prompt solves it with less ceremony. A Skill pays off when the same knowledge repeats across conversations or across team members.
And there's the security side, which isn't a detail. A Skill gives Claude new capabilities via instructions and code, which means a malicious Skill can direct the model to execute things outside its stated purpose: data exfiltration, unauthorized access, unexpected network calls. The guidance is to treat it like installing software: only use Skills that you wrote or obtained from Anthropic, and audit every file in the package, including scripts and resources, before running it in production with access to sensitive data.
For those building in Brazil, the practical take is this: the Skill format is the cheapest way (in tokens) to give an agent durable specialization, and the test cycle in Claude Code is immediate because it's just filesystem. But the portability bar is low, so design the Skill already knowing which surface it will live on, and resist the temptation to depend on the network if the destination is the API. The complete examples are in the Skills cookbook and in Anthropic's open-source Skills repository, including the Claude API skill that already ships built into Claude Code.
Translated from the Brazilian Portuguese original · Read the original
Convex Agent Component: how native memory and RAG work for AI agents
Convex's official component bundles threads, persistent memory, and hybrid vector/text search for those building AI agents, without setting up a parallel vector DB stack.
