Skip to main content
A skill is a self-contained capability that lives as a folder inside your agent’s workspace. It bundles instructions (SKILL.md), the scripts that do the real work, and any templates or assets they need. The agent isn’t told about skills in Python — it discovers them at runtime by reading files, decides when one applies, follows its rules, and runs its scripts. This is the natural counterpart to the AutonomousAgent: the agent brings the reasoning and the filesystem/shell tools, and skills bring the standardized, repeatable know-how. Together they turn “an agent that can run commands” into “an agent that knows how your team does things.”
Skills require no new API. An AutonomousAgent already has the filesystem and shell tools it needs to find, read, and execute a skill. You add a skill by dropping a folder into the workspace and pointing to it from AGENTS.md — no code changes.

Why skills exist

Without skills, an autonomous agent improvises every task from scratch. Ask it for “a report” twice and you can get two different layouts. Skills fix that by making the method a first-class artifact:
  • Consistency — the branding, columns, and formatting come from a template file, not from whatever the model invents that run.
  • Progressive disclosure — the agent only loads a skill’s full details when a task actually needs it, keeping context lean even with dozens of skills installed.
  • Evolvability — adding or improving a capability means editing a folder, not redeploying code.
  • Guardrails — a skill states its own rules (“never hand-write Excel; always call generate.py”), and the agent respects them.

Anatomy of a skill

A skill is just a directory under workspace/skills/. Each one owns a SKILL.md plus whatever scripts, templates, and assets it needs:
workspace/
├── AGENTS.md                    # agent behavior + skill index (routing)
├── SOUL.md                      # optional: identity / behavioral rules
├── memory/                      # cross-session continuity (YYYY-MM-DD.md)
├── data/                        # source data the skills operate on
├── reports/                     # outputs
└── skills/
    └── excel_report/
        ├── SKILL.md             # ← the contract: when & how to use this skill
        ├── generate.py          # the real generator (the agent calls this)
        ├── templates/
        │   └── onboarding.json  # branding: colors, logo, columns, title
        └── assets/
            └── upsonic_logo.png
PartRole
SKILL.mdThe contract. When to trigger, how to invoke, arguments, hard rules.
Scripts (e.g. generate.py)The deterministic work. Formatting/branding lives here, not in the model.
templates/Declarative config (layout, colors, columns) the scripts read.
assets/Logos, fonts, and other static files the scripts embed.
Keep formatting decisions in scripts and templates — never in the agent’s head. The agent’s job is to choose and orchestrate the skill, not to reinvent its output. This is what makes results reproducible across runs.

Writing a SKILL.md

SKILL.md is a plain Markdown file written like a briefing for a capable colleague. It tells the agent when the skill applies, how to run it, and what it must never do. Here is the excel_report skill from the example below:
SKILL.md
# Skill: Excel Report Generator

Generate branded, formatted Excel reports from CSV data using predefined templates.

## When to Use

Trigger this skill when the user asks for:
- Reports (onboarding, weekly, monthly, etc.)
- Excel/spreadsheet generation
- Data exports with formatting

## Usage

```bash
python skills/excel_report/generate.py \
  --data data/onboarding.csv \
  --template skills/excel_report/templates/onboarding.json \
  --output reports/<filename>.xlsx
```

### Arguments

| Argument     | Required | Description                                 |
|--------------|----------|---------------------------------------------|
| `--data`     | Yes      | Path to the source CSV file                 |
| `--template` | Yes      | Path to the template JSON config            |
| `--output`   | Yes      | Where to save the generated `.xlsx`         |
| `--filter`   | No       | Date filter, e.g. `--filter "last_2_weeks"` |

### Date Filters

- `last_2_weeks` — rows from the last 14 days
- `last_month` — rows from the last 30 days
- `YYYY-MM-DD:YYYY-MM-DD` — explicit date range

## Important

- **Never write Excel manually.** Always use `generate.py` with a template.
- The generator handles all formatting, branding, and data type conversions.
- If a new report type is needed, create a new template JSON — don't modify `generate.py`.
The key sections every SKILL.md should have:
Concrete phrases and situations that should activate the skill. This is what the agent matches a request against. Be specific: “reports, exports, spreadsheets, ‘last 2 weeks’ report’.”
The precise command and arguments. The agent will run this verbatim through its shell tool, so include real paths and a full example.
The non-negotiables that keep the skill’s guarantees intact: “Never write Excel manually,” “don’t modify generate.py; add a new template instead.” The agent treats these as boundaries, not suggestions.

