不用框架,纯 Python 手搓 AI Agent 可行吗?

作者:十万个为什么2026.11.04 07:01浏览量:1

简介:本文系统解析“纯 Python 手搓 AI Agent”这一开发方式:不依赖第三方 Agent 框架,直接以 Python 调用大模型 API,自行实现工具调用、循环控制与状态管理。文章阐明其定义、核心组成、运行原理与典型场景,并对比框架方案的差异与选型注意事项,帮助开发者判断何时值得手搓、如何手搓。

一、概念定义:什么是“纯 Python 手搓 AI Agent”

所谓“纯 Python 手搓 AI Agent”,指的是一种不依赖任何专门的 Agent 开发框架,仅使用 Python 语言本身及其标准库,直接调用大模型服务的 API,由开发者自行实现智能体核心逻辑的开发方式。这里的“手搓”并不是指从零实现模型推理或网络通信——这些底层能力依然由大模型服务和通用库提供——而是指编排层与控制层的所有代码,包括提示词组织、工具调用、循环控制、状态管理等,都由开发者亲手编写。

可以从三个视角来理解这个定义:

  • 技术视角:一个 Agent 的本质是“大模型 API + 循环 + 字符串处理”。模型接收上下文并输出决策,代码解析决策、执行工具、把结果拼回上下文,再进入下一轮。整个过程只需要字典、列表、JSON 序列化和 HTTP 请求,这些恰恰是 Python 最擅长的事情。
  • 工程视角:手搓 Agent 意味着把智能体当作一个普通的 Python 函数或服务来写。它有明确的输入输出、可以用常规手段打日志、做单测、做性能分析,而不必穿透框架的多层抽象去猜测“框架到底替我做了什么”。
  • 业务视角:开发者对 Agent 的每一步行为拥有完全控制权,提示词怎么组织、工具给谁开放、什么时候终止循环,都写在看得见的代码里,而不是藏在某个框架的配置项背后。

一个容易产生的误解是“手搓等于重复造轮子”。实际上,被复用的部分(模型推理、HTTP 协议、JSON 解析)是稳定且标准化的,而被框架封装的部分(编排逻辑)恰恰是每个业务各不相同、最需要灵活定制的部分。手搓的做法是:复用标准化的,自己写个性化的。

二、背景与价值:为什么“不用框架”会成为被认真讨论的选择

近年来,大量 Agent 开发框架涌现,它们提供记忆管理、多角色编排、工具注册等开箱即用的能力,显著降低了原型搭建门槛。但随着框架进入真实生产环境,一些共性问题逐渐显现:

  1. 抽象层带来的调试成本。框架为了通用性,往往在“你的业务代码”和“模型 API”之间插入多层封装。一旦行为不符合预期,开发者需要穿透框架源码定位问题,而框架版本迭代快、接口变动频繁,进一步放大了维护成本。
  2. 灵活性枷锁。框架预设的编排范式并不总是匹配业务需求。当需要的只是“一个循环加三个工具”时,引入一整套多智能体编排体系反而是负担。
  3. 依赖与锁定风险。框架的依赖树往往较大,升级可能引入破坏性变更,深度使用后迁移成本高。

行业中也出现了一些值得注意的信号:某头部大模型服务商在官方工程指南中明确建议开发者“从直接调用模型 API 开始”,在此基础上再评估是否引入框架(当然,这与其自身立场有关);另有工程团队公开分享,在生产环境使用某主流框架约 12 个月后选择将其完全移除,并反馈“移除后团队更快乐、更高效”。

这些信号背后的核心判断是:LLM 应用的技术本质并不复杂——把字符串发给模型、接收结构化返回、决定下一步动作——这套“字符串处理 + API 调用 + 循环”的组合,Python 原生能力就能很好完成。当底层能力足够简单时,中间抽象层的价值就需要被重新审视。

三、核心组成:一个最小可用 Agent 的五个模块

不依赖框架,不等于不需要设计。一个结构清晰的手搓 Agent 通常包含以下五个模块:

  1. 模型调用层。封装对大模型服务对话接口的调用:组装消息列表、传入工具定义、解析返回结果。无论是直接使用某家大模型服务的 API,还是通过百度智能云等平台提供的大模型服务接入,这一层本质上就是一次带鉴权的 HTTP 请求加一段 JSON 解析。
  2. 工具注册与执行层。为每个工具定义名称、功能描述和参数结构(通常以 JSON Schema 表达),并维护“工具名 → Python 函数”的映射。执行时做参数校验、调用真实函数、把结果序列化成字符串回填给模型。
  3. 循环控制器。这是 Agent 的心脏:一个循环,每轮把上下文发给模型,若模型给出最终答案则终止,若模型请求调用工具则执行后继续。必须设置终止条件,如最大步数、最大 token 预算或超时时间,防止死循环。
  4. 上下文与状态管理。维护对话历史,处理上下文窗口限制:裁剪早期消息、对长文档做摘要、把中间结果存入外部变量而非全部塞进上下文。
  5. 安全与边界控制。为工具设定最小权限,对高危操作(删除数据、对外发送、资金操作)设置人工确认点,对模型输出做校验,防范提示注入引发的越权行为。

四、工作原理:Agent 循环如何运行

