← All concepts

Skills as markdown

Move agent expertise out of code and into versionable markdown. Domain experts contribute via PR; the loop almost never changes.

5 projects 1 insights 4 variants
TL;DR 6 min read

A small architectural bet pays back over years: store the agent’s expertise — methodologies, playbooks, attack patterns, code-review checklists — as markdown files in a skills/ directory, not as code. Each file has a name, a trigger, and a body. The agent loads matched skills into the system prompt at task start. Domain experts contribute via PR. The loop almost never changes; the library evolves weekly. This is the moat.

Skills as markdown

The pattern looks pedestrian at first. A skills/ folder. Inside, a few dozen .md files. Each has frontmatter (a name, a trigger), a body of guidance, and maybe some examples. The agent’s loop matches relevant skills to the current task and concatenates their bodies into the system prompt.

That’s it. The reason it’s an architectural decision worth naming is that it changes who can extend the agent.

Anatomy of a skill file

---
name: SQL injection testing
trigger: "user asks about SQL injection or database security"
priority: 1
---

# SQL Injection Testing Methodology

## When to use this skill
You're investigating a web application's database interaction surface.

## Approach
1. Identify entry points (form fields, URL params, headers).
2. Test for error-based injection first — most signal.
3. Move to UNION-based if errors are silent.
4. ...

The agent’s loop:

on task arrival:
  1. compute trigger matches against this skill library
  2. concatenate matched skill bodies into the system prompt
  3. start the loop

Why this is a strong pattern

flowchart LR
Author[Domain expert] -->|writes .md| Repo[skills/ dir]
Repo -->|PR review| CI
CI -->|merge| Repo
Repo -->|matched triggers| Agent
Agent -->|enriched context| LLM
Authoring lives in markdown PRs; the agent merely runs the loaded skill at the right moment.
  • Reviewability. A pentester reviews a .md PR. They never have to learn Python.
  • Versionability. git log skills/sql-injection.md shows the methodology’s evolution. No archaeology through prompt builders.
  • Locality. Skill, trigger, and rationale all live in one file. Code-based skills scatter across modules.
  • Forkability. A new project lifts a curated subset as a starting library.

Strix as the maximalist case

Strix takes this to ~30 markdown files in strix/skills/ covering web, network, mobile, and crypto attack methodologies. New methodologies arrive as PRs from researchers who never touch the agent’s Python code.

Claude Code’s skill system

Claude Code ships with built-in skills (e.g. init, review, security-review, claude-api) — markdown bundles a user invokes with /skill-name. User-defined skills live alongside in ~/.claude/skills/. Same shape, two scopes (vendor + user).

A split: YAML agent, markdown skills

Strix and Claude Code put the methodology itself in markdown. Omnigent splits the two. The agent is a YAML definition — its executor.harness field is a late-bound dispatch key, so swapping one string swaps the whole agent loop — but the skills attached to it stay markdown SKILL.md files (e.g. examples/polly/skills/cross-review/SKILL.md). Structure lives in YAML where it’s validated; know-how lives in markdown where a domain expert can edit it.

A different axis: the skill as a portable install target

Strix, Claude Code, and Omnigent all use markdown skills inside their own runtime. OpenKnowledge uses the same format as a cross-harness distribution unit. Its ok init writes one SKILL.md into each connected harness’s native skill directory — .claude/skills/, .cursor/skills/, the shared .agents/skills/ for Codex and OpenCode — driven by the same adapter struct that knows each harness’s MCP config path. The agent never learns it’s talking to OpenKnowledge; the skill teaches it in the agent’s own skill mechanism.

The second twist is a robustness principle worth borrowing: the skill is the floor, MCP is the ceiling. OpenKnowledge’s discovery skill is written to work with nothing but ls/cat/grep over the files (its frontmatter literally reads “Any agent host — no MCP server required”). So the integration degrades gracefully — full fidelity when the MCP tools are mounted, basic fidelity from the shell the agent already has. Markdown skills aren’t just expertise here; they’re the lowest-common-denominator contract that survives a missing tool surface.

Why this took until ~2024 to appear

Three preconditions had to land:

  1. Long enough context windows that loading a dozen skills fits.
  2. Prompt caching that makes repeated loading cheap.
  3. Agent loops stable enough that there’s somewhere for skills to plug in.

Pre-2023, the windows were too small. Pre-late-2023, caching was too immature. The pattern depended on infrastructure shifts.

Skill-loading strategies

StrategyWhenCost
Always load allsmall library (<10 skills, <20K tok)constant cache hit
Trigger-matchedmedium library, fast triggerscheap regex / keyword match per task
LLM-routedlarge library, fuzzy triggersextra LLM call to pick skills
User-invokedskills with overhead per callnone until invoked (/skill-name)

Most production agents combine: cheap match for common tasks, LLM router for ambiguous ones, user invocation for skills the user knows are relevant.

Triggers — the underrated piece

A skill is only as useful as its trigger. Bad triggers either miss the right calls or fire too often, bloating context.

  • String match (cheap, brittle): “if user message contains ‘sql’ or ‘database.’”
  • Tag-based: skills declare tags; the agent provides a tag during planning.
  • LLM-routed: ask a small auxiliary LLM “given this task, pick from this list.”
  • Manual: /security-review, no inference needed.

Pick a skill strategy

? How many skills, and how confident is your trigger?
  • Library is small + skills are general Always load all. Predictable cache.
  • Library is moderate with clear keywords String/tag-matched triggers.
  • Library is large with fuzzy applicability LLM-routed triggers.
  • Skills are situational and user-knows Manual invocation only.

Recommended default: Start with always-load-all. Only complicate when the library is too big to load comfortably.

When markdown skills don’t help

  • Tiny agents. Five hardcoded prompts is not worth the indirection.
  • Highly dynamic skills. If skill content depends on runtime data (DB schema, user config), it needs templating; markdown is the wrong format.
  • High-stakes determinism. If you need each invocation to be byte-identical (legal, compliance copy you must reproduce verbatim), code is more auditable than markdown.

Projects that implement this

  • Claude Code — Anthropic's official agentic CLI. Streaming tool calls, prompt caching, thinking signatures, multi-agent subagents, slash commands.
  • Strix — Open-source 'AI hacker' for autonomous pentesting. XML tool format, markdown-as-skills, LLM-based dedupe, module-level agent graph.
  • Omnigent — Open-source meta-harness: one orchestration layer over Claude Code, Codex, Cursor, Kimi, Pi and YAML-defined custom agents. Native bridges per agent, ALLOW/DENY/ASK policy gates, 8-provider cloud sandboxes, vendor-diverse code review.
  • OpenClaw — Open-source Claude-Code-style agent reproduction. Bigger than NanoClaw, reveals which patterns scale and which stay minimal.
  • OpenKnowledge — Local-first WYSIWYG markdown editor that plugs INTO harnesses (Claude Code, Codex, Cursor, OpenCode) as an MCP tool-server + cross-harness SKILL.md. Agent edits are CRDT writes into the live doc; every edit is an attributed git commit on a per-writer ref. The side-channel complement to a meta-harness.