第 10 步:构建 BT Skill¶
这一节学什么¶
- 为什么 BT skill 适合放到节点和树之后再讲
- 一个最小 BT skill 目录由什么组成
SKILL.md、tree.py和运行时状态键分别负责什么- 上层 agent 正常会怎样调用 BT skill
你会运行什么¶
示例代码:
examples/getting_started/step_10_build_bt_skill.py
这个步骤会配套查看:
examples/getting_started/skills/bt_echo/SKILL.mdexamples/getting_started/skills/bt_echo/tree.py
运行:
为什么放到这里¶
BT skill 本质上不是“再写一段 prompt”。
它更像:
- 把一个子行为树打包成 skill
所以在理解它之前,先学完下面两件事会更顺:
- 节点怎么组合成树
- 自定义 Node 怎么读写 state / port
这也是为什么这一节放在 Step 08 和 Step 09 后面。
一个 BT skill 最少需要什么¶
这个最小例子里有两部分:
SKILL.md- 声明名字、描述和执行模式
tree.py- 提供真正执行的行为树构造函数
可以把它们理解成:
SKILL.md负责“声明这是一个什么 skill”tree.py负责“这个 skill 运行时实际做什么”
结构化结果桥接现在不该再简单理解成“在 SKILL.md 里声明 output key”。按当前 runtime,更关键的是:
- BT 子树把结构化结果写到
ctx.skill_result_key指向的命名空间内状态键 - 这个键通常来自
SkillNodeConfig.keys.skill_result
这一节现在演示的主路径¶
这一节不再把 BT skill 直接当成“整个 demo 的根树”来理解。
更接近真实使用方式的是:
- 先定义一个 BT skill
- 再让一个上层 agent 在需要时调用它
这个上层 agent 仍然是通过 SkillNode 接 skill,但因为这里提供了 model_client:
- 外层会先走一轮 ReAct
- ReAct 看见可用的 BT skill 后,会调用
run_bt_skill run_bt_skill再去执行这个 skill 的tree.py
所以你在这一节看到的,不是“BT skill 必须用 Agent 封装”,而是:
Agent是最外层 demo 宿主- 本例中的
SkillNode是 skill 接入层和外层 ReAct 宿主 - BT skill 真正的执行体还是
tree.py -> build_tree(ctx)
本例使用缺省的 orchestration: react。如果 BT skill 声明
orchestration: direct,并且是唯一加载的技能,SkillNode 会直接运行它并发布正式
skill_result,不再经过外层 ReAct 总结。
Prompt Skill 和 BT Skill 的边界¶
可以先按这个标准区分:
- prompt skill
- 主要靠一段 skill prompt 驱动模型
- BT skill
- 主要靠显式节点、状态和树结构驱动执行
所以当你发现自己已经开始需要:
- 稳定控制顺序
- 确定性状态写回
- 非模型驱动的局部逻辑
通常就该考虑 BT skill,而不是继续给 prompt skill 叠说明。
运行后观察什么¶
- 外层 assistant 会出现一次
run_bt_skill(...)调用痕迹 - 这个 BT skill 返回的结果会被上层 agent 消费
- BT skill 会把结构化结果写入
ctx.skill_result_key桥接到的 runtime key(通常就是SkillNodeConfig.keys.skill_result),run_bt_skill再把这个值暴露为 tool output,而外层宿主仍然可以单独生成自己的final_answer - skill 的打包形式已经从“一个 prompt 文件”升级成“一个可运行子树”
怎么理解这一层分工¶
可以先按下面记:
SKILL.md- 声明这个 skill 的名字、模式和元数据
tree.py- 定义这个 skill 真正执行的行为树
SkillNode- 把 skill 接到 agent 主路径里,并把 BT skill 暴露成
run_bt_skill - 对单个
orchestration: directBT,不创建外层 ReAct Agent- 驱动整个示例运行,但不是 BT skill 自身的封装层