本节摘要:本节引入全书的攀爬主线——官方文档
docs/source/en/conceptual_guides/intro_agents.md中的 agency 等级表。agency(LLM 对程序流程的控制权)不是 0/1 的开关,而是连续光谱:从"LLM 输出完全不影响流程"到"LLM 用代码自定义工具、启动其他 agent",共六级。本节逐级解读这张表,标出本教程各章对应哪一级;然后用pip install smolagents加三行代码跑通第一个 CodeAgent;最后讲清 CodeAgent 与 ToolCallingAgent 的选型逻辑与smolagent/webagent两个 CLI 命令。
内容来源:原项目源码
docs/source/en/conceptual_guides/intro_agents.md(agency 等级表与多步 agent 伪码)、src/smolagents/cli.py(CLI)、README.md(quickstart)。
⚠️ 注意:官方对 agency 的核心定义是"AI Agent 是 LLM 输出控制工作流的程序"。如果固定流程已经够用,就别上 agent——文档原话建议"regularize towards not using any agentic behaviour"(向不用 agent 的方向收敛),agent 是给"流程无法预先确定"的任务准备的。
阅读完本节,你应当能够:
smolagent 交互式向导与 webagent 命令。官方定义:"agent 不是离散定义,agency 在一个连续光谱上演化,取决于你给 LLM 多少流程控制权"。原表如下(中译):
| 等级 | 描述 | 简称 | 示例代码 |
|---|---|---|---|
| ☆☆☆ | LLM 输出不影响程序流程 | 简单处理器 | process_llm_output(llm_response) |
| ★☆☆ | LLM 输出控制一个 if/else 分支 | 路由器 | if llm_decision(): path_a() else: path_b() |
| ★★☆ | LLM 输出控制函数执行 | 工具调用 | run_function(llm_chosen_tool, llm_chosen_args) |
| ★★☆ | LLM 输出控制循环与程序继续 | 多步 Agent | while llm_should_continue(): execute_next_step() |
| ★★★ | 一个 agent 工作流可以启动另一个 | 多智能体 | if llm_trigger(): execute_agent() |
| ★★★ | LLM 以代码行动,可自定义工具/启动 agent | 代码 Agent | def custom_tool(args): ... |
黑星(★)越多,LLM 掌握的控制权越大,系统的"自主性"越高,但不确定性也随之增加。注意两点:
while 循环才成为完整的 agent——第 2 章的 ToolCallingAgent 就住在这两行之间。把等级表对齐到本书的攀爬路径:

