免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

AI Agent从概念到工程实践:最小可用示例与落地指南

AI Agent从概念到工程实践:最小可用示例与落地指南 你有没有发现最近 AI 圈的讨论重心正在发生变化大家不再只比较“哪个模型更会聊天”而是开始关注“哪个系统能自己把活干了”。从自动写代码、处理表格到读写 API、按流程完成任务一种新的应用形态正在取代过去那种“问一句、答一句”的交互方式你给 AI 一个目标它自己拆解步骤、调用工具、检查结果、调整计划直到最终交付。这个形态就是所谓 AI Agent。本文要讲的核心判断是Agent 并不是某种突然出现的黑科技而是“大模型 工具调用 循环控制 权限边界”的组合体。真正把它从 Demo 变成工程产品的关键不在于模型本身的推理能力有多强而在于你对它的行为控制有多稳。读完这篇文章你会清晰理解 Agent 和普通对话式 AI 的本质区别也会拿到一个最小可运行的 Agent 工程示例并了解生产环境里最容易被忽略的安全、成本、可观测性问题。如果你正准备做 AI 应用开发或者正犹豫要不要在自己的项目里引入 Agent这篇文章更适合从头读完。1. 为什么“自己干活”成了一个分水岭过去我们对 AI 的使用方式本质上还是“增强版搜索引擎”。你在对话框里输入一个问题模型给你一段回答。它写得好不好取决于模型能力和 Prompt 技巧。但如果问题需要查实时数据、调用某个接口、操作某个系统模型就只能说“我目前无法访问外部信息”。这是大模型最明显的能力边界它知道很多知识但它不“做事”。Agent 的改变在于模型不再只生成文本而是生成“行动决策”。它可以在一次任务里做这几件事理解用户目标拆解成若干子任务决定调用哪个工具来获取必要信息观察工具返回的结果判断当前结果是否满足目标如果不满足继续规划下一步如果满足整理结果并回答用户。这个循环看起来不复杂但工程化之后它就是 AI 应用开发领域一次重要的能力迁移。过去一个“智能客服”只能回复话术现在它可以调用订单系统、库存系统、售后表单自己完成一次完整处理流程。过去一个“编程助手”只能生成代码片段现在它可以读取项目结构、运行测试、修复报错。也是因为这个原因“AI 不再听命令了它开始自己干活”这句话准确概括了 AI Agent 的价值。不过我要提醒一句这里说的“自己干活”是在可控范围内的半自主执行不是无人监管的全自动运行。很多项目失败不是模型不够聪明而是没有想清楚边界。1.1 为什么现在才火起来Agent 概念其实很早就有了但过去几年一直不温不火核心原因是模型能力跟不上。第一早期模型在“多步推理”上不稳定。只要任务链路超过两三个环节模型就容易忘记原始目标或者提前输出一个猜测性答案。第二工具调用的可靠性不够。模型经常把参数格式写错无法稳定对接外部 API。第三工程配套不成熟。开发者很难调试一个“回头再调用工具”的对话流程日志、追踪、权限控制都缺标准。现在的变化是主流大模型已经在推理能力、工具调用Function Calling / Tool Calling、多轮上下文管理上做了大量优化加上 LangChain、Semantic Kernel、Spring AI 等框架的出现Agent 开发从“实验室玩法”逐步变成了“工程实践”。AI 工程实践这个词正在从一个概念变成具体岗位和具体项目。1.2 谁最需要关注 Agent并不是所有 AI 应用都适合做成 Agent但下面几类场景适合需要跨系统完成多步操作的任务例如“查一下这个订单的物流状态如果异常就发起人工复核”需要根据中间结果动态调整策略的任务例如“先读取日志再根据错误类型给出修复方案”需要复用多个内部工具或 API 的场景例如“调用知识库、调用代码工具、调用数据分析接口”希望通过自然语言降低操作门槛的系统例如内部运营后台、运维工单系统、数据查询平台。如果你的需求只是“给用户一个能问答的东西”那暂时不需要 Agent普通的 RAG 应用可能更合适。这也是为什么我要把概念和适用场景写清楚避免一上来就过度设计。2. Agent 的核心原理从“回答问题”到“行动闭环”要理解 Agent先看一个经典范式ReActReasoning Acting。大模型不只负责“思考”还负责“行动”。它会在每一步输出中决定是继续调用工具还是直接给出最终答案。系统收到这个决定后执行对应动作再把执行结果回传给模型让模型接着判断。这就是一个“思考-行动-观察”的闭环。2.1 Agent 的四个组成部分可以把一个 Agent 系统拆成四部分组成部分作用常见实现方式模型负责自然语言理解、推理、生成决策云端大模型 API 或本地部署模型规划把目标拆成步骤决定先做什么、后做什么Chain-of-Thought、ReAct、Plan-and-Execute工具Agent 能调用的外部能力搜索、计算器、数据库、API、代码执行器记忆保存历史对话、中间结果、长期偏好上下文窗口、向量数据库、外部存储很多人只盯着“模型”这个部分忽略了另外三个。但实际工程中真正决定体验上限的是工具和记忆。工具决定了 Agent 能做什么。你的模型再聪明如果工具列表只有两三个它也只能在狭小范围内发挥。记忆决定了 Agent 是否能长期执行复杂任务。如果它每做一步就忘记前面的结论最后结果一定不可靠。2.2 Agent 与普通 Prompt 调用的区别表格对比更方便理解维度普通对话式 AIAI Agent交互方式用户提问模型回答用户给目标模型自主规划并执行信息获取依赖模型内部知识可调用外部工具获取实时数据多步处理通常单轮生成多轮循环逐步逼近目标错误处理回答错了就重问可读取错误结果并调整计划控制复杂度低高需要权限、日志、回滚等机制这里有一个常见的理解偏差Agent 不是“多聊几轮天”。即使你在普通对话里让模型“先分析再写代码”那也只是多轮文本生成Agent 的关键区别在于它可以真正执行动作并且把执行结果纳入下一步决策。2.3 通俗理解Agent 更像“新员工”如果把大模型比作一个实习生普通调用方式就是你让实习生“写一份报告”他只能凭记忆写。Agent 的方式则是你给他一个任务他可以自己去查资料、翻系统、问同事做不完回来跟你确认。这个类比能看出很多工程要点你不可能让实习生做任何事任务边界必须清楚你要给他能用的工具不然他只能干等你要审核他的每一步而不是信任一次性的答案你要有止损机制发现不对立刻叫停。Agent 工程化本质上就是设计好这个“实习生”的工作流程、权限和审查机制。3. 动手前需要准备什么在写代码之前先确认环境。下面的方案以“兼容 OpenAI 协议的模型服务”为例既可以连云端模型 API 的兼容接口也可以连本地部署的模型服务。具体使用哪个模型建议以你的项目实际情况为准。3.1 基本运行环境建议准备Python 3.9 及以上版本一个支持工具调用Function Calling / Tool Calling的大模型服务Python 的 openai 库或 equivalent SDK一个可以发起 HTTP 请求的环境建议准备一套虚拟环境避免依赖冲突。安装依赖的命令python -m venv .venv source .venv/bin/activate pip install openai python-dotenv如果你使用本地模型部署可以把模型服务启动在127.0.0.1:8000然后用兼容接口地址即可。这里不限制具体框架核心是让 Agent 能够通过 HTTP 调用模型并且模型能返回工具调用指令。3.2 环境变量准备在项目目录下创建.env文件LLM_BASE_URLhttp://127.0.0.1:8000/v1 LLM_API_KEYnot-needed LLM_MODELyour-model AGENT_MAX_STEPS5如果使用云端服务LLM_API_KEY要填真实密钥并且不要把密钥写进代码仓库。更稳妥的做法是只在本地环境变量中配置并在.gitignore里忽略.env。4. 最小可用 Agent 工程示例下面编写一个最小但完整的 Agent 工程。它的任务是理解用户输入的计算问题调用一个数学计算工具返回最终结果。这个示例不追求功能丰富目的是把“模型决策 - 工具调用 - 结果回传 - 最终答复”这个完整循环跑通。4.1 项目结构agent_demo/ ├── .env ├── mini_agent.py └── test_math_tool.py先来看mini_agent.py的完整代码。# 文件路径agent_demo/mini_agent.py import json import os import re from openai import OpenAI client OpenAI( base_urlos.getenv(LLM_BASE_URL, http://127.0.0.1:8000/v1), api_keyos.getenv(LLM_API_KEY, not-needed), ) MODEL_NAME os.getenv(LLM_MODEL, your-model) # ---------- 一个简单安全的计算器工具 ---------- TOKEN_RE re.compile(r\d(?:\.\d)?|[*/()]|-) class Parser: 只支持四则运算和括号的极简解析器避免使用 eval。 def __init__(self, text: str): self.tokens TOKEN_RE.findall(text) if .join(self.tokens) ! text.replace( , ): raise ValueError(invalid expression) self.pos 0 def peek(self): return self.tokens[self.pos] if self.pos len(self.tokens) else None def consume(self): token self.tokens[self.pos] self.pos 1 return token def parse(self): value self.expr() if self.pos ! len(self.tokens): raise ValueError(unexpected token) return value def expr(self): value self.term() while self.peek() in (, -): op self.consume() right self.term() value value right if op else value - right return value def term(self): value self.factor() while self.peek() in (*, /): op self.consume() right self.factor() if op *: value * right else: if right 0: raise ValueError(division by zero) value / right return value def factor(self): if self.peek() -: self.consume() return -self.factor() if self.peek() (: self.consume() value self.expr() if self.peek() ! ): raise ValueError(missing right parenthesis) self.consume() return value token self.consume() if not re.fullmatch(r\d(\.\d)?, token): raise ValueError(invalid number) return float(token) def call_math(expr: str) - str: 计算四则运算表达式。 try: return str(Parser(expr).parse()) except Exception as exc: return fmath error: {exc} TOOLS { call_math: call_math, } def get_tools_schema(): return [ { type: function, function: { name: call_math, description: 计算四则运算表达式例如 (123)*4, parameters: { type: object, properties: { expr: { type: string, description: 要计算的数学表达式, } }, required: [expr], }, }, } ] def run_agent(user_query: str) - str: messages [ { role: system, content: 你是任务执行助手。需要计算时请调用 call_math 工具计算完成后用中文总结结果。, }, {role: user, content: user_query}, ] max_steps int(os.getenv(AGENT_MAX_STEPS, 5)) for step in range(max_steps): print(f[agent] step {step 1}: 请求模型决策) response client.chat.completions.create( modelMODEL_NAME, messagesmessages, toolsget_tools_schema(), tool_choiceauto, temperature0.2, ) msg response.choices[0].message if not msg.tool_calls: print([agent] 模型没有调用工具直接返回结果) return msg.content or [空回复] messages.append({ role: assistant, content: msg.content or , tool_calls: [ { id: tc.id, type: function, function: { name: tc.function.name, arguments: tc.function.arguments, }, } for tc in msg.tool_calls ], }) for tc in msg.tool_calls: print(f[agent] 调用工具 {tc.function.name}({tc.function.arguments})) try: args json.loads(tc.function.arguments) if tc.function.name not in TOOLS: result funknown tool: {tc.function.name} else: result TOOLS[tc.function.name](**args) except Exception as exc: result ftool execution error: {exc} messages.append({ role: tool, tool_call_id: tc.id, content: json.dumps({result: result}, ensure_asciiFalse), }) return 达到最大步数已停止执行。 if __name__ __main__: query os.getenv(AGENT_QUERY, 请计算 (123)*4 的结果) print(run_agent(query))这段代码包含一个完整的 Agent 循环把系统提示和用户问题放入 messages请求模型决策如果模型返回tool_calls说明它要使用工具执行工具把工具结果追加到消息列表再次请求模型让模型基于工具结果继续回答如果模型不再调用工具就返回最终结果。真正容易踩坑的地方是消息格式。工具调用结果必须和tool_call_id对应否则模型无法理解这个结果属于哪一次调用。很多 Agent 项目运行失败问题不在工具本身而在消息拼装不规范。4.2 为什么工具要独立成函数把工具实现和 Agent 主循环分开是工程上的基本要求。每个工具是一个纯函数输入参数、输出结果便于单测、便于替换、便于审计。如果工具逻辑直接散落在主循环里后续想加权限控制、参数校验、日志审计会非常痛苦。这里额外说明计算器工具没有使用eval而是用了一个简单的递归下降解析器。这样做是为了避免任意代码执行。虽然eval在示例代码里写起来很快但生产环境直接对模型的输入结果执行eval是安全风险。Agent 工具设计的第一原则就是永远不要轻信模型生成的参数。4.3 配置文件示例如果你希望把 Agent 的核心参数独立管理可以增加一个config.yaml# 文件路径agent_demo/config.yaml agent: model: your-model base_url: http://127.0.0.1:8000/v1 temperature: 0.2 max_steps: 5 query: 请计算 (123)*4 的结果 tools: call_math: enabled: true timeout_seconds: 5 security: enable_audit_log: true allowed_tools: - call_math配置管理的核心不是写出来而是让配置可变更、可测试。比如你可以把允许使用的工具列表放到配置里后续上线新工具时不用改主循环只需要在配置中增加一个条目。4.4 测试示例为工具补充单元测试是保证 Agent 可靠性的第一步。# 文件路径agent_demo/test_math_tool.py from mini_agent import call_math def test_call_math_priority(): assert call_math((123)*4) 60.0 def test_call_math_division_by_zero(): assert error in call_math(1/0) def test_call_math_invalid_expression(): assert error in call_math(2 abc)运行测试pytest test_math_tool.py -v工具测试通过不等于 Agent 全流程通过。后面还需要做端到端的验证。5. 运行与结果验证代码写完后按下面的顺序运行。5.1 启动模型服务如果你使用本地模型部署先确保兼容 OpenAI 接口的服务已经启动。可以用以下命令做一个冒烟测试curl http://127.0.0.1:8000/v1/models如果返回模型列表说明服务已经就绪。如果接口地址不同请修改.env里的LLM_BASE_URL。5.2 运行 Agentset -a source .env set a python mini_agent.py正常情况下控制台会输出类似下面的日志[agent] step 1: 请求模型决策 [agent] 调用工具 call_math({expr: (123)*4}) [agent] 模型没有调用工具直接返回结果 (123)*4 的结果是 60.0这里要说明不同模型的具体输出文本会有差异但日志中的流程应当一致。你可以看到“模型决定调用工具”这个关键行为。如果模型没有返回tool_calls说明模型不支持工具调用或者你的接口配置不对。5.3 如何判断是否成功成功的标准不是“模型输出了一个答案”而是以下条件同时满足Agent 在第一步或前几步就发起了工具调用工具执行结果被正确回传给模型模型在拿到结果后给出了最终总结工具结果和最终答案一致。如果最终答案和工具结果不一致要检查是不是模型在总结时编造了内容。这种情况在弱模型上并不少见因此不要盲目信任最终回复关键是保留工具调用日志。6. 常见问题与排查方法下表整理了 Agent 开发中最常见的五类问题。如果你遇到运行失败先按表格顺序排查。问题现象可能原因排查方式解决方案模型从不返回 tool_calls模型或接口不支持工具调用查看模型文档用接口测试工具参数换支持工具调用的模型或改用文本 ReAct 协议模型返回 tool_calls 但参数解析失败参数 JSON 前后有多余内容打印原始 tool_calls 内容使用正则提取 JSON 片段或调整系统提示词工具结果没有被模型正确理解tool_call_id 不匹配检查 messages 追加顺序严格按照 SDK 要求的消息格式回传Agent 陷入重复调用工具的死循环任务目标不明确或缺少终止条件观察每一步日志确认工具结果是否被用于决策设置 max_steps增加“判断完成”的说明工具执行了危险操作参数校验不严审查工具代码和安全配置使用白名单参数禁止任意代码/命令执行6.1 排查的基本原则遇到 Agent 问题不要只看最终报错要抓住“决策日志”。模型这一轮为什么决定调用这个工具工具传入了什么参数工具返回了什么模型是怎么解释这个结果的如果每一步都有日志很多问题都能快速定位。这也是为什么 Agent 项目一开始就要设计日志规范不要等出问题再补。7. Agent 工程落地最佳实践下面这些经验来自很多 Agent 工程项目的共性教训。如果你的项目已经跑通 Demo一定要认真看这一部分。7.1 先控制任务边界再谈自主性不是所有任务都适合让 Agent 自主执行。一个重要原则是高后果、难回滚的任务必须保留人工审批节点。比如“读取日志并生成分析报告”可以全自动“删除生产环境数据库记录”就不应该让 Agent 自动做。即便你的模型很聪明也不能代替权限控制。一个可行的做法是给 Agent 工具分级只读工具可自动执行受限写工具自动执行但记录日志高风险工具需要人工确认。工具分级可以在工具注册表里实现也可以通过配置平台控制。重点是让“危险操作”始终在人的监督下。7.2 工具设计要遵循最小权限Agent 的工具调用越少越安全。每增加一个工具就增加一个风险面。设计工具时可以参考以下几点工具参数使用强类型结构不要接受自由文本然后拼接成命令禁止把模型输出直接拼接到 shell、SQL、文件路径中文件访问、数据库访问、网络请求都需要单独授权工具执行必须记录输入、输出、耗时、调用方信息工具最好在沙箱环境中运行例如容器、独立进程、受限用户。记住模型只是决策者执行者仍然是你的工具。安全边界必须在工具层封死不能靠模型自律。7.3 引入可观测性和评估体系Agent 是多步决策系统调试成本比普通接口高得多。如果没有可观测性一个任务失败后你很难知道是哪一步出了问题。建议从第一天就做三件事第一全链路日志。每个步骤都记录“模型请求、模型回复、工具调用、工具结果、耗时”。第二任务级追踪。使用 request_id 贯穿整个 Agent 循环方便把一次任务的所有步骤串起来。第三评估集。准备一组“标准问题 预期工具调用顺序 预期最终结果”的测试用例每次改版后跑一遍。AI 应用开发最怕“感觉变好了但不知道哪里变好”评估集是解决这个问题的唯一方式。7.4 成本控制与上下文管理Agent 的每一轮模型调用都要消耗 Token而且多轮循环的成本会快速累积。最常见的成本失控场景是 Agent 陷入反复调用工具的死循环。控制成本的手段包括设置 max_steps强制终止限制上下文长度历史消息做摘要压缩用更快、更便宜的模型处理简单步骤对工具结果做缓存避免重复调用设置单任务成本阈值超过后自动报警。上下文管理是另一个容易被忽视的问题。如果 Agent 每一轮都把全部历史消息发给模型很快会超过上下文窗口。更合适的做法是只保留必要的中间结果把长文档内容放到外部存储或向量库中。7.5 从单工具开始逐步增加复杂度我的建议是不要一开始就搭一个多 Agent、复杂规划框架。先把“一个模型 一个工具 一个循环”跑稳再逐步增加工具数量和任务复杂度。这个思路和写代码是一样的。最小闭环能跑通说明基础架构没问题。后面再怎么扩展都不会因为底层不可靠而反复返工。很多人被复杂框架吸引结果第一周都在处理依赖和概念问题反而学不到 Agent 的核心机制。8. 总结与下一步路径这篇文章想讲清楚的核心点有三个第一Agent 的本质是“模型决策 工具执行 结果回传 循环控制”不是简单的多轮对话。第二开发 Agent 最小闭环并不复杂难点在于工程化管控安全、可观测、评估、成本、上下文管理。第三AI Agent 真正适合的场景是需要跨系统执行任务的地方不是所有 AI 应用都需要 Agent 化。如果你刚接触这个方向下一步可以这样做先跑通本文的最小 Agent 工程示例替换成你自己的模型服务然后增加一个你工作中真正会用到的工具。比如查数据库、读接口、发通知。再然后给 Agent 增加日志和审计把每一步决策记录下来。最后准备一组标准测试用例把 Agent 当成一个正式工程来迭代。AI 应用开发正在从“生成内容”走向“完成任务”这个方向还会继续演进。但万变不离其宗模型负责聪明工程负责可靠。谁能把这两件事结合好谁就能做出真正“自己干活”的 AI 系统。
返回列表