SkillAdaptor evolves agent SKILL.md files from failure trajectories. Run it as a Python CLI on any workspace, or wire it into OpenClaw, Claude Code, Codex CLI, or Hermes Agent via --harness.
- Step-level attribution — On a failed run, the Localizer finds the earliest bad step t★; the Linker scores which injected skill caused it; Reviser patches or Generator creates a skill; Validator re-runs held-out tasks and adopts only on improvement.
- Workspace output —
skills/<id>/SKILL.md, synced to your agent’s skill paths. - Flexible tasks —
input_task/*.md,--manifest,auto_discover, or--input-trajectories. - Retrieval-gated inject — skills attach only when relevant.
PinchBench, WebShop, and Claw-Eval are optional executors (--env + path env vars). Custom task briefs work without them.
git clone https://github.com/zjunlp/SkillAdaptor.git
cd SkillAdaptor/skill-adaptor
pip install -r requirements.txtcd .. # repo root
mkdir -p secrets
cp .env.example secrets/.env
# Edit secrets/.env — API keys & paths# Linux / macOS
source scripts/load_secrets.sh
# Windows PowerShell
. scripts\load_secrets.ps1| Harness | Flag | Install guide |
|---|---|---|
| OpenClaw | --harness openclaw |
plugin/openclaw/README.md |
| Claude Code | --harness claude-code |
below |
| Codex CLI | --harness codex |
plugin/codex/README.md |
| Hermes Agent | --harness hermes |
plugin/hermes/README.md |
OpenClaw live runs need a running gateway:
npm install -g openclaw
openclaw gateway start
openclaw gateway statuscd skill-adaptor
python run_plugin.py init --workspace ../my-workspace --harness claude-code
# Add *.md task briefs under ../my-workspace/input_task/
python run_plugin.py --workspace ../my-workspace --dry-run
python run_plugin.py --workspace ../my-workspace --max-iterations 2Task sources
| Source | When to use |
|---|---|
input_task/*.md |
Default — any custom tasks |
--manifest path.json |
Fixed train/val splits |
--mode auto_discover |
Auto-split from PINCHBENCH_PATH checkout |
--input-trajectories |
Seed failures from existing trajectory files |
Workspace layout
| Path | Role |
|---|---|
input_task/*.md |
Task briefs; ~20% held out as validation Q′ |
test_task/ |
Optional extra held-out briefs |
skills/<id>/SKILL.md |
Adopted skills after Validator passes |
Use --sync-tasks after editing task files. With --env workspace (default when no benchmark path is set), tasks live in input_task/ only.
Evolution runs on tool steps only. Each step must carry a tool-level action, for example:
shell({"command": "grep ERROR app.log"})
write({"path": "report.txt", "content": "..."})
These do not qualify:
(assistant response)— text-only turns- Empty placeholders (
(no action),(end), …) - Runs with a score but no parseable tool trace
If a live run has no qualifying steps, SkillAdaptor raises TaskExecutionError instead of inventing a trajectory.
Load secrets/.env before running. Full template: .env.example.
Two independent API key + base URL pairs. Endpoints use a compatible chat API (…/v1). Switch chat models with --model only.
Chat (SkillAdaptor_PROVIDER=auto, default):
| Variable | Role |
|---|---|
SkillAdaptor_API_KEY |
Chat API key |
SkillAdaptor_BASE_URL |
Chat endpoint (relay / DeepSeek / Kimi / GLM — same pair) |
SkillAdaptor_MODEL |
Default model when --model omitted |
Embedding (always separate — skill–task matching):
| Variable | Role |
|---|---|
SkillAdaptor_EMBEDDING_API_KEY |
Embedding API key |
SkillAdaptor_EMBEDDING_BASE_URL |
Embedding endpoint |
SkillAdaptor_EMBEDDING_MODEL |
Model id (default Qwen3-Embedding-8B) |
If embedding key/URL are omitted, chat credentials are used as fallback. Prefer setting the embedding pair explicitly when the embedding host differs from chat.
# secrets/.env
SkillAdaptor_PROVIDER=auto
SkillAdaptor_BASE_URL=https://your-relay.example.com/v1
SkillAdaptor_API_KEY=sk-...
SkillAdaptor_MODEL=gpt-4.1
SkillAdaptor_EMBEDDING_API_KEY=sk-...
SkillAdaptor_EMBEDDING_BASE_URL=https://your-embedding.example.com/v1
SkillAdaptor_EMBEDDING_MODEL=Qwen3-Embedding-8BDeepSeek via relay (no extra provider vars): keep SkillAdaptor_PROVIDER=auto, point SkillAdaptor_BASE_URL at DeepSeek, use --model deepseek-chat.
After startup, resolve_and_apply writes the active chat pair to SkillAdaptor_API_KEY / SkillAdaptor_BASE_URL for downstream executors.
. scripts/load_secrets.ps1 # or source scripts/load_secrets.sh
cd skill-adaptor
python run_plugin.py --workspace ../my-workspace --model kimi-k2.5Alternate chat providers — only when the gateway needs its own key/URL pair:
SkillAdaptor_PROVIDER |
Key | Base URL | Notes |
|---|---|---|---|
deepseek |
DEEPSEEK_API_KEY → else SkillAdaptor_API_KEY |
DEEPSEEK_API_BASE_URL → else SkillAdaptor_BASE_URL |
Compatible /v1 API; default base https://api.deepseek.com/v1 |
openrouter |
OPENROUTER_API_KEY → else SkillAdaptor_API_KEY |
OPENROUTER_API_BASE_URL → else SkillAdaptor_BASE_URL |
Model ids use vendor/model; embedding falls back to gateway default when no separate embedding API |
Legacy provider names (relay-gpt41, relay-kimi, gpt, glm) map to auto.
| Variable | Purpose |
|---|---|
SkillAdaptor_PROVIDER |
Chat backend: auto (default), deepseek, openrouter |
SkillAdaptor_BENCHMARK_ENV |
Default executor when --env omitted: pinchbench, claw-eval, webshop |
SkillAdaptor_HARNESS |
Default harness: openclaw, claude-code, codex, hermes |
DEEPSEEK_MODEL |
Default DeepSeek model when SkillAdaptor_PROVIDER=deepseek and --model omitted |
OPENROUTER_MODEL |
Default OpenRouter model when SkillAdaptor_PROVIDER=openrouter and --model omitted |
PINCHBENCH_PATH |
PinchBench executor (--env pinchbench) |
CLAW_EVAL_PATH |
Claw-Eval executor (--env claw-eval) |
WEBSHOP_PATH |
WebShop executor (--env webshop) |
CODEX_HOME |
Codex home directory (default ~/.codex) |
HERMES_HOME |
Hermes home directory (default ~/.hermes) |
OPENCLAW_CLI |
Explicit openclaw binary path |
ALLOW_SYNTHETIC_TRAJECTORY |
1 — one-step fallback when no tool trace (debug only) |
TypeScript UI plugin + Python bridge. Configure in openclaw.json:
{
"skillAdaptorRoot": "/absolute/path/to/skill-adaptor/skill-adaptor",
"pythonCommand": "python",
"benchmarkEnv": "pinchbench",
"maxIterations": 2
}Details: plugin/openclaw/README.md.
Skills sync to .claude/skills/.
python run_plugin.py init --workspace /path/to/your-project --harness claude-code
python run_plugin.py --workspace /path/to/your-project --harness claude-codePinchBench validation (--env pinchbench) runs tasks through the OpenClaw gateway and needs PINCHBENCH_PATH.
Skills sync to ~/.codex/skills/ and <workspace>/.agents/skills/.
python run_plugin.py init --workspace /path/to/your-project --harness codex
python run_plugin.py --workspace /path/to/your-project --harness codexEnable [features] skills = true in ~/.codex/config.toml and restart Codex. Marketplace plugin steps: plugin/codex/README.md.
Skills sync to ~/.hermes/skills/skill-adaptor/.
python run_plugin.py init --workspace /path/to/your-project --harness hermes
python run_plugin.py --workspace /path/to/your-project --harness hermesProfile paths and operator skill: plugin/hermes/README.md.
@misc{yu2026skilladaptor,
title={SkillAdaptor: Self-Adapting Skills for LLM Agents from Trajectories},
author={Zhuoyun Yu and Xin Xie and Wuguannan Yao and Chenxi Wang and Lei Liang and Xiang Qi and Shumin Deng},
year={2026},
eprint={2606.01311},
archivePrefix={arXiv},
primaryClass={cs.AI},
url={https://arxiv.org/abs/2606.01311}
}