Skills
Markdown instruction sets that agents load on demand. The index stays in the system prompt; full content is loaded only when the LLM asks for it.
A skill is a Markdown instruction set with a name and description. You give an agent ten of them, only the index goes into the system prompt, and the LLM loads the full text of the one or two it actually needs via a tool call. Loaded content is then promoted into the system prompt as authoritative instruction.
Skills follow the skills.sh community format, so a SKILL.md you write works in both Crux agents and Claude Code.
Why Skills
A capable agent often needs many specialized instruction sets — SEO analysis, research methodology, brand voice, legal review, code style — and most tasks need only one or two of them. Pasting all of them into the system prompt is wasteful: the model pays for tokens it will not use, and the relevant instructions get diluted by the rest.
Skills solve this in three steps:
- Index in the prompt. A short list of
name: descriptionpairs is auto-generated and added to the system prompt. - Load on demand. The LLM sees the index, picks what it needs, and calls
LoadSkill(name). - Promote to system. The loaded content is re-injected at the system prompt level — not returned as a tool result — so it carries the same authority as your hand-written instructions.
The result: a 10-skill agent costs ~10 lines of index upfront, and only pays for the skills the model actually loads.
Quick Start
import { skill, skillsSh } from '@crux/core/skill'
import { prompt, agent, context } from '@crux/core'
// Inline — useful for short, app-specific instructions
const tone = skill.inline({
id: 'tone',
description: 'Writing voice and tone guidelines',
instructions: 'Always write in a warm professional tone. Avoid jargon unless the user uses it first.',
})
// From a SKILL.md file on disk
const seo = skill.fromFile('./skills/seo-analysis/SKILL.md')
// From the skills.sh community registry
const research = skill.fromRegistry(skillsSh, 'mattpocock/skills/research-synthesis')
// Drop them into a prompt's `use` array — same as contexts
const reviewer = agent({
prompt: prompt({
id: 'reviewer',
use: [tone, seo, research, context({ id: 'base', system: 'You review marketing content.' })],
system: '',
}),
})That is the entire integration for adapter-based agents (@crux/anthropic, @crux/openai, @crux/google, @crux/ai). The index, the LoadSkill/LoadReference tools, and the re-resolution loop are all wired up by the resolver.
How It Works Under the Hood
When you place skills in a prompt's use array, the resolution pipeline does four things:
1. Generates a skill index context (priority 90, near the top of the system prompt):
## Skills
You have access to skills — loadable instruction sets.
### Available Skills
- **seo-analysis**: Analyze and optimize content for search engines
- **tone**: Writing voice and tone guidelines
### How to Use
- LoadSkill(name) — Load a skill's full instructions
- LoadReference(skillName, referenceName) — Load reference material2. Injects two tools into the resolved tool set: LoadSkill and LoadReference.
3. Intercepts LoadSkill mid-loop. When the model calls it, the executor:
- Re-resolves the prompt with the skill's full instructions appended to the system prompt
- Continues the tool loop with the new system prompt
- Does not count this against
maxSteps
The skill content arrives as authoritative system context, not as a tool result the model might second-guess.
4. Returns reference content as tool results. LoadReference(skillName, refName) is treated as supplementary information — it stays in the tool-result channel rather than being promoted to the system prompt.
Adapter Support
| Adapter | How it works | Setup |
|---|---|---|
@crux/anthropic, @crux/openai, @crux/google | Executor intercepts LoadSkill mid-loop and re-resolves the system prompt | Add skills to use |
@crux/ai (Vercel AI SDK) | wrapGenerate middleware injects newly activated skills between steps | Add skills to use |
| Convex Agent, Mastra, custom loops | createAgentSkillKit() with a skill activation persistence port — see Agent Frameworks | Store/load SkillActivationSnapshot |
The Escape Hatch
If you want the raw skill text without the skill system, call .dump():
const ctx = context({
id: 'seo-inline',
system: `SEO guidelines:\n${seo.dump()}`,
})This exits the skill system entirely — no index entry, no LoadSkill tool, no re-resolution. Reach for it when you want full control over how a single skill's content is presented, or when you genuinely want a skill always in the system prompt.
Where to Next
Writing skills
SKILL.md format, frontmatter, and how to structure references.
Registries
Use skills.sh, host your own registry, or load from disk.
Agent framework integration
createAgentSkillKit() for Convex Agent, Mastra, and custom tool loops.
API reference
@crux/core/skill — full type signatures and instrumentation hooks.