AI Agent 生产级开发指南:从最小工具调用循环到可治理的智能系统

过去一年,“Agent” 从一个营销热词变成了真实的生产组件。但一个残酷的现实是:大部分团队的 Agent 项目止步于 demo——能演示、不能上线,能回答、不能干活。根本原因在于很多人把 Agent 理解成了"会聊天的机器人",把开发重心放在把 Prompt 写得更花哨上。而专业开发的核心恰恰相反:把不确定性关进工程框架——状态可追踪、工具可管控、失败可恢复、成本可约束。

一、Agent 的核心架构:四层模型

一个可落地的 Agent 通常包含四个层次。规划层负责把用户目标拆解成子任务、决定下一步动作;记忆层由短期对话上下文和长期向量检索两部分组成;工具层提供函数调用、API、数据库访问和代码执行沙箱;执行循环则是那个把一切串起来的引擎——LLM 决策、调用工具、回填观察、继续推理,直到产出最终答案。

无论你选 LangChain/LangGraph、AutoGen、CrewAI 还是 OpenAI Assistants API,底层本质上都是 ReAct 循环的变体。ReAct 的意思是 Reasoning + Acting:模型交替输出"思考"和"行动",借助工具获取外部信息,再根据结果继续推理。理解了这个循环,再看任何框架都会觉得通透——框架只是把这个循环工程化的壳。

二、从零实现一个最小可运行的工具调用 Agent

与其纠结框架,不如先手写一个最小循环。下面用 OpenAI SDK 实现一个带计算器和天气查询两个工具的 Agent:

import json, os, re
from openai import OpenAI

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

TOOLS = [
    {"type": "function", "function": {
            "name": "calculator",
                    "description": "计算数学表达式,例如 (12+8)*3",
                            "parameters": {"type": "object",
                                                   "properties": {"expression": {"type": "string"}},
                                                                          "required": ["expression"]}}},
                                                                              {"type": "function", "function": {
                                                                                      "name": "get_weather",
                                                                                              "description": "查询指定城市天气",
                                                                                                      "parameters": {"type": "object",
                                                                                                                             "properties": {"city": {"type": "string"}},
                                                                                                                                                    "required": ["city"]}}}
                                                                                                                                                    ]
def run_agent(user_input: str, max_steps: int = 5):
    messages = [{"role": "system",
                     "content": "你是严谨助手。需要计算或天气时调用工具,不要编造。"},
                                     {"role": "user", "content": user_input}]
                                         for _ in range(max_steps):
                                                 resp = client.chat.completions.create(
                                                             model="gpt-4o-mini", messages=messages,
                                                                         tools=TOOLS, tool_choice="auto", temperature=0.2)
                                                                                 msg = resp.choices[0].message
                                                                                         messages.append(msg)
                                                                                                 if not msg.tool_calls:
                                                                                                             return msg.content
                                                                                                                     for call in msg.tool_calls:
                                                                                                                                 fn, args = call.function.name, json.loads(call.function.arguments)
                                                                                                                                             result = TOOL_MAP[fn](**args)
                                                                                                                                                         messages.append({"role": "tool",
                                                                                                                                                                                      "tool_call_id": call.id, "content": result})
                                                                                                                                                                                          return "达到最大步数,任务未完成"
                                                                                                                                                                                          ```
这段代码虽然只有几十行,却包含了 Agent 的全部骨架:工具 Schema 声明、模型决策、工具执行、结果回填、循环终止。注意两个细节:`tool_choice="auto"` 让模型自己判断何时调用工具;`max_steps` 硬性限制循环轮数,这是防止 Agent 陷入死循环的第一道保险。

## 三、工具层:Agent 的"手"要管得住

工具是 Agent 能力的边界,也是风险敞口。生产环境的工具治理有四个铁律。

第一,**参数必须校验**。禁止直接执行 Shell、SQL 或文件删除;数学计算不要用 eval,改用 AST 解析白名单运算符。下面的安全计算器用 `ast` 模块把表达式解析成语法树,只允许加、减、乘、除、幂等有限运算,从机制上杜绝了任意代码执行:

```python
import ast, operator
OPS = {ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul,
       ast.Div: operator.truediv, ast.Pow: operator.pow, ast.USub: operator.neg}
