---
title: "Skills"
description: "Author load-on-demand procedures the model pulls into context with load_skill."
---

A skill is a model-loadable procedure that follows the `SKILL.md` convention. It is a markdown document, optionally a packaged directory with supporting files, that the model pulls into context on demand rather than carrying on every turn. eve advertises each skill's description, and the model loads the full body only when a turn calls for it. This is progressive disclosure, the same model the broader Agent Skills standard uses, so a skill authored against that standard ports over as-is.

## How loading works

eve scans the files under `agent/skills/` and exposes each one's description to the model alongside a framework-owned `load_skill` tool. When a request matches a skill's description (or you name the skill outright), the model calls `load_skill`, and eve appends that skill's markdown to the active turn's context.

The description is a routing hint, not a label. Write it as the task that should trigger activation:

```md
Use when the user needs a release checklist or changelog workflow.
```

Loading a skill adds instructions, never a new execution surface. Tools stay visible whether a skill is loaded or not. If you need typed runtime behavior, reach for a [tool](./tools) instead.

## Markdown vs `defineSkill`

The smallest skill is a flat markdown file. The content is the procedure, and the name comes from the path.

```md title="agent/skills/forecast.md"
Use the weather tool before answering forecast or temperature questions.
```

A flat markdown skill can skip the `description` frontmatter. When it does, eve advertises the first non-empty, non-code-fence line of the body with any leading `#`, `>`, `*`, or `-` marker stripped. If the body has no such line, eve falls back to the literal `Instructions for the <name> skill.`, which is a weak routing hint, so add a `description` when you want the model to route on intent.

A packaged skill is a directory with a `SKILL.md` plus sibling files like `references/`, `assets/`, and `scripts/`. The packaged `SKILL.md` must carry `description` frontmatter; it has no filename slug to fall back on.

```md title="agent/skills/research/SKILL.md"
---
description: Research unfamiliar topics before answering with confidence.
---

When the task is novel or ambiguous, gather evidence first, then answer with the
key facts and the remaining uncertainty.
```

When markdown can't express what you need (typed values, generated content, or inline sibling files), author the skill in TypeScript with `defineSkill` from `eve/skills`:

```ts title="agent/skills/research.ts"
import { defineSkill } from "eve/skills";

export default defineSkill({
  description: "Research unfamiliar topics before answering with confidence.",
  markdown:
    "When the task is novel or ambiguous, gather evidence first, then answer with the key facts and the remaining uncertainty.",
  files: {
    "references/checklist.md": "# Checklist\n\n- Find primary sources.\n",
  },
});
```

eve generates `SKILL.md` from `markdown`, and each `files` entry becomes a package-relative sibling. Start with plain markdown and move to `defineSkill` only when you hit its limits.

## Skills are scoped per agent

Skills are scoped to the agent that declares them. A [subagent](./subagents)'s `skills/` are invisible to the root agent, and the reverse holds too. There's no shared-skill mechanism, so put shared executable helpers in `lib/`.

## Read skill files at runtime

Loading a skill adds its `SKILL.md` to context. To reach a packaged skill's sibling files (references, assets, scripts) from inside a tool or hook, use `ctx.getSkill(id)`:

```ts
const research = ctx.getSkill("research");
const checklist = await research.file("references/checklist.md").text();
```

The handle exposes the skill's `name` and `file(relativePath)`; file content is read lazily from the active sandbox.

## Dynamic skills

To serve a different skill per principal, tenant, or channel (the caller's own team playbook, say), wrap `defineSkill` in a `defineDynamic` resolver keyed on `ctx.session.auth`. See [Dynamic capabilities](./guides/dynamic-capabilities).

## What to read next

- [Connections](./connections): add tools from external MCP and OpenAPI servers
- [Dynamic capabilities](./guides/dynamic-capabilities): resolve skills per caller with `defineDynamic`
- [Context control](./concepts/context-control): how skills fit the full context model