第 4-7 章不上星——它们是攀爬的装备区(记忆/工具/沙箱/模型),为已到达的星级提供工程纵深。
官方文档还给出多步 agent 的骨架伪码,这就是第 2 章将要精读的 MultiStepAgent 的雏形:
memory = [user_defined_task] while llm_should_continue(memory): # 这个循环是"多步"的部分 action = llm_get_next_action(memory) # 这是"工具调用"的部分 observations = execute_action(action) memory += [action, observations]
四行伪码 = 记忆 + 循环 + 动作 + 观察。第 2 章你会发现 agents.py 的 _run_stream 几乎是它的直译。
这张表同时是一份"何时该止步"的清单。官方文档专门写了"When to use agents / when to avoid them":如果你的冲浪旅行网站只有两类请求(查行程知识/联系销售),两个写死的分支(搜索框/联系表单)就是最优解——100% 可靠、零 LLM 不确定性;只有当用户会问"我周一到、护照丢了可能拖到周三、想订周二早上的课还想要取消险"这种预先写不死流程的问题时,才值得把控制权交给 agent(给它天气 API、地图 API、排班表与知识库 RAG)。原则:流程能写死就写死,agent 是给长尾灵活性准备的。
安装:
pip install smolagents # 可选装能力组,例如: pip install "smolagents[openai]" # OpenAIModel 依赖 pip install "smolagents[toolkit]" # 内置工具全家桶(搜索/网页等)
API key 用环境变量提供(OPENAI_API_KEY/HF_TOKEN,或放进 .env 文件——smolagents 必装依赖里的 python-dotenv 会自动加载)。
quickstart(以 OpenAI 模型为例,需设置 OPENAI_API_KEY 环境变量):
from smolagents import CodeAgent, OpenAIModel, WebSearchTool model = OpenAIModel(model_id="gpt-4o-mini") agent = CodeAgent(tools=[WebSearchTool()], model=model) # 一个能搜索的代码 agent agent.run("How many seconds would it take a leopard at full speed to run through Pont des Arts?")
三行代码逐行拆解:
OpenAIModel(...):包装一个 LLM 后端。第 7 章会看到共有 10 个 Model 类可换:TransformersModel(本地)、VLLMModel(本地高性能推理)、MLXModel(Apple 芯片)、InferenceClientModel(HF Hub 的 Inference Providers,支持 Cerebras/Together/Nebius 等十余家)、LiteLLMModel(一个接口调 100+ 云模型)、OpenAIModel/AzureOpenAIModel/AmazonBedrockModel/LiteLLMRouterModel 等,接口统一为 generate(messages) -> ChatMessage。HF 原生写法是 InferenceClientModel()(只需 HF_TOKEN 环境变量)。CodeAgent(tools=[...], model=model):构造 agent。tools 是它能调用的工具列表(这里是官方内置的网页搜索);构造时还会自动补上 final_answer 终止工具(第 2 章 _setup_tools 源码会见到)。常用可选参数:max_steps(默认 20)、additional_authorized_imports=["requests", "bs4"](放行 import)、stream_outputs=True(流式打印 LLM 输出)、executor_type="e2b"(远程沙箱)。agent.run(task):启动 ReAct 循环。LLM 会输出若干段 Python 代码,代码里调用 web_search(...) 查豹子速度与桥长、做除法,最后 final_answer(秒数) 结束,run 返回最终答案。想看逐步细节可传 stream=True 拿生成器逐事件消费,或跑完后调 agent.replay(detailed=True) 回放每步记忆。跑通后你会看到 rich 彩色日志逐条打印:任务、每一步执行的代码、执行日志(Observation)、最终答案。
两个开箱即用的 agent 类(都在 agents.py 中,后两章精读):
| 维度 | CodeAgent |
ToolCallingAgent |
|---|---|---|
| action 形态 | Python 代码块 | JSON 工具调用 |
| 依赖模型能力 | 会写代码即可(几乎所有模型) | 需要较好的原生 tool calling 支持 |
| 步数效率 | 少 30% 步(可组合/可循环) | 一步一调用 |
| 执行环境 | 需要 Python 解释器(本地或沙箱) | 不执行代码,直接调度函数 |
| 官方建议 | 默认推荐 | 模型 tool calling 很强、或不想跑代码时 |
经验法则:优先 CodeAgent——它是 smolagents 的灵魂,也是本书第 3 章的主角;当你使用的模型在 JSON 工具调用上经过特殊强化、或运行环境完全不允许执行生成代码时,退回 ToolCallingAgent。两类 agent 共享同一套 MultiStepAgent 生命周期(第 2 章),区别只在"动作怎么表达与执行"。
smolagent 与 webagentpyproject.toml 注册了两个命令:
[project.scripts] smolagent = "smolagents.cli:main" webagent = "smolagents.vision_web_browser:main"
smolagent:不带参数运行时进入交互式向导(cli.py 的 interactive_mode()),一步步问你——用哪个模型类型/模型 id、加载哪些工具(内置工具名或 Hub Space 的 user/repo 路径)、允许哪些 import、动作类型选 code 还是 tool_calling,然后现场拼出 agent 执行你的 prompt。向导背后是 run_smolagent()(cli.py:219):load_model 按类型实例化模型,工具名带 / 时走 Tool.from_space 从 Hub Space 加载,否则查 TOOL_MAPPING 取内置工具,最后按 action_type 分派:
254 if action_type == "code": 255 agent = CodeAgent(tools=available_tools, model=model, 256 additional_authorized_imports=imports, stream_outputs=True) 258 elif action_type == "tool_calling": 259 agent = ToolCallingAgent(tools=available_tools, model=model, stream_outputs=True)
等价的一条命令(cli.py 支持):
smolagent "Plan a trip to Tokyo, Kyoto and Osaka." \ --model-type "InferenceClientModel" \ --model-id "Qwen/Qwen2.5-Coder-32B-Instruct" \ --imports "pandas numpy" \ --tools "web_search"
webagent:启动 vision_web_browser.py 里的视觉网页 agent——用截屏 + 点击坐标的方式浏览网页,无需读 DOM,是"多模态 agent 实战"的官方示例(第 8 章详解)。
💡 阶梯要点:agency 等级表是"能力光谱"不是"难度排名"——星级越高不代表越好,只代表把越多控制权交给 LLM。工程上先问"流程能不能写死",不能写死再上 agent,再决定要 ★★☆(工具调用循环)还是 ★★★(代码 agent/多智能体)。
MultiStepAgent._run_stream。CodeAgent(tools=[...], model=...) → agent.run(task)。smolagent(交互式向导/一条命令)与 webagent(视觉网页 agent)。docs/source/zh/ 已有 8 篇官方中文翻译(概念指南与教程),可作术语对照参考。下一节进入源码:精读
agents.py的 MultiStepAgent 抽象基类——run/step生命周期、记忆写入与错误体系,这是两类 agent 共享的地基。