> ## Documentation Index
> Fetch the complete documentation index at: https://docs.decimal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Skills

> Sync skill files from disk to platform, pull missing skills, and route to the right skill at runtime.

Skills are the unit of reusable agent knowledge in DecimalAI. The SDK has two flows: **sync** (push your local `SKILL.md` files to the platform during `install()`) and **pull** (download platform skills to disk).

At runtime, the [**Skill Router**](/api-reference/skills/router) is what your agent talks to — it picks which skills to load on every query and emits the telemetry that powers per-skill effectiveness. This page covers the SDK surface; the [Router page](/api-reference/skills/router) covers strategies, response shape, and the routing-id → trace join.

***

## Sync skills from code to platform

```python theme={null}
from decimalai.openai_agents import install

install(
    agent=agent,
    skill_dirs=["./skills/"],  # scans for SKILL.md files
)
# Skills are auto-synced to platform on install()
```

The `skill_dirs` argument is supported by all framework `install()` calls — OpenAI Agents, LangChain, LlamaIndex, etc.

***

## Pull skills from platform to disk

```python theme={null}
from decimalai import SkillRouter

router = SkillRouter(api_key="dai_sk_...", base_url="https://api.decimal.ai")
result = router.pull_missing(
    local_skill_names={"existing_skill"},
    agents=["my-agent"],
)
print(f"Pulled {result['pulled']} new skills")
```

### Pull a public skill — no signup required

For consumers who just want to read a published skill without forking it
into an org, the CLI's `pull` command works against the public registry
endpoint with no auth:

```bash theme={null}
# Writes ./code-review-security/SKILL.md
decimalai skills pull code-review-security

# Or print to stdout for piping into another tool
decimalai skills pull pdf --stdout > pdf.md
```

`pull` is read-only — no fork is created, no activation telemetry is
recorded. Use `install()` (Python) once you sign up to get the full
lifecycle. In the SDK, **`install()` = fork + write `SKILL.md` to disk**
(plus per-trace activation tracking); use `fork()` for the workspace copy
without the disk write.

***

## `SkillRouter` — full CRUD

For programmatic skill management, instantiate `SkillRouter` directly:

```python theme={null}
from decimalai import SkillRouter

router = SkillRouter(api_key="dai_sk_...", base_url="https://api.decimal.ai")

# Registry browsing
menu = router.get_menu(agent_name="support-agent")

# Smart routing — let the router pick the best skill for a query
chosen = router.smart_route(query="How do I cancel my subscription?",
                            agent_name="support-agent")

# CRUD
router.create_skill(name="refund_policy", description="Refund policy", body_markdown="...")
router.list_skills()
router.get_skill("refund_policy")
router.update_skill("skill_abc", body_markdown="...")
router.delete_skill("skill_abc")

# Bulk — sync_skills takes a list of skill dicts
router.sync_skills([{"name": "refund_policy", "body_markdown": "..."}])
router.export_to_disk(agents=["claude-code"])  # writes into the project's agent skill dirs
router.pull_missing(local_skill_names={"foo"}, agents=["support-agent"])
```

See the [Skills API reference](/api-reference/skills/overview) for the underlying REST surface.

***

## On-demand bodies: the `load_skill` tool

The routed menu carries names + descriptions; bodies load on demand. On the
`openai_agents` and `pydantic_ai` adapters, `install(enable_skill_loader=True)`
also registers a native **`load_skill(name)` tool** on every agent — the model
reads the menu, calls the tool with a skill's exact name, and the full
instructions arrive as the tool result mid-turn. Nothing to wire manually:

```python theme={null}
import decimalai
from decimalai.openai_agents import install

decimalai.init()
install(enable_skill_loader=True)   # menu injection + load_skill tool

# ... the model can now call load_skill("refund-policy") on its own
```

Body loads are budgeted per turn so they can't blow the context window:

| `SkillRouter` knob     | Default | Effect                                                            |
| ---------------------- | ------- | ----------------------------------------------------------------- |
| `max_loaded_bodies`    | 3       | Max distinct bodies per turn; further loads get a refusal message |
| `body_token_budget`    | 6000    | Estimated-token cap across all loaded bodies                      |
| `per_body_char_limit`  | 8192    | Each body is trimmed to this (server- and client-side)            |
| `body_load_deadline_s` | 20      | Wall-clock cap on body round-trips within a turn                  |

Re-loading an already-loaded skill is free. Each load is recorded on the trace
(`skills_loaded_by_agent`), closing the offered-vs-loaded join server-side.

The `anthropic` and `langchain` adapters have no tool loop to route a result
through, so they stay on prompt injection — their `inject_skill_body=True`
path applies the same trim and budget. Disable the tool everywhere with
`decimalai.init(load_skill_tool=False)` or `DECIMALAI_LOAD_SKILL_TOOL=0`.

You can also call the primitive directly:

```python theme={null}
router.load_skill("refund-policy")        # budgeted, returns "## Skill: ..." block
router.get_skill_body("refund-policy", max_chars=8192)  # raw fetch, server-side trim
```

***

## What's next

<CardGroup cols={2}>
  <Card title="Skills guide" icon="book" href="/guides/skills">
    File format, registry, and SkillScore for skill effectiveness.
  </Card>

  <Card title="Skills Observability tutorial" icon="chart-line" href="/tutorials/skills-observability">
    Real-world example of measuring skill impact with experiments.
  </Card>
</CardGroup>
