smolagents 中的 CodeAgent 和 ToolCallingAgent 均继承自 MultiStepAgent,遵循 ReAct(Reason → Act → Observe)循环范式。Agent 接收用户任务后,在每一步中由大语言模型生成行动指令,框架执行后将结果作为观察反馈给模型,循环往复直至任务完成或达到最大步数限制。
Agent 的执行过程由多种步骤类型构成:
所有步骤按顺序存储在 AgentMemory 对象中,构成完整的执行轨迹。
循环在以下三种情况下终止:
final_answer 工具或匹配的工具调用产出最终答案max_steps 设定的上限,抛出 AgentMaxStepsErrorsmolagents 中的工具本质上是带有结构化元数据的 Python 可调用对象。最常用的定义方式是 @tool 装饰器:
from smolagents import tool
@tool
def get_current_weather(city: str) -> str:
"""Returns the current weather for a given city.
Args:
city: Name of the city to check.
"""
return fetch_weather(city)装饰器会自动解析函数签名和文档字符串,生成大语言模型可读的工具描述和参数模式。文档字符串和类型注解直接成为模型决策时的参考信息。
smolagents 支持从多种渠道获取工具:
DuckDuckGoSearchTool、WebSearchTool、Whisper 语音转写工具和浏览器自动化工具Tool.from_hub() 加载社区共享的工具,或通过 Tool.push_to_hub() 分享自定义工具Tool.from_langchain() 直接包装现有 LangChain 工具ToolCollection.from_mcp() 连接任意 MCP 服务器获取工具集Tool.from_space() 将 Hugging Face Space 转换为可调用工具每个工具需具备以下核心属性:
name:工具名称,作为模型调用时的函数标识description:工具功能描述,帮助模型判断何时使用该工具inputs:参数字典,包含每个参数的类型和说明output_type:输出类型标注forward():实际执行逻辑的方法smolagents 采用模型无关(Model-Agnostic)架构,model 参数接受任何符合消息列表到响应映射接口的对象。内置适配器覆盖主流推理后端:
适配器类 | 后端类型 | 安装方式 |
|---|---|---|
InferenceClientModel | Hugging Face Inference Providers(Together、Fireworks 等) | 核心库内置 |
LiteLLMModel | 100+ 提供商(OpenAI、Anthropic、Bedrock 等) | pip install 'smolagents[litellm]' |
TransformersModel | 本地 transformers 流水线 | pip install 'smolagents[transformers]' |
OpenAIServerModel | 任意 OpenAI 兼容端点 | 核心库内置 |
MLXModel | Apple Silicon 本地推理 | pip install 'smolagents[mlx-lm]' |
VLLMModel | 本地 vLLM 服务器 | pip install 'smolagents[vllm]' |
对于希望在本地运行模型的场景,可通过 Ollama 或 vLLM 提供服务,然后将 LiteLLMModel 或 OpenAIServerModel 指向本地端点(如 http://localhost:11434)。这使得 Agent 可以在完全离线、数据不出网络的环境中运行。
更换模型仅需修改一行代码,Agent 的业务逻辑和工具配置保持不变。这种设计避免了被单一供应商锁定,开发者可根据成本、延迟和性能需求灵活选择模型。
CodeAgent 通过 executor_type 参数选择代码执行环境,不同选项在安全性和适用场景上存在差异:
执行器类型 | 安全级别 | 适用场景 |
|---|---|---|
local(默认) | 受限(基于 AST 的导入白名单) | 本地开发、可信环境 |
e2b | 高(云端 Firecracker 微虚拟机) | 生产环境、不可信代码 |
docker | 高(容器隔离) | 自托管、完全控制 |
modal | 高(无服务器容器) | 大规模自动扩缩容 |
blaxel | 高(托管远程执行) | 边缘原生执行 |
wasm | 高(WebAssembly 沙箱) | 浏览器级隔离、边缘部署 |
默认的 LocalPythonExecutor 并非真正的安全沙箱,它通过以下机制提供基础防护:
os、sys、subprocess)的导入eval、exec、os.system 等危险内置函数官方文档明确指出,本地执行器不能用作安全边界,生产环境中处理不可信输入时必须使用远程沙箱执行器。
需要注意的是,沙箱化执行目前不支持多智能体系统,架构设计时应将不可信输入的处理隔离在独立的子 Agent 中。
CodeAgent 的核心优势在于工具组合的自然性。与传统 JSON 工具调用每次只能执行单一操作不同,CodeAgent 生成的 Python 代码可以在单一步骤中实现:
例如,当 Agent 被要求"查找巴黎的人口并乘以法国的 GDP 人均值"时,CodeAgent 会自主生成如下代码:
population = get_population("Paris")
gdp_per_capita = get_gdp_per_capita("France")
result = population * gdp_per_capita
final_answer(result)整个计算过程在一次模型调用中完成,无需多次往返传递中间结果。
Agent 生成的代码可以导入额外的 Python 模块,但需通过 additional_authorized_imports 参数显式声明。默认情况下,解释器仅允许 math、statistics、datetime 等安全模块。任何工具依赖的第三方库(如 requests、pandas、matplotlib)都必须在此列表中声明,这一机制既保障了安全性,又保持了灵活性。
planning_interval 参数控制 Agent 在执行过程中周期性暂停行动、生成策略规划的频率。当设置为整数 N 时,Agent 会在第 1 步生成初始计划,之后每 N 个行动步骤再生成一次计划更新。
触发条件为:step_number == 1 或 (step_number - 1) % planning_interval == 0。
默认的规划策略采用结构化的"事实调查"(Facts Survey)方法,要求模型在生成计划前先完成三项分析:
这种方法论在 CodeAgent 和 ToolCallingAgent 中均适用,有助于减少多跳问题中的无效探索。
通过 step_callbacks 参数可以拦截规划过程。当回调函数检测到 PlanningStep 类型时,可实现人工审核工作流——在 Agent 继续执行前检查或修改其计划。这为需要人类监督的关键场景提供了干预点。
smolagents 的记忆通过 AgentMemory 对象管理,以 Python 列表形式保存完整的步骤历史。每次模型推理、工具执行或规划事件都会向列表中追加对应的步骤对象,完整的步骤序列在每次模型调用前被序列化为聊天消息,使大语言模型感知到持续的对话上下文。
当前版本(v1.26.0)的记忆仅存在于进程内存中,不具备以下能力:
社区已多次请求持久化功能,但目前仍作为开放特性请求跟踪。
开发者可以直接访问和检查 Agent 的记忆:
result = agent.run("你的任务")
for step in agent.memory.steps:
print(step.step_number, step.tool_calls or step.code_action)AgentMemory 支持 succinct_steps() 方法,可在规划更新时提供精简的历史上下文,避免上下文窗口溢出。此外,记忆结构适合导出到 Langfuse、OpenTelemetry 等可观测性平台进行日志记录和分析。
smolagents 支持文本、视觉、视频和音频输入,通过模态无关(Modality-Agnostic)架构实现。Agent 可以将图像、音频和视频直接纳入代码生成和执行流程,处理多模态数据。
Hugging Face 社区推出了 smolagents-can-see 扩展库,为 Agent 提供视觉理解能力。这使得 Agent 可以处理网页截图、检测 UI 元素,并基于视觉输入生成相应的 Python 操作代码。在 GAIA 基准测试的标注数据集中,也包含了 PDF 和 Excel 文件的手动截图,以辅助基于视觉的推理。
多模态能力主要通过自定义工具实现。例如,可以定义一个图像分析工具,使用 PIL 处理图像并返回描述信息;或定义语音转写工具,将音频文件转换为文本。Agent 在代码中可以调用这些工具,对多模态输入进行分析、转换和综合处理。
smolagents 通过 ManagedAgent 包装器支持多智能体层级架构。任何 Agent 都可以被包装为托管 Agent,并作为工具传递给父级 Agent 使用。被包装的 Agent 必须具备 name 和 description 属性,父级 Agent 根据描述决定何时将任务委托给该子 Agent。
层级委托遵循特定的交互序列:
这种模式实现了专业分工——例如,一个"网页研究"子 Agent 负责搜索和信息收集,一个"数据分析"子 Agent 负责数值计算和图表生成,而管理 Agent 专注于任务编排和结果整合。
在大规模多智能体任务中,可通过 LiteLLMRouterModel 将模型工作负载分布到不同的提供商或实例。例如,管理 Agent 使用高性能模型进行复杂推理,而专业子 Agent 使用成本更低的小模型执行特定任务,从而在性能和成本之间取得平衡。
维度 | CodeAgent | ToolCallingAgent |
|---|---|---|
行动表达方式 | 可执行 Python 代码 | JSON 结构化工具调用 |
单步操作能力 | 多工具组合、循环、条件 | 每次调用单一工具 |
状态管理 | 变量跨步骤持久化 | 无内置变量持久化 |
模型要求 | 需具备代码生成能力 | 需具备函数调用能力 |
基准表现 | 在多工具任务上更优 | 传统范式,兼容性更好 |
CodeAgent 是 smolagents 的默认和旗舰 Agent 类型。当任务涉及多工具组合、数据转换、数值计算或需要保留中间状态时,CodeAgent 通过代码表达可以显著减少步骤数和模型调用次数。研究表明,相比 JSON 工具调用,代码方式可减少约 30% 的步骤,并在 GAIA 等复杂规划基准上取得更好的性能。
ToolCallingAgent 适用于以下情况:
总体而言,除非有特定的兼容性或格式需求,建议优先使用 CodeAgent。
smolagents 的核心特性是让大语言模型生成并执行 Python 代码,这带来了固有的安全风险:
默认的 LocalPythonExecutor 虽然提供了导入白名单、危险模块阻止和操作数量限制等防护,但官方明确声明其不能作为安全边界使用。经过对抗性微调的模型仍可能绕过这些限制,对用户环境造成损害。
对于处理不可信输入的生产系统,建议采取以下措施:
当前版本的可观测性评分相对较低,默认使用 Rich 控制台格式化输出,适合人工阅读但不适合机器解析。生产部署需要额外集成:
/healthz、/readyz)社区已提供与 Phoenix 的集成方案,用于实时追踪复杂的多步执行轨迹和评估。
由于记忆仅存在于进程内存中,Agent 重启后状态完全丢失。对于需要状态恢复或长期运行的任务,需要自行实现外部存储层,或在每次请求时重新初始化 Agent 并从外部数据源加载上下文。
沙箱化执行目前不支持多智能体系统,因为 Agent 之间需要传递可执行代码,而远程沙箱环境难以处理这种交互。架构设计时,应将不可信输入的处理隔离在独立的子 Agent 中,这些子 Agent 不与其他 Agent 共享可执行代码边界。
ThreadPoolExecutor 实现高并发处理,默认并发数为 8agent.monitor.get_total_token_counts() 聚合管理 Agent 和所有子 Agent 的成本