技能系统#
技能是在每次任务前注入智能体提示词的可复用、领域特定的知识片段。它们编码了从之前运行中总结出的成功证明策略、领域约定和常见陷阱。
eurekaclaw/skills/
├── registry.py SkillRegistry (load + store skills)
├── injector.py SkillInjector (retrieve + format for prompts)
├── install.py SkillInstaller (install seed skills or skills from ClawHub)
└── evolver.py SkillEvolver (distill skills from proceeded session)
技能文件格式#
每个技能是一个带 YAML frontmatter 的 Markdown 文件:
---
name: ucb_regret_analysis
version: "1.0"
tags: [bandit, regret, ucb, concentration]
agent_roles: [theory, survey]
pipeline_stages: [theory]
description: How to decompose and bound UCB1 regret using concentration inequalities
source: seed # seed | distilled | manual
created_at: 2026-01-01T00:00:00
usage_count: 0
success_rate: null # float 0-1, or null if unknown
---
# UCB Regret Analysis
When bounding UCB1 regret, decompose into:
1. Suboptimal arm pulls where confidence bound held (good event)
2. Pulls where the bound failed (bad event, controlled by concentration)
Use Hoeffding for sub-Gaussian rewards, Bernstein when variance is known...
技能根据其来源存储在三个位置之一(详见下方技能生命周期)。
SkillRegistry#
文件: eurekaclaw/skills/registry.py
class SkillRegistry:
def __init__(skills_dir: Path | None = None) -> None
加载#
def load_all() -> list[SkillRecord]
从已注册目录加载所有技能。加载顺序(后者覆盖前者):
eurekaclaw/skills/seed_skills/中的种子技能领域插件技能(来自
get_skills_dirs()的额外目录)~/.eurekaclaw/skills/中的用户技能(最高优先级)
def add_skills_dir(path: Path) -> None
注册额外的技能目录(由领域插件使用)。
def reload() -> None
从磁盘重新加载所有技能(例如蒸馏写入新文件后)。
检索#
def get(name: str) -> SkillRecord | None
按精确名称检索技能。
def get_by_tags(tags: list[str]) -> list[SkillRecord]
返回所有包含至少一个给定标签的技能。
def get_by_role(role: str) -> list[SkillRecord]
返回所有 agent_roles 包含 role 的技能。
def get_by_pipeline_stage(stage: str) -> list[SkillRecord]
返回指定流水线阶段的所有技能。
存储#
def upsert(skill: SkillRecord) -> None
将技能写入磁盘并注册到内存。在 ~/.eurekaclaw/skills/ 中创建或覆盖 .md 文件。
SkillInjector#
文件: eurekaclaw/skills/injector.py
检索与任务最相关的技能并将其格式化,注入智能体系统提示词。
class SkillInjector:
def __init__(
registry: SkillRegistry,
selected_skills: list[str] | None = None,
) -> None
selected_skills — 可选的技能名称列表,用于固定技能。固定技能始终排在前 k 个结果的最前面,优先于按使用次数排序的可选技能。若固定技能名称在注册表中未找到,则记录警告并静默跳过。
检索#
def top_k(
task: Task,
role: str,
k: int = 5,
strategy: Literal["tag", "semantic", "hybrid"] = "tag"
) -> list[SkillRecord]
检索策略:
策略 |
说明 |
|---|---|
|
按匹配的 |
|
基于 |
|
标签过滤(3×k 候选),再按文本相似度排序 |
固定技能优先级: 当 selected_skills 非空时,tag(及 hybrid)检索将候选分为:
必须包含 — 同时在
selected_skills和角色/阶段集合中的技能 → 始终排在前面可选 — 剩余候选 → 按
usage_count降序排序
合并后的列表截断为 k 个。
格式化#
def render_for_prompt(skills: list[SkillRecord]) -> str
返回注入智能体系统提示词的 XML 块:
<skills>
<skill name="ucb_regret_analysis">
# UCB Regret Analysis
...
</skill>
<skill name="concentration_inequalities">
...
</skill>
</skills>
数据模型#
文件: eurekaclaw/types/skills.py
class SkillMeta(BaseModel):
name: str
version: str = "1.0"
tags: list[str] = []
agent_roles: list[str] = [] # e.g., ["theory", "survey"]
pipeline_stages: list[str] = [] # e.g., ["theory", "experiment"]
description: str = ""
source: Literal["seed", "distilled", "manual"] = "seed"
created_at: datetime
usage_count: int = 0
success_rate: float | None = None
class SkillRecord(BaseModel):
meta: SkillMeta
content: str # Markdown body after frontmatter
file_path: str = "" # absolute path to the .md file
embedding: list[float] | None = None # populated on first semantic retrieval
@property
def full_markdown(self) -> str: ... # frontmatter + content
技能蒸馏(运行后学习)#
每次成功的会话结束后,ContinualLearningLoop.post_run() 从会话中蒸馏新技能:
ContinualLearningLoop.post_run()
├── extract failures (FailedAttempt[]) from TheoryState
├── deduplicate — only unique failure patterns (skip low-novelty)
├── compress successes — proof text trimmed to 300 chars
├── SkillEvolver.distill_from_session()
│ → new SkillRecord .md files in ~/.eurekaclaw/skills/
└── (rl/madmax modes) ProcessRewardModel scoring
SkillEvolver.distill_from_session() 使用主 LLM:
从成功的证明中识别可推广的模式
编写带有适当标签和角色的新技能 Markdown 文件
在 frontmatter 中设置
source: distilled
新技能通过 SkillRegistry.reload() 在下一次会话中立即可用。
种子技能(MAB 领域)#
MAB 领域插件内置四个种子技能:
技能 |
标签 |
说明 |
|---|---|---|
|
bandit, regret, ucb |
通过集中不等式进行 UCB1 遗憾分解 |
|
bandit, thompson, bayesian |
Thompson Sampling 遗憾分析 |
|
bandit, lower-bound, information |
Lai-Robbins 和基于 Fano 的下界 |
|
bandit, simulation, experiment |
如何运行和解读赌博机模拟 |
安装种子技能#
eurekaclaw install-skills # copy seeds to ~/.eurekaclaw/skills/
eurekaclaw install-skills --force # overwrite existing copies
eurekaclaw install-skills <skillname> # install a skill from ClawHub
<skillname> 形式通过 clawhub CLI(需单独安装)从 ClawHub 注册表获取技能。示例:
eurekaclaw install-skills steipete/github
此命令仅用于检查和手动编辑。智能体不需要执行此命令——种子技能始终直接从包中获取。
技能生命周期#
了解技能的物理存储位置,可以避免对 ~/.eurekaclaw/skills/ 中未包含某些技能的困惑。
三个存储位置#
位置 |
写入者 |
时机 |
|---|---|---|
|
包开发者(您) |
提交到代码库;随 |
|
领域插件作者 |
通过 |
|
|
按需写入;用户可编辑 |
运行时加载顺序#
每次 SkillRegistry._load() 运行时,按以下顺序读取所有三个来源。同名技能后来者覆盖前者:
1. eurekaclaw/skills/seed_skills/**/*.md (lowest priority)
2. domain plugin skill dirs (extra_dirs) (medium priority)
3. ~/.eurekaclaw/skills/**/*.md (highest priority — overrides seeds)
结论: 向 seed_skills/ 添加文件后,智能体在下一次运行时即可看到该技能,无需将任何内容复制到 ~/.eurekaclaw/skills/。~/.eurekaclaw/skills/ 中缺少某个种子技能不会降低智能体能力。
新技能的生成方式#
技能通过三条路径进入系统:
1. 种子技能(开发者编写)#
在 eurekaclaw/skills/seed_skills/<category>/ 中创建 .md 文件:
# e.g. for a new theory skill
touch eurekaclaw/skills/seed_skills/theory/my_new_skill.md
在 frontmatter 中设置 source: seed。文件保存后,智能体立即可用——无需 CLI 步骤。
2. LLM 蒸馏(自动,运行后)#
每次成功的会话结束后,SkillEvolver.distill_from_session() 使用会话中最多 5 条 FailedAttempt 记录和 5 条 ProofRecord 成功记录进行调用。它使用快速模型发起蒸馏提示,并将响应解析为新的 SkillRecord。
新技能通过 SkillRegistry.upsert() 写入 ~/.eurekaclaw/skills/<name>.md,带有:
source: distilledname: distilled_<session_id[:8]>_<random_hex>从 LLM 响应中提取的标签、角色和阶段
后续会话无需重启即可立即使用。
Session completes
└── SkillEvolver.distill_from_session(failures, successes)
└── LLM call (fast model, max_tokens=1024)
└── _parse_skill_response()
└── SkillRegistry.upsert() → ~/.eurekaclaw/skills/<name>.md
3. ClawHub 技能#
eurekaclaw install-skills <author>/<skillname>
通过 clawhub CLI 从 ClawHub 注册表下载技能并放置在 ~/.eurekaclaw/skills/ 中。需要安装 clawhub(pip install clawhub 或等效方式)。
4. 手动用户技能#
将任何带有有效 YAML frontmatter 的 .md 文件直接放入 ~/.eurekaclaw/skills/,下一次会话加载时即可使用。在 frontmatter 中使用 source: manual 与蒸馏技能区分。
技能统计更新#
每次会话结束后,SkillRegistry.update_stats(name, success) 会以更新后的 usage_count 和 success_rate(指数移动平均,α=0.3)重写技能文件。这仅影响 ~/.eurekaclaw/skills/ 中已存在的技能——包内的种子技能不会被运行会话修改。
为何 ~/.eurekaclaw/skills/ 可能看起来是空的#
全新安装且尚未运行任何会话时,~/.eurekaclaw/skills/ 目录将为空。这是正常现象。智能体并未"缺失"任何技能——它们在运行时直接读取种子技能和领域插件技能。~/.eurekaclaw/skills/ 会随时间通过以下方式逐渐填充:
eurekaclaw install-skills(一次性复制,用于检查/编辑)已完成的会话(自动蒸馏)
手动放置的自定义
.md文件