Agent Systems / Skills

Agent Skills 入门:把研究流程封装成可复用、可测试的技能

把“每次重写 prompt”变成“调用一个有说明、有脚本、有测试的技能”,让 Agent 可发现、可组合、可靠地执行研究流程。

Skill 可以先理解成“研究流程的说明书 + 脚本 + 测试”。它告诉 Agent:这个流程叫什么、什么时候用、分几步、需要什么输入、产出什么。和一次性 prompt 不同,技能是持久、可复用、可测试、可组合的——这正是把课程项目从“手工拼”变成“可复现流水线”的关键。

先看这里

学完这一页你应该会什么

01

把可复用的研究步骤封装成技能:名称、何时使用、输入、步骤、产物。

02

理解技能选择:Agent 按任务描述匹配最合适的技能,而不是硬编码。

03

会把技能组合成带 gate 的流水线,并知道整体可靠性是各步通过率之积。

04

知道技能需要测试:用例 + 通过率,像对待代码一样对待技能。

05

理解渐进式披露:只在触发时加载技能正文,节省上下文。

学习路径

学习路径:定义 → 选择 → 组合 → 测试 → 渐进披露

按这条路径理解技能:先把流程写成合约,再按描述选择,组合成带 gate 的流水线,给每步写测试,最后用渐进式披露管理上下文。

  1. Step 1

    Define

    把流程写成 name + when_to_use + steps + run。

  2. Step 2

    Select

    按任务与描述相似度选择最匹配技能。

  3. Step 3

    Compose

    把技能按依赖组合成流水线。

  4. Step 4

    Test

    为每个技能写用例,统计通过率。

  5. Step 5

    Disclose

    只加载被触发技能的正文,节省上下文。

01 / 直觉

核心直觉

prompt 是一次性的口头指令,技能是写下来、可复跑、可分享的流程说明书;前者难复现,后者像实验室 SOP。

技能的核心是“何时使用”(when_to_use):写清触发条件,Agent 才能在对的场景选对技能,而不是什么都塞进一个大 prompt。

技能可以组合:清洗 → 估计 → 出表 → 稳健性,每一步是独立、可测试的技能,连起来才是研究流水线。

技能越多越要管理上下文:用一个轻量索引描述所有技能,只有被触发的技能才加载完整正文和脚本。

02 / 数学

把技能写成合约、选择、组合与可靠性

01 / 技能合约

一个技能是带元数据的可执行单元:名称、触发条件、输入、步骤和产物。

02 / 技能选择

Agent 用任务与各技能描述的相似度选择最匹配技能;与工具发现同理,但更高层。

03 / 组合为流水线

多个技能按依赖顺序组合,前一个的产物是后一个的输入。

04 / 前置 gate

每个技能执行前检查前置条件;不满足就回退或报错,而不是带病继续。

05 / 流水线可靠性

若各技能独立通过,流水线整体可靠性是各步通过率之积——这解释了为何要逐个测试。

06 / 上下文经济

渐进式披露:上下文成本 = 索引成本 + 仅被触发技能的正文成本。

03 / 代码

代码案例:定义、选择、组合并测试技能

下面用纯 Python 模拟技能的入门逻辑:把流程写成合约、按描述选择、组合成流水线、算可靠性、做渐进式披露、写测试。

案例 1:按任务描述自动选择技能

不要硬编码调用哪个技能。让 Agent 按任务与技能描述的重合度自动选择。

REGISTRY = {
    "clean_panel": "balance a panel drop duplicates handle missing values",
    "event_study": "panel staggered treatment event time relative dummies",
    "make_table":  "render regression results into a publication table",
}

def select(task, registry):
    tok = set(task.lower().split())
    scored = {name: len(tok & set(desc.split())) for name, desc in registry.items()}
    return max(scored, key=scored.get), scored

task = "estimate an event study for a staggered treatment in panel data"
best, scores = select(task, REGISTRY)
print("scores:", scores)
print("selected skill:", best)

预期输出

scores: {'clean_panel': 2, 'event_study': 4, 'make_table': 1}
selected skill: event_study

怎么读这段代码

  • 重合度最高的技能被选中,对应 argmax similarity。
  • 真实系统用嵌入相似度,但思想一致:描述写得好,才选得准。

案例 2:把技能组合成带 gate 的流水线

清洗 → 估计 → 出表,每一步是独立技能,前置 gate 不满足就报错。

def clean_panel(state):
    state["clean"] = True; return state
def event_study(state):
    assert state.get("clean"), "needs a clean panel first"
    state["coefs"] = [0.01, 0.04, 0.12]; return state
def make_table(state):
    assert "coefs" in state, "needs estimates first"
    state["table"] = "outputs/event_study.tex"; return state

pipeline = [clean_panel, event_study, make_table]
state = {"panel": "firm-year.csv"}
for skill in pipeline:
    state = skill(state)
print("artifacts:", {k: state[k] for k in ("clean", "coefs", "table")})

预期输出

artifacts: {'clean': True, 'coefs': [0.01, 0.04, 0.12], 'table': 'outputs/event_study.tex'}

