09 Agent 代码模板:从通用骨架映射到 SecurityClaw
结论先说:通用 Agent 模板没有价值,真正有价值的是“模板如何落地到真实系统” #
你在网上能看到无数 Agent 模板,核心都差不多:
输入 -> 规划 -> 执行 -> 评估 -> 继续或结束
问题不在这四个词对不对,而在:
- 这些词对应代码里的什么结构
- 状态字段怎么拆
- 技能和工具怎么接进循环
- 停止条件和恢复路径怎么定义
SecurityClaw 的价值就在这里:它不是讲概念,而是把这套模板落成了可运行的骨架。
一、先看最小骨架:AgentState 是整个模板的地基 #
class AgentState(TypedDict):
question: str
plan: list[dict]
skill_results: list[dict]
step_count: int
max_steps: int
evaluation: str
trace: list[dict]
这 7 个字段就够搭起一个多步 Agent。把它们重新分类,会更容易理解:
1.1 输入层 #
question
1.2 规划层 #
planstep_countmax_steps
1.3 执行层 #
skill_results
1.4 评估与记忆层 #
evaluationtrace
你会发现,一个通用 Agent 模板真正需要的不是“很多能力”,而是少量但边界清晰的状态字段。
二、通用模板如何映射到真实节点 #
在 SecurityClaw 里,这套模板被拆成图中的几个节点:
flowchart TD
Start((开始)) --> Decide[decide_node]
Decide --> Execute[execute_node]
Execute --> Evaluate[evaluate_node]
Evaluate --> ShouldLoop{should_loop}
ShouldLoop -- 继续 --> Decide
ShouldLoop -- 结束 --> Format[format_response_node]
Format --> End((结束))
这张图里,每个节点都不是“业务功能”,而是“模板的一部分”。
2.1 decide_node #
模板里的“规划”
2.2 execute_node #
模板里的“执行”
2.3 evaluate_node #
模板里的“判断结果是否足够”
2.4 should_loop #
模板里的“继续还是停止”
2.5 format_response_node #
模板里的“给用户一个最终回答”
这意味着一件很重要的事:
模板不是抽象 PPT,而是能一一对应到真实函数边界。
三、decide_node 真正负责的不是“思考”,而是产出可验证计划 #
def decide_node(state: AgentState) -> dict:
if state["step_count"] == 0:
plan = llm_parse_plan(state["question"])
else:
plan = llm_replan(state["question"], state["trace"], state["evaluation"])
validated_plan = validate_plan(plan)
return {
"plan": validated_plan,
"step_count": state["step_count"] + 1,
}
这里最重要的不是 LLM 生成 plan,而是:
validated_plan = validate_plan(plan)
也就是说,模板落地到真实项目后,规划不是“模型说了算”,而是:
模型产出计划
-> 代码验证计划
-> 只有通过验证的计划才能进入执行层
这是通用 Agent 模板和真实工程之间最核心的差别。
四、execute_node 把“工具调用”变成“技能调用” #
通用模板通常写成:
result = tool(action)
但在 SecurityClaw 里,执行层更像:
def execute_node(state: AgentState) -> dict:
results = []
for step in state["plan"]:
skill_func = registry.get(step["skill"])
ctx = build_context(state)
output = skill_func.run(ctx, **step["parameters"])
results.append({
"skill": step["skill"],
"output": output,
"error": None,
})
return {"skill_results": results}
这说明了一个关键映射 #
通用模板里的 tool #
在这里变成了 skill.run(context, **kwargs)
通用模板里的“环境” #
在这里变成了 Context
通用模板里的“结果” #
在这里变成了结构化的 skill_results
所以你可以把 SecurityClaw 理解成:
用技能系统,把通用 Agent 模板中的“工具调用位”填成了真正可扩展的能力层。
五、为什么 trace 比很多人想象的重要 #
很多 Agent 模板只保留:
- 当前问题
- 当前计划
- 当前结果
但 SecurityClaw 多保留了一个 trace。
trace: list[dict]
它的意义不是“方便打印日志”,而是让系统有机会:
- 做再规划
- 做恢复
- 输出失败解释
- 写入 checkpoint
- 做后续 RAG 检索
也就是说,模板里的 trace 不是装饰字段,而是把一次执行过程变成可重复利用的证据链。
这一步是很多网上 Agent demo 没做的,所以它们看起来能跑,但一失败就只会说: “抱歉,我没有完成。”
而不是: “我尝试了哪些路径、为什么失败、还能不能继续。”
六、停止条件才是模板真正的灵魂 #
模板最容易被写浅的地方,就是最后的 if done(): break。
在真实系统里,“结束”至少有三种完全不同的含义:
- 成功结束:答案已经足够
- 预算结束:步数或 token 用尽
- 失败结束:没有可恢复路径了
def should_loop(state: AgentState) -> Literal["decide", "finish"]:
if state["evaluation"] == "SUCCESS":
return "finish"
if state["step_count"] >= state["max_steps"]:
return "finish"
if state["evaluation"] == "ERROR" and no_new_paths(state):
return "finish"
return "decide"
你看,这里的“结束”不是一个布尔值,而是一个状态判断系统。
这就是为什么我说:
Agent 模板最有价值的部分,不是 Planning,而是 Stopping。
七、通用模板在真实项目里要补上的四件事 #
如果你把一个抽象 Agent 模板真正落地,至少要补四层工程约束:
7.1 计划验证 #
模型说的不一定能执行
7.2 运行时上下文注入 #
技能不能自己乱连依赖
7.3 结构化结果记录 #
执行结果不能只是一段自然语言
7.4 停止与恢复 #
失败时不能只有“重试”这一种手段
没有这四层,模板只是“会循环的 prompt”。
八、这一篇真正要你记住的框架 #
把通用 Agent 模板映射到真实工程,可以记成这张表:
| 抽象模板 | SecurityClaw 中的落点 | 真正解决的问题 |
|---|---|---|
| 输入 | question | 用户意图进入系统 |
| 规划 | decide_node + plan | 把问题变成可执行步骤 |
| 执行 | execute_node + skill.run() | 调用真实能力 |
| 评估 | evaluate_node + evaluation | 判断结果是否够用 |
| 记忆 | trace | 让失败、恢复和解释成为可能 |
| 停止 | should_loop | 控制何时继续、何时结束 |
如果你能把这张表讲清楚,你就不是“知道 Agent 模板长什么样”,而是真的理解它怎么落地。
九、验证命令 #
python -m pytest tests/test_core/test_chat_router/test_logic.py -v --tb=short
如果你只想看循环是否正确终止:
python -m pytest tests/test_core/test_chat_router/test_logic.py -k "loop or finish or evaluate" -v