手搓 Agent 的运行逻辑可以概括为“感知—决策—执行—反馈”的循环:

  1. 开发者将任务目标、可用工具的描述一并写入消息列表,发送给模型;
  2. 模型基于当前上下文决策:要么直接给出最终答案,要么输出一个结构化的工具调用请求(指明工具名和参数);
  3. 代码解析该请求,执行对应的 Python 函数,把结果作为一条工具消息追加到上下文;
  4. 回到第 1 步,直到模型给出最终答案或触发终止条件。

下面是一段示意性伪代码(不依赖任何特定框架):

  1. import json
  2. def run_agent(goal: str, tools: dict, max_steps: int = 10):
  3. messages = [{"role": "user", "content": goal}]
  4. for _ in range(max_steps):
  5. # 调用任意大模型服务的对话接口,传入消息与工具定义
  6. msg = call_llm_api(messages, tool_schemas=format_tools(tools))
  7. messages.append(msg)
  8. if not msg.get("tool_calls"):
  9. return msg["content"] # 模型给出最终答案,循环结束
  10. for call in msg["tool_calls"]: # 模型请求调用工具
  11. result = execute_tool(tools, call["name"], call["arguments"])
  12. messages.append({
  13. "role": "tool",
  14. "name": call["name"],
  15. "content": json.dumps(result, ensure_ascii=False),
  16. })
  17. raise TimeoutError("Agent 达到最大步数仍未收敛")

整个核心逻辑不到三十行。需要说明的是,“模型返回结构化工具调用请求”(即通常所说的函数调用能力)是主流大模型服务普遍支持的通用能力,并非某一框架的专属特性——框架在这一层做的事情,主要是把上述循环和映射关系替你写好而已。

五、典型适用场景

手搓方式并非万能,但在以下场景中它往往是更优选择:

  • 工具数量有限、流程清晰的场景:例如一个查询订单、查库存、生成对账单的内部助手,三五个工具加一个循环,手搓代码量极小且完全透明。
  • 需要深度定制的生产系统:提示词策略、上下文裁剪规则、权限边界与业务强耦合时,自己写的代码比修改框架配置更直接。
  • 对可观测性和审计要求高的场景:金融、医疗等合规要求严格的系统中,每一步决策都需可追溯,自研循环配合结构化日志比黑盒框架更可控。
  • 长期维护的核心链路:依赖越少、抽象越薄,系统受上游变更冲击越小。

反之,以下情况引入框架更合理:需要快速验证想法的原型阶段;需要多智能体协作、复杂状态机等复杂编排且团队不愿自行维护这类基础设施;团队希望用统一范式约束多人协作风格。框架的价值在于提供起步速度和协作规范,而非不可替代的技术能力。

六、与相关概念的区别

  • Agent 与工作流:工作流的执行路径由代码预先定义,模型只在固定节点被调用;Agent 的执行路径由模型在循环中自主决策。手搓方式恰好能清晰呈现这一边界——先写工作流,把最不确定的一步交给循环,是常见的渐进式设计。
  • Agent 与函数调用:函数调用是模型输出结构化工具请求的单次能力;把函数调用放入循环、允许模型连续多轮决策,才构成 Agent。
  • Agent 与链式调用:链式调用是固定的多步序列(A→B→C),没有分支与回环;Agent 允许根据中间结果改变执行路径。
  • API、SDK 与框架:API 是服务端暴露的通信契约;SDK 是对 API 的薄封装;框架则在 SDK 之上再叠加编排抽象。手搓 Agent 通常意味着“直接使用 API 或薄 SDK,跳过框架层”。

七、使用注意事项

  1. 上下文与成本管理:循环式 Agent 的 token 消耗随步数增长,需设计历史裁剪与摘要策略,并对每类任务设置预算上限。
  2. 错误处理与重试:工具执行可能失败、接口可能超时,应对工具结果做结构化包装(成功/失败/原因),并把失败信息回传给模型使其自我修正;对网络调用做指数退避重试。
  3. 工具安全:遵循最小权限原则,敏感操作增加人工确认环节,防范提示注入诱导模型调用高危工具。
  4. 可观测性:为每轮循环记录结构化日志(输入、模型输出、工具调用、耗时、token 用量),这是线上排查问题的基础。
  5. 评测与回归:为核心任务建立小规模评测集,每次修改提示词或工具后执行回归验证,避免“改好一处、坏掉三处”。
  6. 循环收敛控制:最大步数、步数告警、异常模式检测(如同一工具被反复调用)都应作为工程默认项。

八、总结

回到最初的问题:不用框架,纯 Python 手搓 AI Agent 真的可行吗?答案不仅是可行,而且在工具数量有限、流程清晰、需要深度定制和强可观测性的场景中,它往往是更优选择。其定义可以浓缩为一句话:以 Python 原生能力直接构造“大模型 API + 工具调用 + 循环控制”的最小智能体系统,用自己写的、看得见的代码替代框架的黑盒抽象。

它的适用边界同样清晰:当任务需要复杂多角色编排、团队需要统一协作范式或追求极致起步速度时,框架仍有其价值。真正的工程判断标准不是“用不用框架”,而是“当前抽象层的复杂度是否与问题复杂度匹配”。理解了 Agent 的本质只是一个循环,开发者就拥有了选择的自由——这正是手搓实践最大的价值。