怎么读这段代码

  • 前一个技能的产物是后一个的输入,串成研究流水线。
  • gate(assert)保证不带病继续,例如未清洗就不许估计。

案例 3:流水线可靠性 = 各技能通过率之积

五个看似很高的技能串起来,整体可靠性会明显下降。

import math
pass_rates = {"clean_panel": 0.99, "event_study": 0.95, "make_table": 0.98}
R = math.prod(pass_rates.values())
print("per-skill pass rates:", pass_rates)
print(f"pipeline reliability = {R:.3f}")
print(f"failure rate = {1 - R:.3f}  -> test each skill, do not trust the chain")

预期输出

per-skill pass rates: {'clean_panel': 0.99, 'event_study': 0.95, 'make_table': 0.98}
pipeline reliability = 0.922
failure rate = 0.078  -> test each skill, do not trust the chain

怎么读这段代码

  • 0.99×0.95×0.98 ≈ 0.92,失败率约 8%。
  • 这解释了为何要逐个测试,而不是盲信整条链。

案例 4:渐进式披露——只在触发时加载技能正文

用轻量索引描述所有技能,只有被触发的技能才加载完整正文。

skills = {
    "clean_panel": {"index": 40, "body": 1200},
    "event_study": {"index": 45, "body": 1500},
    "make_table":  {"index": 38, "body": 900},
}
triggered = ["event_study"]                       # only this matches the task
index_only = sum(s["index"] for s in skills.values())
progressive = index_only + sum(skills[n]["body"] for n in triggered)
load_all = index_only + sum(s["body"] for s in skills.values())
print("index-only tokens:        ", index_only)
print("progressive-disclosure:   ", progressive)
print("load-everything tokens:   ", load_all)

预期输出

index-only tokens:         123
progressive-disclosure:    1623
load-everything tokens:    3723

怎么读这段代码

  • 索引 123 token;只加载触发技能 → 1623;全加载 → 3723。
  • 渐进式披露让技能库可以很大而不撑爆上下文。

案例 5:技能也要测试

像对待代码一样,为技能写用例(含边界与失败),统计通过率。

def event_study_skill(n_periods):
    if n_periods < 2:
        raise ValueError("need >= 2 periods")
    return {"ok": True, "periods": n_periods}

test_cases = [5, 3, 1, 8, 0]
results = []
for tc in test_cases:
    try:
        event_study_skill(tc); results.append(True)
    except Exception:
        results.append(False)
print("results:", results)
print(f"pass rate = {sum(results)/len(results):.2f}  (skills need tests, like code)")

预期输出

results: [True, True, False, True, False]
pass rate = 0.60  (skills need tests, like code)

怎么读这段代码

  • 通过率暴露技能在边界输入下的脆弱性。
  • 没有测试的技能会随数据与依赖变化而静默失效。

04 / 案例

案例:把“事件研究”封装成可复用技能

  • 你在多个项目里反复做事件研究:构造相对时间虚拟变量、估计、画系数图,每次重写很容易出错。
  • 把它封装成 event_study 技能:SKILL.md 写清何时使用与步骤,scripts/ 放可复跑脚本,tests/ 放用例。
  • Agent 拿到“估计一个交错处理的事件研究”任务时,按描述自动选中该技能,并在执行前检查面板是否已清洗(gate)。
  • 技能可组合:clean_panel → event_study → make_table → robustness_suite,每步留痕;整体可靠性 = 各步通过率之积,因此每个技能都要有测试。

05 / 因果

通向因果:把识别与稳健性做成技能

技能让因果研究的关键步骤变得可复用、可测试、可审计:识别检查、估计、稳健性都可以是独立技能,组合成一条可复现的因果流水线。

01 / 识别检查作为技能(assumption → skill)

把平行趋势、overlap、工具相关性 / 排他性写成 check 技能,估计前先跑。

02 / 估计作为技能(design → estimator skill)

为每种设计封装估计技能(DiD / IV / RD / DML),输入设计参数即可调用。

03 / 稳健性作为技能套件(estimate → robustness suite)

把安慰剂、敏感性、honest DiD 打包成一个可复用的稳健性技能套件。

04 / 可靠性可量化(chain → tested chain)

整条因果流水线的可靠性是各技能通过率之积,逼着你为每步写测试。

三条红线:(1) 技能能复用流程,但识别假设仍要人来辩护;(2) 技能必须有测试,否则数据一变就静默失效;(3) 高风险技能要设 gate 与人工确认,不能让自动化越权。

06 / 风险

常见误区

把技能写成一段模糊 prompt,没有明确“何时使用”和输入输出,导致 Agent 选错或乱用。
只堆技能不写测试:技能会随数据和依赖变化而失效,没有用例就无法发现。
忽视组合可靠性:五个 95% 的技能串起来整体只有约 77%,必须逐个加固。
把所有技能正文一次性塞进上下文,挤占窗口;应只在触发时加载。
技能里硬编码路径或样本,无法复用到别的项目;应参数化输入。
让技能执行高风险动作(删数据、覆盖结果)而不设 gate 与人工确认。

配套资源

下载实操资料

参考资料