把开源 Skills 集成到 LangGraph 项目中,核心是先将开源 Skill 标准化封装为 LangGraph 可识别的"工具/子图",再通过状态机编排调用逻辑。下面我会给你一套通用、可落地的完整流程,包含具体代码示例和适配不同类型开源 Skill 的方法。
一、集成前的核心准备
1. 明确开源 Skill 的类型(先分类,再适配)
不同开源 Skill 的实现形式不同,对应集成方式也不同,先做分类:
| Skill 类型 | 典型示例 | 集成形式 |
|---|---|---|
| 原子函数型 | Anthropic 官方技能库中的"文档解析""代码生成" | 封装为 LangChain Tool |
| 流程任务型 | Superpowers 中的"TDD 开发流程""Git 工作流" | 封装为 LangGraph 子图(Subgraph) |
| 浏览器自动化型 | Vercel Agent Browser、Qoder 的 /browser 技能 | 封装为带外部依赖的 Tool |
| 数据处理型 | Awesome Agent Skills 中的"结构化数据汇总" | 封装为 Tool + 状态处理函数 |
2. 环境依赖安装
先安装 LangGraph 及技能集成所需的核心依赖:
bash
# 核心依赖
pip install langgraph langchain langchain-core langchain-community
# 可选:浏览器自动化/工具调用依赖
pip install playwright python-dotenv # 浏览器操作
playwright install chrome # 安装浏览器驱动
二、通用集成流程(以 Anthropic 开源 Skill 为例)
步骤 1:下载并解析开源 Skill
以 Anthropic 技能库中的 browser-test-skill 为例,先克隆仓库并提取核心逻辑:
bash
# 克隆开源技能库
git clone https://github.com/anthropics/skills.git
cd skills
打开技能目录下的 SKILL.md(技能元数据)和 main.py(核心逻辑),提取关键功能(比如"浏览器自动化测试")。
步骤 2:封装开源 Skill 为 LangChain Tool
这是最基础、最通用的集成方式,把开源 Skill 的核心函数包装成 LangGraph 可调用的 Tool:
python
from langchain.tools import tool
from typing import Optional
# 1. 引入开源 Skill 的核心逻辑(这里模拟 Anthropic 的浏览器测试 Skill)
# 实际使用时替换为你下载的开源 Skill 代码
def run_browser_test(task: str, screenshot: bool = True) -> str:
"""
开源 Skill 核心逻辑:执行浏览器自动化测试
:param task: 自然语言测试指令(如"添加2个商品到购物车并验证数量")
:param screenshot: 是否生成截图
:return: 测试结果 + 截图路径(如有)
"""
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://你的测试网站.com")
# 这里是开源 Skill 的核心操作逻辑(省略具体步骤)
result = f"测试完成:{task},截图已保存至 ./test-screenshot.png"
browser.close()
return result
# 2. 封装为 LangChain Tool(LangGraph 可直接调用)
@tool
def anthropic_browser_test_skill(
task: str,
screenshot: Optional[bool] = True
) -> str:
"""
封装后的开源 Skill:浏览器自动化测试
参数说明:
- task: 自然语言测试指令(必填)
- screenshot: 是否生成测试截图(默认True)
"""
try:
return run_browser_test(task, screenshot)
except Exception as e:
return f"技能执行失败:{str(e)}"
步骤 3:定义 LangGraph 状态与智能体节点
状态是 LangGraph 的核心,所有 Skill 的输入/输出都通过状态传递:
python
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
from typing import List, TypedDict
# 1. 定义智能体状态(必须包含 messages,其他字段按需扩展)
class AgentState(TypedDict):
messages: List[HumanMessage | AIMessage | ToolMessage] # 消息流(核心)
skill_output: Optional[str] # 存储 Skill 执行结果
next_node: str # 控制流程跳转
# 2. 定义智能体决策节点(决定是否调用 Skill)
def agent_decision_node(state: AgentState) -> AgentState:
"""
智能体决策逻辑:根据用户输入判断是否调用开源 Skill
"""
# 获取最后一条用户消息
last_message = state["messages"][-1]
user_input = last_message.content.lower()
# 触发条件:包含"浏览器测试""购物车测试"等关键词时调用 Skill
if any(keyword in user_input for keyword in ["浏览器测试", "购物车测试", "e2e测试"]):
# 告诉智能体下一步调用 Tool 节点
state["next_node"] = "tool_node"
# 追加调用指令到消息流
state["messages"].append(
AIMessage(content="将调用浏览器测试技能执行你的指令")
)
else:
# 不调用 Skill,直接结束
state["next_node"] = END
state["messages"].append(
AIMessage(content="你的指令无需调用技能,任务完成")
)
return state
# 3. 注册封装好的开源 Skill 为 ToolNode
# 把所有封装的开源 Skill 放入工具列表
tools = [anthropic_browser_test_skill]
# 创建 LangGraph 工具节点(自动处理 Tool 调用)
tool_node = ToolNode(tools)
# 4. 定义 Tool 执行后的结果处理节点
def tool_result_node(state: AgentState) -> AgentState:
"""
处理 Skill 执行结果,更新状态
"""
# 获取 Tool 执行结果
tool_result = state["messages"][-1].content
# 保存结果到状态
state["skill_output"] = tool_result
# 处理完成后返回给智能体,结束流程
state["next_node"] = END
state["messages"].append(
AIMessage(content=f"技能执行结果:{tool_result}")
)
return state
步骤 4:编排 LangGraph 并运行
将决策节点、Tool 节点、结果节点串联成图,完成集成:
python
# 1. 创建状态机图
graph = StateGraph(AgentState)
# 2. 添加节点
graph.add_node("agent_decision", agent_decision_node) # 决策节点
graph.add_node("tool_node", tool_node) # Skill 执行节点
graph.add_node("tool_result", tool_result_node) # 结果处理节点
# 3. 定义边(流程跳转规则)
# 起始节点 → 决策节点
graph.set_entry_point("agent_decision")
# 决策节点 → Tool 节点(需要调用 Skill 时)
graph.add_conditional_edges(
"agent_decision",
lambda x: x["next_node"], # 根据 next_node 决定跳转
{
"tool_node": "tool_node",
END: END
}
)
# Tool 节点 → 结果处理节点
graph.add_edge("tool_node", "tool_result")
# 结果处理节点 → 结束
graph.add_edge("tool_result", END)
# 4. 编译图(核心步骤)
app = graph.compile()
# 5. 测试运行(调用集成的开源 Skill)
if __name__ == "__main__":
# 输入:触发开源 Skill 的用户指令
initial_state = AgentState(
messages=[HumanMessage(content="用浏览器测试购物车流程:添加2个商品并验证数量")],
skill_output=None,
next_node=""
)
# 运行图
result = app.invoke(initial_state)
# 输出结果
print("=== 最终结果 ===")
print(result["skill_output"])
print("=== 消息流 ===")
for msg in result["messages"]:
print(f"{msg.type}: {msg.content}")
三、进阶:集成流程型开源 Skill 为子图
对于多步骤的开源 Skill(如 Superpowers 的"TDD 开发流程"),需要封装为子图再嵌入主图:
python
from langgraph.graph import StateGraph
# 1. 定义子图(封装流程型开源 Skill)
def create_tdd_skill_subgraph():
"""
封装 Superpowers 的 TDD 开发流程 Skill 为子图
流程:需求分析 → 编写测试用例 → 编写代码 → 运行测试 → 总结
"""
subgraph = StateGraph(AgentState)
# 子图节点:对应开源 Skill 的每一步
def tdd_analysis_node(state: AgentState) -> AgentState:
# 开源 Skill 逻辑:需求分析
state["messages"].append(AIMessage(content="TDD 第一步:需求分析完成"))
state["next_node"] = "tdd_write_test"
return state
def tdd_write_test_node(state: AgentState) -> AgentState:
# 开源 Skill 逻辑:编写测试用例
state["messages"].append(AIMessage(content="TDD 第二步:测试用例编写完成"))
state["next_node"] = "tdd_write_code"
return state
# 省略其他节点(编写代码、运行测试)...
# 添加子图节点并编排流程
subgraph.add_node("tdd_analysis", tdd_analysis_node)
subgraph.add_node("tdd_write_test", tdd_write_test_node)
# ... 其他节点
subgraph.set_entry_point("tdd_analysis")
subgraph.add_edge("tdd_analysis", "tdd_write_test")
# ... 其他边
subgraph.add_edge("tdd_run_test", END)
return subgraph.compile()
# 2. 在主图中集成子图
if __name__ == "__main__":
# 创建主图
main_graph = StateGraph(AgentState)
# 注册子图(流程型开源 Skill)
tdd_subgraph = create_tdd_skill_subgraph()
main_graph.add_node("tdd_skill", tdd_subgraph)
# 主图决策节点:触发子图
def main_decision_node(state: AgentState) -> AgentState:
if "TDD 开发" in state["messages"][-1].content:
state["next_node"] = "tdd_skill"
else:
state["next_node"] = END
return state
# 编排主图
main_graph.add_node("main_decision", main_decision_node)
main_graph.set_entry_point("main_decision")
main_graph.add_conditional_edges(
"main_decision",
lambda x: x["next_node"],
{"tdd_skill": "tdd_skill", END: END}
)
main_graph.add_edge("tdd_skill", END)
# 编译并运行
main_app = main_graph.compile()
initial_state = AgentState(
messages=[HumanMessage(content="用 TDD 流程开发一个加法函数")],
skill_output=None,
next_node=""
)
result = main_app.invoke(initial_state)
print(result["messages"])
四、关键避坑与优化技巧
- 状态传递要规范 :所有 Skill 的输入/输出必须通过
AgentState传递,禁止使用全局变量,否则多轮调用会出错。 - 异常处理不可少 :在 Tool 封装时加入
try-except,避免单个开源 Skill 崩溃导致整个智能体挂掉。 - 技能触发条件要明确:通过关键词、意图识别(如用 LLM 解析用户输入)触发 Skill,避免误调用。
- 依赖隔离:不同开源 Skill 的依赖可能冲突,建议用虚拟环境(venv)或 Docker 隔离。
- 调试用 LangSmith:开启 LangSmith 跟踪 Skill 调用链路,定位执行中的问题:
python
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "你的 LangSmith API 密钥"
总结
- 开源 Skill 集成到 LangGraph 的核心是分类封装:原子技能→Tool,流程技能→子图。
- 所有 Skill 的输入/输出必须通过 LangGraph 的
State传递,确保流程可追溯。 - 关键步骤:下载解析 Skill → 封装为 Tool/子图 → 编排状态机 → 测试运行。