Registering a skill in AGENTS.md

The agent finds skills because AGENTS.md tells it where to look and when to use each one. AGENTS.md is the index and routing table; each SKILL.md is the detailed manual the agent opens only when routed there.
AGENTS.md
## Skills

Skills live in `skills/`. Each skill has its own folder with a `SKILL.md`.
Read the relevant one before starting a task — skills can be combined.

**Available skills:**

- **excel_report** — Generate branded Excel reports from CSV data. Use when the
  user asks for reports, exports, spreadsheets, or "last 2 weeks' report".

### Routing Rules

| User says...                            | Skill to use |
|-----------------------------------------|--------------|
| "create report", "report", "export"     | excel_report |
| "onboarding status", "last 2 weeks"     | excel_report |
| "excel", "spreadsheet", "table"         | excel_report |

**Important:** Never write Excel files by hand. Always delegate to the skill's `generate.py`.
When the workspace is set, AGENTS.md is injected into the system prompt automatically. So at the start of every run the agent already knows the skill catalog and the routing rules — without any of the skills’ bulky details. It opens the full SKILL.md only once a task routes to it. That is progressive disclosure, and it’s what lets the model scale to many skills without bloating context.

How skills and the autonomous agent work together

The connection between the two is files, not code. The agent never imports a skill. It discovers, respects, and (when needed) extends a skill purely by reading and running files in the workspace.
User input: "give me last month's onboarding report — as a PDF"


┌───────────────────────────────────────────────┐
│  Chat  (session + memory)                       │
└───────────────────────────────────────────────┘
        │  invoke(stream=True, events=True)