def safe_calc(expr: str):
    def _eval(node):
            if isinstance(node, ast.Expression): return _eval(node.body)
                    if isinstance(node, ast.Constant): return node.value
                            if isinstance(node, ast.BinOp):
                                        return OPS[type(node.op)](_eval(node.left), _eval(node.right))
                                                raise ValueError("不支持的表达式")
                                                    return str(_eval(ast.parse(expr, mode="eval")))
                                                    ```
第二,**最小权限**。工具描述要写清楚用途和边界,模型才不会误调用;涉及转账、删除等高危操作必须设置人工确认门禁。第三,**异常转观察**。工具执行失败不要中断 Agent 循环,把错误信息作为 tool 消息回传给模型,让它决定重试还是向用户说明。第四,**全量审计**。每次工具调用的入参、出参、耗时都要落日志,这是排查"模型为什么做出这个决定"的唯一线索。

## 四、记忆层:短期与长期的分工

没有记忆的 Agent 是健忘的。短期记忆就是当前会话的上下文窗口,需要控制长度——滑动窗口只保留最近 N 轮,或者对早期对话做摘要压缩。长期记忆通过向量数据库实现:用户的偏好、历史行为、领域知识库都可以向量化存储,跨会话检索复用。

这里有一个工程细节:**上下文不是越多越好**。长上下文中模型的有效注意力会稀疏化,越靠后的指令越容易被前面堆积的内容稀释。所以长期记忆检索回来的内容,同样要经过重排序和压缩,只把最相关的部分注入提示词。

## 五、Agent 的评估:别只看"像不像人"

Agent 系统的评估比传统软件难得多,因为它的输出是概率性的。评估体系至少要覆盖五个维度:任务完成率——给定测试集,Agent 有多少任务真正达成了目标;工具调用准确率——该调工具的时候调没调、参数对不对;幻觉率——答案中虚构事实的比例;逻辑连贯性——多步推理是否前后一致;成本指标——平均每任务消耗多少 Token、多少步数。

建议用固定测试集配合 LLM-as-a-Judge 自动打分:先定义好评分维度(准确性、引用质量、结构完整性),再让一个较强的模型按维度打分。早期用二十个左右有代表性的 case 就能暴露大部分问题,再逐步扩展到几百个。不要只看最终答案对不对,要逐节点看每个环节的准确率——多 Agent 系统里,一个 90% 准确率的子 Agent,其错误结论被下游当成事实引用后,系统的有效准确率可能远低于 90%。

## 六、成本控制:预算是一等公民

Agent 是 Token 消耗大户,尤其是多 Agent 系统,用量轻松达到单 Agent 的十几倍。成本治理要前置:给单次任务设置最大步数和最大 Token 上限;用预算器给每个子任务分配额度,超限就强制收敛;用路由策略让简单问题走小模型、复杂推理才上大模型。实测中,简单分类、抽取类任务用小模型,推理、规划类任务用大模型,Token 成本可以降低四成到六成。

## 七、合规红线与安全护栏

最后必须提安全。输入侧要防提示词注入:用户文本可能试图覆盖系统指令,需要做指令边界隔离和注入检测。输出侧要接内容审核,阻断有害内容。执行侧要权限管控:写代码的 Agent 不需要发邮件的权限,读数据的 Agent 不需要删数据的权限。还有合规底线——遵守平台条款、隐私法规和开源许可证,不开发用于欺诈、攻击、骚扰的应用。

## 八、总结

专业 Agent 开发的真谛,是把 LLM 的不确定性封装进可观测、可控制、可恢复的工程系统。先跑通一个最小工具调用循环,再逐步加入记忆、规划、多 Agent 协作和生产级治理。代码本身不复杂,难的是对边界、成本和安全的持续把控。从今天起,动手写你的第一个 Agent 循环,比看十篇概念文章更有价值。


Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