smolagents v1.26.0 入口扫描
B17(Day 161-170)把 outcome 指标仪表盘 + 配对 A/B 收口——我们手里已经有了「用独立金标 + 真实成本/时延 + 配对 A/B」打出来的真值(V4-Pro 89.7% vs V4-Flash 79.3%、Δ+10.3pp、cost $0.0139/run)。
阶段: B18 · OSS 收口 + 英文 + 全局 SOTA 复核(Day 171-180) 标签: #smolagents #code-agent #tool-calling #mcp
今日导引(由浅入深)
B17(Day 161-170)把 outcome 指标仪表盘 + 配对 A/B 收口——我们手里已经有了「用独立金标 + 真实成本/时延 + 配对 A/B」打出来的真值(V4-Pro 89.7% vs V4-Flash 79.3%、Δ+10.3pp、cost $0.0139/run)。
B18 是整条 B1→B18 能力曲线的最后一段:把内功对外——读主流 OSS agent 框架的真源码、做全局 SOTA 复核、写英文 writeup、走真实 OSS 贡献流程。
今天是 B18 开篇,先扫 Hugging Face smolagents v1.26.0 的入口,搞清楚它的两类 agent 范式(CodeAgent vs ToolCallingAgent),并和本仓刻意做成「零模型回合、纯 TS、可重放」的 src/agent/mcp/toolRegistry.ts 做对照。紧接昨天「内部 eval 收口」,通向明天的「外部评测框架(DeepEval/Inspect AI)」。
最小可判定产出:一份对照 transcript.md(smolagents 真模型回合的 tool-call 轮数 vs 本仓 mock 的零回合执行),其中本仓侧对照物已就绪、smolagents 侧标「待跑(需 key)」。
一句话锚点:今天不是「学会用 smolagents」,而是「读懂主流 agent 框架的工具编排范式,并能说清本仓为什么选确定性 mock 换 CI 可重放」——这是 B18「内功对外」的第一块砖。
1. 机理精读
两类 agent 范式的定义。 smolagents(Hugging Face 维护的轻量 agent 库,本日扫的版本号为 v1.26.0)把 agent 主循环分成两条路线:
CodeAgent:LLM 不输出结构化的工具调用 JSON,而是直接生成一段 Python 代码作为 action,这段代码在受限沙箱里执行,代码里可以调用注册进来的 tool(如web_search(...))。ToolCallingAgent:走传统的结构化 JSON tool-call 协议,每一步模型产出一个{name, arguments}形态的调用,更贴近 OpenAI / Anthropic 原生 function-calling 的报文形状。
为什么 CodeAgent 这样设计:用代码当 action 减少往返轮数。 ToolCallingAgent 每调一个工具就是一个「模型生成 → 执行 → 把结果喂回模型」的回合;要串三个工具就是三个回合。
CodeAgent 让模型把多个 tool 调用组合进一段代码——results = web_search(q); top = results[0]; detail = visit(top.url)——一次生成就能编排多步,理论上把 N 个回合压成 1 个。这正是 smolagents 文档主推 CodeAgent 的核心论据:代码是比 JSON 更自然的「组合多步动作」的载体。依据:Hugging Face smolagents docs (2026-01)。
关键权衡:表达力 vs 安全/可控。 CodeAgent 的代码即 action 带来表达力,代价是必须有沙箱——LLM 生成的任意 Python 要在隔离环境跑(smolagents 提供本地受限执行 + E2B/Docker 远程沙箱选项),否则就是远程代码执行风险。ToolCallingAgent 没有「执行任意代码」这层风险面,但牺牲了组合性、回合更多。这是一对正面权衡:谁拿走表达力,谁就接过沙箱的安全债。
把这对权衡再拆细,有三条次级取舍值得记住:
- 可调试性:CodeAgent 的中间状态是 Python 变量,出错时 traceback 直接指向哪一步炸了;ToolCallingAgent 的中间状态散在多个回合的 JSON 里,串联调试更绕。
- token 成本:ToolCallingAgent 每回合都要把「历史 + 上一步结果」重新塞进 context,多回合 ⇒ 重复前缀膨胀;CodeAgent 单段代码省掉了这部分往返重发,但代码本身可能更长。
- 可观测埋点:ToolCallingAgent 的每个
{name, arguments}是天然的 span 边界,OTel GenAI 埋点对得很齐;CodeAgent 一段代码里串多个 tool,要在沙箱里逐 call 打点才能拿到同等粒度。
与本仓 toolRegistry 的边界。 本仓 src/agent/mcp/toolRegistry.ts 走的是第三条路:它既不是 CodeAgent 也不是真的 ToolCallingAgent,而是把「工具暴露给 LLM 的契约层」(MCP 2026-07-28 stateless 语义的协议形状:tools/list + tools/call + JSON-Schema 校验)抽出来,做成进程内、确定性、纯 TS 的 mock——刻意避开真模型回合,让 CI 可重放。
换句话说:smolagents 是「真模型驱动的 agent 运行时」,本仓 toolRegistry 是「不依赖模型的协议骨架」。两者不是竞品,是同一条链上的不同切片——smolagents 演示「模型怎么编排工具」,toolRegistry 演示「工具契约层长什么样、怎么单测」。
这条边界很重要:明天起的 OSS 复核都建立在「我能读懂真框架,但本仓选择用确定性 mock 换 CI 可重放」这个自洽叙事上。
入口扫描要看的三个面(读 repo 时的 checklist)。 扫一个 agent 框架入口,不是只看 README 跑通 demo,而是带着三个问题读源码:
- action 表示:模型的 action 是代码还是结构化 tool-call?(决定沙箱需求与回合数)
- 工具契约:工具怎么声明(name/description/schema)、怎么发现、入参怎么校验?(这正是本仓 toolRegistry 抽出来的层)
- 停机与错误:主循环何时停(达成目标 / 步数上限),工具抛错怎么回灌给模型?
smolagents 的 CodeAgent/ToolCallingAgent 在这三面给的答案,本仓 toolRegistry.ts 都有对应物(schema 校验 + JSON-RPC error 折叠),区别只在「跑不跑真模型」。
2. 推导 / 手算 / 代码走读
今天是代码对照日。已用 Read 打开 src/agent/mcp/toolRegistry.ts,走读其真实符号与零回合行为(这是 transcript.md 里「本仓侧」的对照物):
McpToolRegistry.register(spec, handler)(line 151):把一个内部 TS 函数注册成 MCP 工具。它做三道防线——工具名必须匹配/^[a-zA-Z][\w.-]*$/、重名直接抛错(避免静默覆盖)、inputSchema.type必须是'object'。注册是纯内存Map,无网络。list()(line 169):对应 MCPtools/list工具发现,返回按name稳定排序的 spec 列表,注释明确标「stateless:不依赖任何会话,结果可被客户端按 ttl 缓存」——这正是 MCP 2026 stateless core 的形状。call(name, args)(line 183):对应tools/call。关键行为顺序——先validate(t.spec.inputSchema, args)按声明 schema 校验,校验失败抛McpCallError(RPC.INVALID_PARAMS, ...);通过后才t.handler(args);handler 自身抛错被包成McpCallError(RPC.INTERNAL_ERROR, ...)。整个调用没有任何模型回合——给定 args,输出由 handler 纯函数式决定,这就是「零回合执行」。handle(req)(line 199):JSON-RPC 2.0 信封版 dispatch,注释标「永不抛错:所有失败折成 response.error」,符合 JSON-RPC 语义。tools/list/tools/call/ 未知 method 三分支齐全,未知 method 返回RPC.METHOD_NOT_FOUND。validate(schema, value, path)(line 112):教学用 JSON-Schema 子集校验器,覆盖 type / enum / minLength / minimum / maximum / array.items 递归 / object.required + properties 递归。type 不符则早返回不再深入(line 117 注释)。这是 smolagents tool 入参校验在本仓的对应物——只是本仓把它做成确定性可单测。
轮数对照(手算): 一个「搜索 → 取首条 → 取详情」的任务:
- smolagents
CodeAgent:理论 1 段代码即可串完三步 ≈ 1 回合(但实测含纠错重试,seed 预期 3-5 turns); - smolagents
ToolCallingAgent:三步三回合 ≈ 3 回合; - 本仓
toolRegistry.call:给定 args 直接 handler,0 模型回合(执行是纯函数)。
对照的洞察:本仓不是「更快的 agent」,而是「把 agent 协议层从模型不确定性里解耦出来,换 CI 可重放」——这是写进 transcript.md 的论点。
为什么本仓选「零回合协议骨架」而非真跑 agent(再推一层): CI 的第一性原理是可重放。真模型回合每次输出都可能不同(温度、版本漂移、限流),把它放进 CI 会让测试时绿时红、无法定位是代码退化还是模型抖动。
本仓把「工具契约层」从「模型推理层」切开——契约层(注册/发现/校验/调用)用纯 TS 做成确定性可单测,推理层(真模型回合)留给 scripts 下的接线脚本、需 key 时才跑。这条切法和 dsdb-lab 浏览器内确定性教学装置同理:把可确定的部分锁死进 CI,把不可确定的部分隔到 key-gated 边界外。
3. 今日实战
按 seed 落地(指向真实路径与命令):
git clone https://github.com/huggingface/smolagents,按官方 quickstart 起一个CodeAgent,挂 DuckDuckGo 搜索 tool,模型用model=LiteLLMModel("deepseek/deepseek-v4-flash")(key 已配,走 LiteLLM 适配 DeepSeek)。- 跑几个多步任务,记录每个任务的 tool-call 轮数(CodeAgent 预期 3-5 turns)。
- 在本仓侧用
src/agent/mcp/toolRegistry.ts的register+call起一组等价工具(确定性 handler),记录其零模型回合执行路径。 - 把两侧轮数与执行语义写进
transcript.md,committed。 - 本仓对照物的可信度由测试套件背书:
toolRegistry.ts在本仓 423 测试套件中绿。
4. 今日实测 / 产出
- smolagents 真模型回合 → 待跑(需 key 跑 smolagents 真模型回合);将产出
transcript.md+ 轮数(预期 3-5 turns,非已测真值)committed。 - 本仓侧对照物已就绪:
toolRegistry.ts在 423 测试套件中绿。 - 不臆造 smolagents 实测轮数——seed 标「预期」即写「预期」,不写「实测得到」。
5. 常见误区 / 陷阱
- 把 CodeAgent 当「更智能」而非「不同权衡」:CodeAgent 省回合的代价是必须有沙箱,把它当无脑首选会忽略 RCE 风险面。
- 把本仓 toolRegistry 当 agent 运行时:它是协议契约层 mock,不跑模型;不要在 transcript 里声称它「执行了 agent 推理」。
- 把 mock 的零回合当「比 smolagents 快」:零回合是因为没跑模型,不是更快的 agent;混淆两者会让对照叙事失真。
- 版本号不复验:smolagents v1.26.0 是本日扫到的号,当周必须在 PyPI 复验(agent 库迭代快)。
- 拿 LiteLLM 模型 id 当真值数字:seed 的 3-5 turns 是预期区间,不是测出来的;混入 transcript 当实测会破坏诚信底线。
- 沙箱当摆设:跑 CodeAgent 不开沙箱(直接本地 exec LLM 生成的 Python)等于自挖 RCE 坑——本地试也应走受限执行或容器隔离。
- 把「省回合」当唯一指标:回合数只是一个维度,可调试性 / token 成本 / 埋点粒度同样影响生产选型,不能只看 turns。
6. 学习资源(每条带 YYYY-MM)
- Hugging Face, smolagents documentation(CodeAgent vs ToolCallingAgent 范式)— 2026-01
- Hugging Face, smolagents GitHub repo(v1.26.0,PyPI 版本号当周复验)— 2026
- Anthropic, Model Context Protocol — stateless core / tools 语义(2026-07-28 最终规范,RC 2026-05-21 锁定)— 2026-05
- MCPTox benchmark(工具投毒攻击成功率最高 72%)/ NIST CAISI AI Agent 标准(2026-02 启动)— 2026-02(本仓 toolRegistry.ts 头注引用)
- LiteLLM, provider 适配文档(统一 OpenAI-compatible 接口接 DeepSeek,供 smolagents
LiteLLMModel用)— 2026 - 本仓
src/agent/mcp/toolRegistry.ts(进程内 MCP stateless 协议形状 mock,零回合对照物)— 2026
SOTA检查 (2026-06 更新)
- 当前主流:smolagents 仍是 Hugging Face 主推的轻量 agent 框架,CodeAgent 范式与 2026 context-engineering 主线一致,非过时。本仓 toolRegistry 复刻的 MCP stateless 协议形状对齐 2026-07-28 规范方向。
- 是否仍 SOTA:是(轻量 agent 框架赛道)。但 v1.26.0 版本号当周需在 PyPI 复验——agent 库半衰期约 6 个月,版本漂移快。
- 过时黑名单:避免引用已停更的 transformers-agents(旧 Agent API,已被 smolagents 取代);避免把 AutoGen/SK 当主线(维护模式)。
- 安全前沿:MCPTox(2026)测得工具投毒攻击成功率最高 72%,NIST CAISI AI Agent 标准 2026-02 启动——真实 MCP server 必须零信任校验工具描述/参数,本仓 schema 校验只是该防线最小演示。
- 下次复查点:2026-07-28 MCP 最终规范定稿日(server 构建须排其后);每周一 WebSearch 复刷 smolagents PyPI 版本号。
衔接
- 昨天:Day 170 — Block 收口 + SOTA 检查(B17 用独立金标 + 真实成本/时延 + 配对 A/B 收口,留下 V4-Pro 89.7% / V4-Flash 79.3% / Δ+10.3pp not-sig@N=29 真值)
- 今天:扫 smolagents v1.26.0 入口,理清 CodeAgent vs ToolCallingAgent 两范式,与本仓零回合 toolRegistry 做对照
- 明天:Day 172 — DeepEval + Inspect AI 评测框架(从「框架的 agent 主循环」转到「框架的评测口径」,对照本仓 cohensKappa/agentEval)