┌───────────────────────────────────────────────┐
│  AutonomousAgent  (reasoning + tools)           │
│  tools: read_file · list_files · write_file ·   │
│         check_command_exists · run_command      │
└───────────────────────────────────────────────┘
        │   reads ┌─────────────┐
        ├────────▶│ AGENTS.md   │  routing → excel_report; "never hand-write Excel"
        │         │ SOUL.md     │  identity + behavior
        │         │ memory/*    │  what happened last time
        │         └─────────────┘
        │   discovers + respects

┌───────────────────────────────────────────────┐
│  Skill: excel_report                            │
│   SKILL.md  ............ the contract            │
│   generate.py  ──► .xlsx  (branding=template)   │
│   templates/onboarding.json  (colors/logo/cols) │
└───────────────────────────────────────────────┘


   reports/onboarding_2026-06-09.xlsx
The agent is the reasoning + tools; the skill is the declarative capability on disk; AGENTS.md + SKILL.md are the contracts that bind them. None of this behavior is hardcoded in Python — it emerges from the workspace files plus the model’s reasoning.

Walkthrough: a skill in a live run

This is a real, observed run of an AutonomousAgent paired with the excel_report skill. It shows the whole loop — discover, respect, extend, verify, remember — and is the best way to understand the combo.

The driver: a terminal chat over the workspace

chat.py wires a Chat session to an AutonomousAgent pointed at the workspace. That’s the entire integration — there is no mention of skills in this file.
chat.py
import asyncio
import os
from dotenv import load_dotenv
from upsonic import AutonomousAgent, Chat
from upsonic.run.events.events import TextDeltaEvent, ToolCallEvent

load_dotenv()
WORKSPACE = os.path.join(os.path.dirname(__file__), "workspace")


async def main() -> None:
    agent = AutonomousAgent(
        model="anthropic/claude-opus-4-8",
        workspace=WORKSPACE,        # ← skills/, AGENTS.md, memory/ live here
        print=True,
    )

    async with Chat(session_id="hq-terminal", user_id="user", agent=agent) as chat:
        while True:
            user_input = input("You: ").strip()
            if user_input.lower() in {"exit", "quit"}:
                break

            stream = await chat.invoke(user_input, stream=True, events=True)
            async for event in stream:
                if isinstance(event, ToolCallEvent):
                    print(f"\n  ↳ [tool] {event.tool_name}", flush=True)
                elif isinstance(event, TextDeltaEvent):
                    print(event.content, end="", flush=True)


if __name__ == "__main__":
    asyncio.run(main())
The single input for this run was: “give me last month’s onboarding report — as a PDF.” Note the twist: the excel_report skill only outputs .xlsx. Here is how the agent handled it, across four phases.
1

Orient — read the contracts and the data

Before producing anything, the agent followed the order AGENTS.md imposes: it read SOUL.md (identity), scanned memory/ for prior runs, opened skills/excel_report/SKILL.md, then looked at the actual data (data/onboarding.csv) and even generate.py to understand what the skill really produces.Its own framing: “The skill makes Excel, you asked for PDF. Let me read the context and check the data first.” Critically, it identified the skill’s boundary (.xlsx only) and the user’s real ask (PDF) before writing a single line.
2

Probe the environment

The agent checked what tools were available for PDF generation: check_command_exists libreoffice (missing), soffice (missing), then probed Python and found reportlab, pandas, and openpyxl already installed. It decided to generate the PDF with reportlab — but to pull layout and branding from the same template the Excel uses, so the two formats stay identical.
3

Run the skill — and face the data

It invoked the skill as SKILL.md documents it: generate.py --filter last_month returned “No data after filtering.” Instead of shipping an empty report, the agent diagnosed why: today is 2026-06-09, but every CSV record is from 2026-04-28 to 2026-05-05, so a rolling 30-day window catches nothing. It fell back to an explicit range covering the real data and got a valid report (12 rows) — and flagged the staleness to the user honestly.
4

Extend, verify, remember

To fill the PDF gap, the agent did not bypass or modify the skill (SKILL.md forbids editing generate.py). Instead it added a sibling script, to_pdf.py, that reuses the skill’s own logic:
to_pdf.py
# Reuse the proven logic from the Excel generator
from generate import (
    apply_date_filter, format_cell_value,
    load_data, load_template, validate_columns,
)
Same template, same colors, same status coloring (HUMAN REVIEW → yellow, COMPLETED → green) — just a PDF renderer. It generated the file, verified it (1 page, landscape A4, branding intact), and wrote the session and its lessons to memory/2026-06-09.md so the next session starts smarter.

What the agent produced

  • reports/onboarding_2026-06-09_last_month.xlsx — the skill’s standard output.
  • reports/onboarding_2026-06-09_last_month.pdf — the requested format, branded identically.
  • skills/excel_report/to_pdf.py — a new capability added to the skill ecosystem without breaking it.
  • memory/2026-06-09.md — a continuity note: “this data is stale; rolling-window filters return empty; use to_pdf.py for PDFs.”

Design principles this run reveals

The agent learned the skill at runtime by reading SKILL.md. Adding a new skill = a new folder + a SKILL.md + a routing line in AGENTS.md. The agent’s code never changes.
AGENTS.md said “never hand-write Excel.” The agent always produced Excel through generate.py. Branding lived in the template, not in the model’s improvisation.
PDF wasn’t supported. The agent didn’t fake a table or edit generate.py (forbidden). It added a sibling script that reuses the skill’s logic — the ecosystem grew, the guarantees held.
An empty filter result wasn’t silently shipped. The agent found the cause, told the user, and chose a sensible fallback — behavior that flows from SOUL.md’s “have opinions / flag what looks off.”
The agent wrote what it learned to memory/. The next session reads it and avoids repeating the same discovery. Skills + memory compound over time.

Adding a new skill

1

Create the folder

Make workspace/skills/<skill_name>/ (kebab or snake case, matching how you’ll reference it).
2

Write SKILL.md

Add a SKILL.md with When to Use, Usage (exact command + arguments), and Important (the hard rules). Write it like a briefing — concise and actionable.
3

Add scripts, templates, and assets

Put the deterministic work in scripts and the formatting/branding in templates. Keep decisions out of the model so output stays reproducible.
4

Register it in AGENTS.md

Add the skill to the Available skills list and the Routing Rules table so the agent knows when to reach for it.
5

Run a task that triggers it

Invoke the agent with a request that matches the routing rules and confirm it reads the SKILL.md, runs the script, and produces the expected output.
All skill scripts run through the agent’s shell tool, sandboxed to the workspace. Only add scripts you trust, and keep secrets out of skill files — the workspace travels with the agent.

Next steps

AGENTS.md

How the workspace contract is loaded into the system prompt and used to route to skills.

Filesystem Tools

The read/write/search tools the agent uses to discover and run skills.

Memory Integration

How cross-session memory lets skill usage compound over time.

Folder Organizer Example

A complete autonomous agent driven entirely by a workspace skill file.