news 2026/9/24 9:51:32

PocketFlow Agent Skills 实战:用 Markdown 技能文件在 Graph 中构建可路由的 LLM Agent

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PocketFlow Agent Skills 实战:用 Markdown 技能文件在 Graph 中构建可路由的 LLM Agent
  • 人工智能
  • 大模型
  • AI Agent
  • 工作流自动化
  • RAG

【免费下载链接】PocketFlow

Pocket Flow: 100-line LLM framework. Let Agents build Agents!

项目地址:https://gitcode.com/gh_mirrors/poc/PocketFlow
点击查看免费下载

本指南基于 PocketFlow 官方 cookbook 中的pocketflow-agent-skills示例,讲解如何在 PocketFlow 图(Graph)中以最轻量的方式集成Agent Skills:把技能写成可复用的 Markdown 指令文件,运行时按用户请求动态选择技能并注入最终 LLM Prompt。读完本文,你将掌握技能文件的路由、注入与执行全流程,并能基于 flow.py、nodes.py、utils.py 的源码级实现,在自己的 PocketFlow 应用中落地这套模式。

什么是 Agent Skills

在 PocketFlow 的语境中,Agent Skills 就是可复用的指令文件(Markdown)。它们不绑定任何特定任务,而是封装"一类任务该怎么做"的专家指令——例如"写给高管看的简报该怎么写"、"如何把需求拆成可执行的清单"。真正的任务文本在运行时才被传入,两者在 Graph 中汇合。

这种设计的核心价值在于:

  • 技能与代码解耦:新增或调整一种能力,只需增删/编辑一个.md文件,无需改动 Python 逻辑;
  • 运行时路由:同一个 Graph 可以服务多种任务,由路由节点根据用户请求挑选最合适的技能;
  • Prompt 工程可维护:长指令从代码中剥离,集中存放在skills/目录,便于非工程师协作维护。

