# Skills model

> Skills as importable Python packages, SKILL.md frontmatter constraints, collision precedence, and project vs personal skill scope.

- Repository: PrimeIntellect-ai/prime-agent
- GitHub: https://github.com/PrimeIntellect-ai/prime-agent
- Human docs: https://grok-wiki.com/public/docs/primeintellect-ai-prime-agent-3367c32760b1
- Complete Markdown: https://grok-wiki.com/public/docs/primeintellect-ai-prime-agent-3367c32760b1/llms-full.txt

## Source Files

- `packages/coding-agent/skills/skill-creator/SKILL.md`
- `packages/coding-agent/examples/sdk/04-skills.ts`
- `packages/coding-agent/test/fixtures/skills/valid-skill/SKILL.md`
- `packages/coding-agent/test/suite/regressions/2781-skill-collision-precedence.test.ts`
- `packages/coding-agent/skills/edit/SKILL.md`
- `packages/coding-agent/skills/edit/src/edit/__init__.py`

---

---
title: "Skills model"
description: "Skills as importable Python packages, SKILL.md frontmatter constraints, collision precedence, and project vs personal skill scope."
---

Skills in Prime Agent are directories with a required `SKILL.md` (YAML frontmatter plus markdown instructions). At startup the runtime loads only each skill’s `name` and `description` into the system prompt; the full body loads on demand when a task matches. Discovery and merge run through `DefaultResourceLoader` (`reload()` / `getSkills()`), which returns resolved `Skill` records and collision or load diagnostics. Prime Agent follows the [Agent Skills standard](https://agentskills.io/specification) and extends it with Python-backed skills installed into the agent’s persistent IPython kernel.

## Skill kinds

| Kind | Shape | Use when |
|---|---|---|
| **markdown** | `SKILL.md` plus optional `scripts/`, `references/`, `assets/` | Workflows, CLI recipes, domain knowledge, multi-step instructions |
| **python** | Same markdown skill **plus** a Python package installed into the persistent IPython kernel | Capabilities that are naturally one call: `await my_skill(...)` — API wrappers, fetchers, converters, computations |

Default to markdown. Use Python only when the agent should **call** the capability from the kernel rather than follow instructions.

## Scope and install locations

| Scope | Path | Typical use |
|---|---|---|
| **Project** | `.prime/agent/skills/<name>/` | Shared via the repo |
| **Personal (global)** | `~/.prime/agent/skills/<name>/` | User-wide skills |
| **Package** | Package `skills/` directory, or paths listed under `pi.skills` in that package’s `package.json` | Skills shipped with an npm package |

Package skills are wired through settings: a `settings.json` under the user agent dir or project `.prime/agent/` may list package roots in a `packages` array. The package’s `package.json` can declare skill paths with `pi: { skills: ["skills/<name>"] }`.

## Layout

```
my-skill/
├── SKILL.md              # Required: frontmatter + instructions
├── scripts/              # Optional helper scripts referenced by instructions
├── references/           # Optional detail docs (load only when needed)
└── assets/               # Optional templates and data files
```

Only `SKILL.md` is required; everything else is freeform. Paths in the body are relative to the skill directory (the directory that contains `SKILL.md`).

## SKILL.md frontmatter

```markdown
---
name: my-skill
description: What this skill does and when to use it. Be specific.
---
```

| Field | Required | Rules |
|---|---|---|
| `name` | Yes | Max 64 chars. Lowercase `a-z`, `0-9`, hyphens. No leading, trailing, or consecutive hyphens. Must match the parent directory name. |
| `description` | Yes | Max 1024 chars. **Missing or empty description → skill is silently not loaded.** |
| `disable-model-invocation` | No | `true` hides the skill from the system prompt; only explicit `/skill:<name>` invokes it. |
| `license` | No | License name or reference to a bundled file. |
| `compatibility` | No | Max 500 chars. Environment requirements. |
| `metadata` | No | Arbitrary key-value mapping. |
| `allowed-tools` | No | Space-delimited pre-approved tools (experimental). |

Unknown fields are ignored. Name rule violations produce **warnings** but the skill still loads. Description emptiness is the hard load gate.

### Description as routing surface

The description is the only text the model sees before deciding to load the skill. State **what** the skill does **and** **when** to use it (trigger conditions, concrete tasks, tools, phrases).

- Good: `Extracts text and tables from PDF files, fills PDF forms, and merges PDFs. Use when working with PDF documents.`
- Poor: `Helps with PDFs.`

### Body and progressive disclosure

Keep `SKILL.md` short: decision flow, common commands, contract. Put exhaustive detail (schemas, long option lists, large examples) in `references/*.md` and link them so they enter context only when needed. State setup (installs, env vars, credentials) early and explicitly.

## Collision precedence

On a name collision, **the first skill found wins**. Effective precedence (highest first):

1. Explicit `--skill` paths and `skills` settings entries  
2. **Project** skills (`.prime/agent/skills/`)  
3. **User / global** skills (`agentDir/skills/`, typically `~/.prime/agent/skills/`)  
4. **Package** skills (via `packages` + package `pi.skills`)  
5. **Built-in** skills  

Regression coverage for this order (`DefaultResourceLoader`):

| Scenario | Winner |
|---|---|
| Same name on user auto-discovered skill and package skill | User skill |
| Same name on project skill and package skill | Project skill |
| Same name on project, user, and package | Project skill |

When a collision occurs, `loader.getSkills().diagnostics` can include a diagnostic with `type: "collision"` and `collision.name` / `collision.loserPath` (for example the package skill path loses when a user skill wins).

```text
  load order / precedence (winner = first match for a name)
  ─────────────────────────────────────────────────────────
  explicit --skill / settings.skills
            │
            ▼
  project  .prime/agent/skills/<name>/
            │
            ▼
  user     <agentDir>/skills/<name>/
            │
            ▼
  package  packages[] + package.json pi.skills
            │
            ▼
  built-in
```

## Runtime and SDK surface

### Discovery and override

`DefaultResourceLoader` is constructed with `cwd` and `agentDir`, then `await loader.reload()`. `loader.getSkills()` returns `{ skills, diagnostics }`.

SDK configuration can filter or replace the discovered set via `skillsOverride`:

```ts
const customSkill: Skill = {
  name: "my-skill",
  description: "Custom project instructions",
  filePath: "/virtual/SKILL.md",
  baseDir: "/virtual",
  sourceInfo: createSyntheticSourceInfo("/virtual/SKILL.md", { source: "sdk" }),
  disableModelInvocation: false,
  kind: "markdown",
};

const loader = new DefaultResourceLoader({
  cwd: process.cwd(),
  agentDir: getAgentDir(),
  skillsOverride: (current) => {
    const filteredSkills = current.skills.filter(
      (s) => s.name.includes("browser") || s.name.includes("search"),
    );
    return {
      skills: [...filteredSkills, customSkill],
      diagnostics: current.diagnostics,
    };
  },
});
await loader.reload();
const { skills: allSkills, diagnostics } = loader.getSkills();
```

Pass the loader into `createAgentSession({ resourceLoader: loader, ... })` so the session uses the merged skill set.

### Skill record fields (SDK)

| Field | Role |
|---|---|
| `name` | Skill id (matches frontmatter / directory) |
| `description` | Routing text in the system prompt |
| `filePath` | Path to `SKILL.md` (or synthetic path for inline skills) |
| `baseDir` | Skill root directory |
| `sourceInfo` | Provenance (`createSyntheticSourceInfo` for SDK-defined skills) |
| `disableModelInvocation` | Mirrors frontmatter `disable-model-invocation` |
| `kind` | e.g. `"markdown"` |

## Python-backed skill contract (example: `edit`)

Shipped python skills keep the same `SKILL.md` surface and add a package entry that the kernel can call. Example: `packages/coding-agent/skills/edit/`.

**Frontmatter (`edit/SKILL.md`):**

```yaml
---
name: edit
description: Replace an exact, unique string in an existing file. Use for targeted single-occurrence edits to files from the IPython kernel instead of rewriting the whole file.
---
```

**Callable API** (`edit/src/edit/__init__.py`):

```python
async def run(path: str, old_str: str, new_str: str) -> str:
    ...
```

| Input / output | Behavior |
|---|---|
| `path` | Relative, absolute, or `~`-prefixed (home expanded) |
| `old_str` | Must occur **exactly once**; else `ValueError` |
| `new_str` | Replacement text |
| Success | Returns short confirmation (e.g. `Edited <resolved_path>`); may stream a diff via MIME `application/vnd.prime-agent.diff+json` |
| Missing file | `FileNotFoundError` |
| 0 or &gt;1 matches | `ValueError` |

Invocation from the kernel (documented on the skill):

```python
await edit(path="pkg/file.py", old_str=old, new_str=new)
```

Or shell-style: `!edit --path pkg/file.py --old-str "..." --new-str "..."`.

## Load, reload, and verification

| Signal | Meaning |
|---|---|
| Startup | Name + description only in system prompt; body on demand |
| Interactive `/reload` | Picks up new or changed skills without full process restart |
| Other sessions | Pick up skills on start |
| `/skill:<name>` | Explicit invoke (required when `disable-model-invocation: true`) |
| Empty / missing description | Skill **not loaded** (silent) |
| Name rule break | Warning; skill still loads |
| Name collision | Winner per precedence; diagnostics may record loser path |
| `getSkills().diagnostics` | Load warnings and collisions for tooling or user inspection |

Verification checklist after authoring:

1. Frontmatter rules, especially `name` ≡ directory name and non-empty `description`.  
2. Reload or new session; inspect warnings / diagnostics for bad names, missing descriptions, collisions.  
3. Optional direct invoke: `/skill:<name>`.  
4. For Python-backed skills, also satisfy the package install / callable checks described in skill-creator’s `references/python-skills.md` (create flow).

## Settings touchpoints

| Surface | Role |
|---|---|
| User `settings.json` under `agentDir` | e.g. `{ "packages": ["<pkgDir>"] }` to attach package skill roots |
| Project `.prime/agent/settings.json` | Same `packages` pattern at project scope |
| Package `package.json` → `pi.skills` | Relative skill paths inside the package (e.g. `skills/web-fetch`) |
| Explicit `skills` settings / `--skill` | Highest precedence sources |

Skill packs remain **file, repository, or catalog sources**—not tied to a particular model provider. Provider auth and model selection are separate from skill discovery and collision.

## Failure modes

| Symptom | Likely cause | What to check |
|---|---|---|
| Skill never appears | Empty/missing `description` | Frontmatter; silent skip |
| Unexpected skill body | Name collision | Project vs user vs package; diagnostics `type: "collision"` |
| Model never loads skill | `disable-model-invocation: true` | Invoke with `/skill:<name>` |
| Name warnings | Frontmatter `name` ≠ dir or invalid charset | Fix name; skill may still load |
| Package skill ignored | Missing `packages` entry or wrong `pi.skills` path | User/project `settings.json` and package `package.json` |

## Related pages

<CardGroup>
  <Card title="Create and install skills" href="/create-skills">
    Author a skill package with skill-creator, required SKILL.md fields, Python package layout, and load-path verification.
  </Card>
  <Card title="Built-in skills reference" href="/builtin-skills">
    Catalog of shipped skills (goal, refine, compact, heartbeat, observe, message, edit, integrations) with entry modules and invocation roles.
  </Card>
  <Card title="Skills, tools, and extensions (SDK)" href="/sdk-skills-tools-extensions">
    SDK recipes for loading skills, registering tools, extensions, context files, prompt templates, and subagent extension wiring.
  </Card>
  <Card title="Continual Harness" href="/continual-harness">
    Durable harness state including skill specs, refine boundaries, and rollback snapshots.
  </Card>
  <Card title="RLM control plane" href="/rlm-control-plane">
    Persistent IPython as the control tool and how kernel-callable Python skills fit the control plane.
  </Card>
  <Card title="Extensions and custom tools" href="/extensions">
    Register extensions and custom tools alongside skills for broader capability surfaces.
  </Card>
</CardGroup>