示例仓库把技能保存在本地skills/*.md文件里,整个演示只做三件事:选择技能 → 注入 Prompt → 执行任务

整体流程:两个节点的微型 Graph

示例的完整流程是一个只有两个节点的有向图:

  1. SelectSkill根据用户请求挑选技能文件(例如executive_brief还是checklist_writer);
  2. ApplySkill读取该技能,携带技能指令执行 LLM 任务。

图的装配代码在 flow.py 中,只有寥寥几行:

from pocketflow import Flow from nodes import SelectSkill, ApplySkill def create_flow(): select_skill = SelectSkill() apply_skill = ApplySkill() select_skill >> apply_skill return Flow(start=select_skill)

这里的>>是 PocketFlow 提供的**默认转移(default transition)**操作符:SelectSkill执行完毕后自动进入ApplySkillFlow(start=select_skill)则声明了入口节点。从 pocketflow/init.py 的源码可以看到,__rshift__底层等价于next(other),即在successors字典中注册"default"动作对应的后继节点;Flow 的_orch编排循环会不断执行当前节点、读取其post返回值作为动作、再查找后继节点,直到没有后继为止。

SelectSkill:确定性的技能路由

SelectSkill 节点 遵循 PocketFlow 标准的prep → exec → post三阶段生命周期:

class SelectSkill(Node): def prep(self, shared): return { "task": shared["task"], "skills": load_skills(shared["skills_dir"]), } def exec(self, prep_res): task = prep_res["task"].lower() skills = prep_res["skills"] # Tiny deterministic router for demo purposes. if "checklist" in task or "steps" in task: preferred = "checklist_writer" else: preferred = "executive_brief" if preferred in skills: return preferred, skills[preferred] # fallback: first available skill name, content = next(iter(skills.items())) return name, content def post(self, shared, prep_res, exec_res): skill_name, skill_content = exec_res shared["selected_skill"] = skill_name shared["selected_skill_content"] = skill_content return "default"

三个阶段的职责分工清晰:

  • prep(准备):只做纯数据读取——从shared共享存储取出任务文本,并调用load_skills加载全部技能。shared是贯穿整个 Graph 的共享字典,由入口 main.py 初始化(包含taskskills_dir两个键)。
  • exec(执行):实现路由逻辑。示例刻意保持确定性路由(demo 级实现,无需 LLM 参与):任务文本中包含checkliststeps关键词时选择checklist_writer,否则默认选择executive_brief;若首选技能不存在,则回退到第一个可用技能。该函数只依赖入参、无副作用,便于单测。
  • post(后处理):把exec的结果(技能名 + 技能内容)写回shared,并返回动作字符串"default",驱动 Flow 沿默认边进入下一个节点。

这种"数据在 prep 取、逻辑在 exec 算、状态在 post 存"的划分,正是 PocketFlow 设计哲学——prep/exec/post的解耦让exec可以被独立重试(见下文底层机制),也让路由这类逻辑可以脱离 LLM 单独验证。

ApplySkill:把技能注入 Prompt 并执行

ApplySkill 节点 负责真正"干活":把选中的技能指令与用户任务拼接成一个结构化 Prompt,交给 LLM:

class ApplySkill(Node): def prep(self, shared): return { "task": shared["task"], "skill_name": shared["selected_skill"], "skill_content": shared["selected_skill_content"], } def exec(self, prep_res): prompt = f""" You are running an Agent Skill. Skill name: {prep_res['skill_name']} Skill instructions: --- {prep_res['skill_content']} --- User task: {prep_res['task']} Follow the skill instructions exactly and return the final result only. """.strip() return call_llm(prompt) def post(self, shared, prep_res, exec_res): shared["result"] = exec_res return "default"

Prompt 模板在prep阶段从shared中读取技能名、技能正文与用户任务,然后按"技能身份声明 → 指令边界(用---分隔)→ 用户任务 → 输出约束"的结构组装。其中"Follow the skill instructions exactly and return the final result only."是关键的输出约束指令,要求模型严格遵循技能规则且只返回最终结果,避免模型输出解释性杂音。

LLM 调用封装在 utils.py 的 call_llm 中,默认使用 OpenAI SDK 与gpt-4o模型,API Key 从环境变量OPENAI_API_KEY读取:

def call_llm(prompt: str) -> str: client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY", "your-api-key")) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": prompt}], ) return response.choices[0].message.content

最终生成结果写入shared["result"],由入口程序打印输出。

技能加载:utils.py 的 load_skills

load_skills 是整个技能机制的"仓储层",实现极其轻量:

def load_skills(skills_dir: str) -> dict[str, str]: skills = {} for md_file in sorted(Path(skills_dir).glob("*.md")): skills[md_file.stem] = md_file.read_text(encoding="utf-8") if not skills: raise ValueError(f"No skill files found in {skills_dir}") return skills

要点:

  • Path.glob("*.md")扫描技能目录下所有 Markdown 文件,文件名(去掉.md后缀)即技能 ID,例如checklist_writer.md"checklist_writer"
  • 按文件名排序后返回{技能ID: 文件全文}字典,保证路由结果可复现;
  • 目录为空时抛出ValueError快速失败,避免下游拿到空技能集静默出错。

技能目录路径通过shared["skills_dir"]传入,入口默认值为"skills"(见 main.py),因此你可以自由替换为任意目录而不改任何节点代码。

编写自己的 Agent Skills

技能文件本质是写给 LLM 的指令模板。示例自带两个技能,展示了两种风格:

executive_brief.md——面向高管的简报技能:

# Executive Brief Skill You are writing for senior leaders. ## Rules - Keep it concise and decision-oriented. - Start with 3 bullet point summary. - Include risks and recommended next action. - Avoid implementation-level details unless critical.

checklist_writer.md——面向任务拆解的清单技能:

# Checklist Writer Skill Convert requests into clear, actionable checklists. ## Rules - Use numbered steps. - Keep each step short and verifiable. - Highlight dependencies and blockers. - End with a "Definition of Done" section.

编写技能文件的实践建议:

  • 第一行用标题声明技能身份与适用场景,让模型(和未来的你)快速理解"这个技能是干嘛的";
  • ## Rules小节收敛规则,规则条目要具体、可验证,避免"写得好一点"这类模糊表述;
  • 针对受众或输出形态给出强约束(如"面向高管、省略实现细节""以 Definition of Done 结尾"),这是技能与普通 Prompt 的最大差异——它固化的是"专业角色的行为准则";
  • 新增技能只需在skills/下添加一个.md文件,并同步更新路由节点(或改用下文介绍的 LLM 路由)。

运行与命令行用法

运行依赖在 requirements.txt 中声明:

pocketflow>=0.0.1 openai>=1.0.0

完整启动步骤(以 Bash 为例):

pip install -r requirements.txt export OPENAI_API_KEY="your-key" python main.py --"Summarize this launch plan for a VP audience"

命令行入口解析逻辑见 main.py 的 parse_task:扫描sys.argv[1:],取第一个以--开头的参数、去掉前缀后作为任务文本;若未提供任何--参数,则使用默认任务"Summarize this launch plan for a VP audience"

换一个任务,测试清单路由分支:

python main.py --"Turn this into an implementation checklist"

程序运行后会依次打印:任务文本、选中的技能名(=== Skill Used ===)以及 LLM 生成结果(=== Output ===)。第一个任务因不含checklist/steps关键词会路由到executive_brief,第二个任务则会命中checklist_writer——你可以据此直观验证路由行为。

底层机制:PocketFlow 的 prep/exec/post 生命周期

技能路由之所以能写得如此简洁,得益于 PocketFlow 极简的图抽象。核心实现在 pocketflow/init.py:

  • Node三阶段协议prep(shared)从共享存储准备数据 →exec(prep_res)执行纯逻辑 →post(shared, prep_res, exec_res)回写状态并返回动作字符串。prep返回什么,exec就接收什么;exec返回什么,post就接收什么——类型与数据流完全由开发者掌控;
  • 默认转移>>与条件转移-a >> b注册 default 后继;a - "action" >> b则按动作名注册,post返回的动作字符串决定走向哪条边。Flow 的_orch循环据此持续推进,直到get_next_node找不到后继为止;
  • Node的容错Node(max_retries=1, wait=0)支持对exec的自动重试,exec_fallback可自定义兜底逻辑——这对 ApplySkill 这类包含不稳定 LLM 调用的节点尤其有用,可以显著提升健壮性;
  • shared共享存储:全 Graph 共享一个字典,正是 SelectSkill 写入selected_skill、ApplySkill 读取它的通道。

从 tests/test_flow_basic.py 可以印证这套约定:设计用于默认转移(>>)的节点,其post应返回None(不指定动作);设计用于条件转移(-)的节点,则必须返回动作字符串。示例中两个节点的post都显式返回"default",与>>连接方式完全对应。

从 Demo 到生产:可扩展方向

示例刻意保持了最小化,但从源码结构看,向生产环境演进有清晰的路径:

  • 把确定性路由换成 LLM 路由:在 SelectSkill 的exec中调用call_llm,让模型根据任务语义打分选技能,即可支持更复杂的任务语义匹配;确定性路由则保留作为快速回退。
  • 技能数量规模化load_skills返回的字典天然支持任意数量技能;当技能较多时,可引入技能描述清单(每个技能配一行摘要)辅助路由,避免把全部技能正文塞进路由 Prompt。
  • Batch 化处理:若一批任务需要套用同一技能,可将 SelectSkill 换成BatchNode,或利用 PocketFlow 的 BatchFlow/AsyncFlow 做并行批量执行。
  • 技能版本与校验:由于技能即文件,可以接合 Git 做版本管理;在load_skills中增加前置校验(如必含## Rules小节)即可防止劣质技能进入 Prompt。

小结

Agent Skills 与 PocketFlow 的组合,本质上是一种"指令即数据"的架构模式:Graph 负责流程,技能文件负责专业知识,LLM 负责执行。pocketflow-agent-skills示例用两个节点、一个目录加一个 CLI 入口,就把"按需路由技能 → 注入 Prompt → 生成结果"的完整链路跑通。这种模式几乎不引入框架负担(核心库仅约 100 行),却能让你的 Agent 能力按文件粒度无限扩展——这正是 PocketFlow"轻量、表达力强"设计理念的最佳注脚。

  • 人工智能
  • 大模型
  • AI Agent
  • 工作流自动化
  • RAG

【免费下载链接】PocketFlow

Pocket Flow: 100-line LLM framework. Let Agents build Agents!

项目地址:https://gitcode.com/gh_mirrors/poc/PocketFlow
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 9:48:55

STM32开发环境搭建:ST-LINK驱动安装与Keil调试实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 9:44:08

马赫-曾德尔调制器π/2偏置控制:从半波电压到闭环稳定实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 9:44:00

混合型分布式入侵检测系统设计与Python实现解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 9:30:56

静默电影感lr预设|低饱和日系电影人像写真Lightroom下载lr调色风格!

调色介绍这套静默电影感lr预设,是那种看起来不争不抢,但越看越有味道的类型。你下载导入Lightroom之后,它不会把颜色拉得很鲜艳,也不会刻意把对比度做得很高,而是让整个画面保持在一个低饱和、柔和的状态,像…

作者头像 李华