
很多第一次接触 Agent 开发的读者都会有这样一个感觉看概念文章和分享视频的时候觉得不过如此无非是“大模型 工具调用 循环判断”。可真轮到自己动手从需求拆解、模型调用、工具设计、上下文管理再到结果验证和稳定性处理每一步都可能卡住。市面上讲 Agent 概念的材料很多但能带着你从零把一套可运行的智能体工具链搭起来的内容却不多。这篇文章想做一个偏硬核的尝试不依赖某个重量级 Agent 框架而是从最底层开始亲手设计并实现一个轻量级智能体工具链。我们会一起拆解 Agent 的核心运行循环实现工具注册与调用、记忆管理、结果验证并讨论工程化落地时真正值得关注的坑。读完这篇文章你应该能回答这几个问题Agent 开发的门槛到底在哪里一个可运行的 Agent 工具链最少包含哪几个模块以及你自己动手时应该从哪里开始、如何设计、如何排错。1. 这篇文章真正要解决的问题很多人学 Agent 的时候会陷入两种极端一种是一直在学概念看了大量“什么是 Agent 智能体”“什么是框架与编排”的科普文章却从来没有跑通过自己的代码另一种是直接套用某个 Agent 框架把配置填好、跑一个 demo然后就结束了。等换一个业务场景因为不懂内部机制稍微出点问题就不知道怎么排查。这篇文章走的是第三条路不依赖重型框架从零搭建一套最小可用的智能体工具链。这套工具链会包含以下核心能力接收用户任务并转化为系统提示和初始消息。调用大模型进行规划和决策。根据模型输出解析出工具调用请求。执行工具函数把结果返回给模型。维护短期记忆和上下文长度控制。设定最大轮次防止无限循环。记录完整的执行轨迹方便排查问题。这个过程中你会真实理解 Agent 框架底层做的事情而不是停留在“Agent 就是大模型加工具”的粗浅认知上。以后再去看 LangChain、Microsoft Agent Framework、Codex Agent 这类产品或者阅读 Agent 框架源码理解成本会低很多。什么样的人最适合读这篇文章如果已经有 Python 基础写过简单的 API 调用但还没有完整实现过一个 Agent 项目那么这篇文章就是为你准备的。如果你已经在用某个 Agent 框架但总觉得是“黑盒”希望搞清楚推理循环、工具调用和上下文管理内部发生了什么这篇文章也能提供不少有价值的信息。2. Agent 与工具链的基础概念2.1 什么是 AgentAgent 智能体广义上是指能够感知环境、做出决策并采取行动的自主系统。在 LLM 语境里Agent 通常指以大型语言模型为“大脑”通过规划、工具调用和记忆机制完成复杂任务的程序系统。有一个容易被忽略的点Agent 不是让你训练一个模型也不是简单封装一个 Chat API。Agent 的核心价值在于“行动能力”。模型本身只能生成文字它不能查天气、不能操作数据库、不能调用电商订单接口。Agent 通过工具调用让模型能够对外部世界产生影响并在工具返回结果后继续推理直到任务完成。传统问答系统的工作方式是“用户问一句模型答一句”。Agent 的工作方式是“模型根据目标生成动作执行动作观察结果再决定下一步动作”这个过程反复循环直到达成目标或达到终止条件。这正是 Agent 和普通 Chatbot 的本质区别。2.2 为什么叫“工具链”“工具链”这个词从编译器领域借过来。写 C/C 时编译器只是其中最核心的一环真正要把一份源码变成可运行的程序还需要链接器、汇编器、标准库、构建系统和调试工具这些组合在一起才叫编译工具链。比如给 Keil 这样的 IDE 配置外部的 GCC 工具链实际上就是在更换整个编译链路中负责代码生成的那个核心组件。Agent 领域很像。大模型是“编译器内核”但要让 Agent 在真实业务里跑起来还需要周围一整套配套组件模型接入层负责屏蔽不同模型的 API 差异工具层负责把业务能力封装成模型可调用的函数记忆层负责管理上下文和长期知识执行循环负责把“模型决策”变成“真实动作”可观测性负责记录每次决策和工具调用出了问题能回放。这一整套东西就是 Agent 的工具链。理解了这一点就会明白为什么只调一个 Chat API 不能叫 Agent 开发也明白为什么社区里讨论“Agent 开发学习路线”时总有经验丰富的前辈强调要重视工具链建设而不只是模型选择。2.3 Harness、Skill 与 Agent 的关系搜索热词里经常出现几个相近概念这里一次说清楚。Harness 可以理解为“运行 Agent 的外壳或者执行环境”。它负责管理 Agent 的执行循环、消息流转、工具调用生命周期、错误处理和终止条件。可以把它类比为 Web 应用里的 Spring MVC 框架——它不关心你的业务细节但决定了请求怎么进来、路由怎么走、异常怎么处理。Skill 则代表“Agent 可以调用的某项能力封装”本质上是一组工具函数和对应调用说明的集合。一个“获取天气”的 Skill 可能包括天气 API 的调用代码、参数模型、返回结果解析逻辑以及“什么时候该用这个工具”的描述。Agent 是宏观智能体Harness 是 Agent 的执行载体Skill 是 Agent 的技能组件。搭建工具链时第一步要搭的是 Harness也就是执行循环本身第二步才是按业务能力封装 Skill。很多初学者一上来就想实现特别复杂的技能结果核心循环跑不通这是本末倒置。2.4 Agent 记忆的分类记忆也是 Agent 开发的热门话题搜索热词里“agent记忆”出现频率很高。工程上建议至少区分两层记忆。工作记忆指当前任务进行中需要保留的对话上下文和中间结果通常放在消息列表里由 Agent 执行循环管理。由于大模型上下文窗口有限工作记忆需要做裁剪、摘要或丢弃。长期记忆指跨会话的业务知识、用户偏好、历史结论一般存放于向量数据库、KV 存储或普通数据库中在合适的时机通过检索注入到上下文中。自己搭工具链时优先把工作记忆做好长期记忆先按需求做最小实现不必过度设计。3. 环境准备与前置条件开始写代码之前先把环境准备好。以下为本项目的运行环境建议具体版本请以实际项目为准本文重点演示通用思路。操作系统Windows / macOS / Linux 均可。Python 3.9 及以上版本。pip 包管理工具。网络环境可访问大模型 API 服务。一个可用的模型 API Key使用 OpenAI 兼容接口格式。建议准备一个虚拟环境避免依赖冲突。创建并激活虚拟环境python -m venv agent_env source agent_env/bin/activateWindows 环境激活命令为agent_env\Scripts\activate安装依赖pip install requests python-dotenv这里没有采用重量级框架只使用 requests 发送模型请求python-dotenv 用于读取本地环境变量。选择最小依赖的原因是为了让你看清 Agent 工具链的底层逻辑而不是被框架封装掩盖。后续如果有需要可以再把代码迁移到任何主流框架上。项目目录结构规划如下agent-toolchain/ ├── .env # 环境变量文件API Key ├── config.py # 读取配置 ├── tools.py # 工具定义与注册 ├── memory.py # 记忆管理 ├── agent.py # 核心执行循环 ├── main.py # 入口脚本与演示 └── requirements.txt # 依赖清单4. 工具链架构设计与核心流程拆解4.1 整体架构一套轻量级 Agent 工具链我按职责拆成四个模块每个模块只做一件事模块职责对应文件配置层管理 API Key、模型名、系统提示等config.py工具层定义工具函数生成工具说明执行调用tools.py记忆层维护消息列表控制上下文长度memory.py执行层调度模型、解析工具调用、驱动循环agent.py这种分层设计的好处是隔离变化。某个模块需要调整时不会牵连其他模块。例如以后想把模型从 A 厂商切换到 B 厂商只需要在配置层和模型请求函数里做少量修改工具层和记忆层基本不用动。4.2 核心执行循环这是整个 Agent 工具链的心脏。执行循环的基本逻辑是这样的拼接系统提示、记忆消息、用户新请求形成完整的消息列表。把消息列表发送给大模型。模型可能返回两种结果直接给出最终答案或者输出一个工具调用指令。如果是工具调用指令则解析出工具名和参数调用对应工具函数把结果作为一条新消息加入列表。再次调用模型让它基于工具结果继续推理。反复执行步骤 3 到 5直到模型不再调用工具或达到最大迭代轮次。这个循环把一个“复杂的多步任务”拆成了“模型决策 工具执行 结果反馈”的简单迭代。重点是让每次循环中模型都能看到新的信息从而做出下一次更准确的决策。4.3 工具注册与调用为了让模型能够调用工具工具层必须做两件事一是提供工具的描述信息比如工具名称、功能说明、参数类型和是否必填二是提供真实的执行函数。工具的说明要写得足够清楚因为模型是“读”着这些描述决定什么时候调用、传什么参数的。描述越模糊模型乱调用的概率越高。一个常见的错误是工具描述里不写适用条件导致模型在根本不该用工具的场景调用了工具。工具函数本身要尽量做成无状态、纯函数式。同样的参数传入返回结果应该确定且可预测。这样不仅方便测试也让整个 Agent 的行为更容易维护。4.4 记忆管理自己搭工具链时上下文管理是一个容易忽略但很致命的点。多轮工具调用后消息列表会快速增长很快接近模型的上下文窗口上限。Memory 模块需要提供两个基本能力追加消息在消息过多时做裁剪。最简单但实用的裁剪策略是保留系统提示、保留最近 N 轮对话消息、把中间过长的历史消息替换成一段摘要。这样牺牲了一部分长程信息但保证了 Agent 不会因超长报错。等需要更强记忆时再引入向量检索和摘要记忆设计思想是一样的。5. 完整示例代码实现下面我会逐个文件搭建这套工具链。示例代码使用 OpenAI 兼容接口格式模型请求会发送到/v1/chat/completions你可以根据自己的 API 服务商调整OPENAI_BASE_URL。所有代码均为最小演示实现核心目的是展示 Agent 工具链的工作机制。5.1 配置文件# config.py import os from dotenv import load_dotenv load_dotenv() OPENAI_API_KEY os.getenv(OPENAI_API_KEY, ) OPENAI_BASE_URL os.getenv(OPENAI_BASE_URL, https://api.openai.com/v1) MODEL_NAME os.getenv(MODEL_NAME, gpt-4o-mini) SYSTEM_PROMPT 你是一个能够调用工具完成任务的中文智能体。 当你需要获取额外信息时请根据工具说明调用工具。 每次只能输出一个工具调用格式如下 tool_call{name: 工具名, arguments: {参数名: 参数值}}/tool_call 基于工具结果继续推理。如果任务已经完成直接输出最终答案不要再调用工具。 MAX_ITERATIONS 5.env文件示例OPENAI_API_KEYsk-your-api-key OPENAI_BASE_URLhttps://api.openai.com/v1 MODEL_NAMEgpt-4o-mini这里要特别提醒千万不要把包含真实 Key 的.env文件提交到 Git 仓库。建议把.env写入.gitignore项目中只保留.env.example作为模板。5.2 工具层实现# tools.py import json # 工具注册表 TOOL_REGISTRY {} def register_tool(name, description, parameters): 注册工具的装饰器工厂 def decorator(func): TOOL_REGISTRY[name] { name: name, description: description, parameters: parameters, func: func, } return func return decorator register_tool( nameget_weather, description获取指定城市的当前天气信息当用户询问天气时使用, parameters{ type: object, properties: { city: {type: string, description: 城市名称例如 北京} }, required: [city], }, ) def get_weather(city: str): # 演示用真实项目中可以替换为天气 API 调用 weather_data { 北京: 晴25 度, 上海: 小雨22 度, 广州: 多云28 度, } data weather_data.get(city, f暂无 {city} 的天气数据) return json.dumps({city: city, weather: data}, ensure_asciiFalse) register_tool( namecalculator, description执行简单的四则运算表达式当用户需要数学计算时使用, parameters{ type: object, properties: { expression: {type: string, description: 数学表达式例如 1 2 * 3} }, required: [expression], }, ) def calculator(expression: str): # 演示用仅支持安全的数学表达式 # 实际项目请使用更严谨的表达式解析库不要直接用 eval try: safe_expression expression.replace(^, **) result eval(safe_expression, {__builtins__: {}}, {}) return json.dumps({expression: expression, result: result}, ensure_asciiFalse) except Exception as e: return json.dumps({error: f计算失败: {str(e)}}, ensure_asciiFalse) def get_tool_schemas(): 生成用于模型提示的工具描述列表 schemas [] for tool in TOOL_REGISTRY.values(): schemas.append({ name: tool[name], description: tool[description], parameters: tool[parameters], }) return schemas def execute_tool(name: str, arguments: dict): 根据工具名执行工具 if name not in TOOL_REGISTRY: return json.dumps({error: f未找到工具: {name}}, ensure_asciiFalse) func TOOL_REGISTRY[name][func] try: return func(**arguments) except TypeError as e: return json.dumps({error: f工具参数错误: {str(e)}}, ensure_asciiFalse) except Exception as e: return json.dumps({error: f工具执行异常: {str(e)}}, ensure_asciiFalse)代码里有两点值得注意第一工具描述和参数结构是给模型读的写得越明确模型调用就越准确第二示例中的calculator使用了eval但这只是演示。实际项目中不要直接对模型生成的表达式执行eval这是严重的安全隐患。更好的做法是用aSTE库或者其他安全的表达式解析方案并且一定要在沙箱或受控环境中运行外部输入。5.3 记忆层实现# memory.py class Memory: 简单的消息记忆管理器 def __init__(self, max_messages: int 20): self.messages [] self.max_messages max_messages def add(self, role: str, content: str): self.messages.append({role: role, content: content}) self._trim_if_needed() def get_messages(self): return self.messages def _trim_if_needed(self): # 超过阈值时丢弃最旧的中间消息保留系统提示和最近消息 if len(self.messages) self.max_messages: return keep_count self.max_messages - 2 self.messages [self.messages[0]] self.messages[-keep_count:] def clear(self): self.messages []这个 Memory 类非常朴素但它抓住了记忆管理的核心防止上下文无限增长。它的裁剪策略是“丢最旧的中间消息”在演示场景已经够用。真实项目中可以把“被丢弃的历史”替换成摘要消息这是下一步的优化方向。5.4 Agent 核心执行循环# agent.py import json import re import requests from config import OPENAI_API_KEY, OPENAI_BASE_URL, MODEL_NAME, SYSTEM_PROMPT, MAX_ITERATIONS from memory import Memory from tools import get_tool_schemas, execute_tool TOOL_CALL_PATTERN re.compile(rtool_call(.*?)/tool_call, re.S) class Agent: def __init__(self): self.memory Memory() self.memory.add(system, SYSTEM_PROMPT) def _call_model(self, messages): 调用 OpenAI 兼容接口 headers { Authorization: fBearer {OPENAI_API_KEY}, Content-Type: application/json, } payload { model: MODEL_NAME, messages: messages, } # 工具描述直接拼进系统提示里让模型知道有哪些工具 tool_schemas get_tool_schemas() payload[messages][0][content] \n\n可用工具:\n json.dumps(tool_schemas, ensure_asciiFalse) response requests.post( f{OPENAI_BASE_URL}/chat/completions, headersheaders, jsonpayload, timeout60, ) response.raise_for_status() data response.json() return data[choices][0][message][content] def run(self, user_input: str): 执行 Agent 主循环 self.memory.add(user, user_input) current_messages self.memory.get_messages() for step in range(1, MAX_ITERATIONS 1): print(f[Step {step}] 调用模型进行推理...) response_text self._call_model(current_messages) print(f[Step {step}] 模型输出: {response_text}) tool_match TOOL_CALL_PATTERN.search(response_text) # 没有工具调用认为任务完成 if not tool_match: self.memory.add(assistant, response_text) return response_text # 解析工具调用 try: tool_call json.loads(tool_match.group(1)) tool_name tool_call[name] tool_args tool_call.get(arguments, {}) except Exception as e: error_msg f工具调用解析失败: {str(e)} print(f[Step {step}] {error_msg}) self.memory.add(assistant, response_text) self.memory.add(user, error_msg) continue print(f[Step {step}] 调用工具: {tool_name}, 参数: {tool_args}) tool_result execute_tool(tool_name, tool_args) print(f[Step {step}] 工具结果: {tool_result}) # 把中间过程写入记忆供后续推理使用 self.memory.add(assistant, response_text) self.memory.add(tool, tool_result) current_messages self.memory.get_messages() return 已达到最大执行轮次任务未能完成请简化任务或检查工具调用。Agent.run是这个工具链的核心。它不断经历“模型推理 - 判断是否调用工具 - 执行工具 - 把结果写回上下文”的循环直到模型不再调用工具或者轮次耗尽。每一轮都打印运行日志这是后面排查和验证的关键。5.5 入口与运行# main.py from agent import Agent def main(): agent Agent() while True: user_input input(请输入你的问题输入 exit 退出: ).strip() if user_input.lower() exit: break if not user_input: continue print( * 50) result agent.run(user_input) print( * 50) print(最终结果:, result) print( * 50) if __name__ __main__: main()运行之前先把依赖安装好pip install -r requirements.txtrequirements.txt内容requests2.31.0 python-dotenv1.0.0然后启动python main.py6. 运行结果与效果验证6.1 预期运行过程输入问题时Agent 会打印每一步的推理和工具调用过程。例如输入北京今天天气怎么样顺便算一下 123 * 45预期会看到类似下面的执行轨迹请输入你的问题输入 exit 退出: 北京今天天气怎么样顺便算一下 123 * 45 [Step 1] 调用模型进行推理... [Step 1] 模型输出: tool_call{name: get_weather, arguments: {city: 北京}}/tool_call [Step 1] 调用工具: get_weather, 参数: {city: 北京} [Step 1] 工具结果: {city: 北京, weather: 晴25 度} [Step 2] 调用模型进行推理... [Step 2] 模型输出: tool_call{name: calculator, arguments: {expression: 123 * 45}}/tool_call [Step 2] 调用工具: calculator, 参数: {expression: 123 * 45} [Step 2] 工具结果: {expression: 123 * 45, result: 5535} [Step 3] 调用模型进行推理... [Step 3] 模型输出: 北京今天天气晴朗气温 25 度。123 * 45 的结果是 5535。 最终结果: 北京今天天气晴朗气温 25 度。123 * 45 的结果是 5535。 注意由于不同模型对提示的遵循程度不同实际输出格式可能略有差异但执行流程应该保持一致先调用天气工具再调用计算器工具最后汇总答案。6.2 如何判断成功判断这套工具链是否真正跑通可以从以下几个维度验证模型能够在需要时输出工具调用标记而不是自顾自地编造答案。工具调用能被正确解析工具名称和参数都能对应上。工具结果能回到模型上下文中并影响最终回答。连续多步工具调用场景下Agent 不会丢失前面的状态。多轮对话场景下Agent 能记住当前会话之前的上下文。达到最大轮次时会安全退出而不是死循环或直接崩溃。6.3 建立简单的评测集工具链搭好之后不要只测试一个例子就收工。建议准备一个小的评测集里面包含几类典型任务任务类型示例问题期望行为单工具调用北京天气怎么样调用 get_weather返回天气多工具组合北京天气和 12*15 的结果依次调用两个工具无需工具你好直接回答不调用工具工具参数缺失查一下天气模型应追问城市参数超长多轮连续提问 5 个问题上下文裁剪正常无崩溃把这些评测用例写成脚本每次修改工具链代码后都跑一遍。这是 Agent 工程化最重要的一步它决定了你的工具链是“能跑 demo”还是“能稳定迭代”。7. 常见问题与排查思路自己从零实现 Agent 工具链的过程中会踩很多坑。以下是高频问题与排查方法。问题现象可能原因排查方式解决方案模型始终不输出工具调用系统提示里没有把工具描述讲清楚打印发给模型的完整消息检查工具描述是否拼接优化工具描述明确“什么时候用、参数是什么”工具调用格式解析失败模型输出与tool_call标记不完全一致打印原始模型输出检查前后是否存在额外文字调整正则表达式或者要求模型严格按 JSON 输出执行循环停不下来工具结果无法支撑模型做出终止决策查看每一轮模型输出和工具结果增加最大轮次限制或优化系统提示要求模型及时收尾上下文很快超出限制每轮都追加消息从不做裁剪打印 Memory 中的消息数量配置最大消息数启动裁剪或摘要机制API 返回 401 或 403API Key 无效或没有读取到环境变量在配置层打印 Key 前缀检查 .env 文件和 dotenv 加载逻辑请求超时模型响应慢或网络不稳定查看错误堆栈增加超时时间增加重试机制工具执行报参数错误模型生成的参数和工具定义不一致打印工具注册表和实际入参增加参数校验解析失败时返回明确错误信息每次结果不稳定模型输出本身有随机性重复运行多次对比调整温度参数或固定种子参数排查 Agent 问题时最重要的一点是必须能看到完整的执行轨迹。强烈建议把每一轮的模型输入消息、模型输出、工具调用指令、工具返回结果全部打印或写入日志。很多问题只有回放执行轨迹才能定位。“Agent execution terminated due to error”这类报错如果不看执行轨迹基本无从下手。8. 工程化最佳实践与安全边界8.1 工具函数的权限控制与安全边界这是 Agent 生产化最核心的一条。模型输出的工具调用本质上是不可信的输入因为模型可能生成错误的参数也可能被恶意提示词引导调用危险工具。安全设计应该遵循最小权限原则工具函数只暴露业务需要的最小能力不要把一个完整的万能函数暴露给 Agent。涉及数据库写入、文件删除、数据修改、资金操作等敏感操作必须设置二次确认或人工审批机制。不要让 Agent 直接执行任意 Shell 命令或 Python 代码尤其是当工具的输入来自外部用户时。对工具执行结果要做校验避免把异常数据直接注入到模型上下文中。在测试环境中验证工具行为再考虑部署到生产环境并准备回滚方案。8.2 工具描述与参数设计工具并不是越多越好。工具描述写得不好模型会在不必要时调用工具粒度太细模型需要多步才能完成任务增加错误概率。建议按“业务能力”而不是“API 粒度”来封装工具。一个查询订单状态的工具应该封装好订单查询的完整逻辑而不是把好几个底层参数直接暴露给模型。在设计工具时还要注意参数约束。必填参数、可选参数、参数类型、取值范围这些信息都应该体现在参数 Schema 中。模型面对空泛的参数描述时常常会脑补一个不存在的值传给工具。8.3 日志、可观测性与进度打印一个生产级 Agent 工具链必须能够回答三个问题它为什么做出这个决策它调用了什么工具卡在了哪一步建议使用结构化日志记录每个环节的耗时和状态包括模型调用耗时、工具执行耗时、模型返回内容、工具返回内容。在本项目的Agent.run方法中已经加入了[Step N]形式的过程输出。真实项目中可以把这些信息输出到日志文件或可观测性平台便于事后分析和优化。8.4 配置管理Model 名称、API Base URL、API Key、最大轮次、超时时间等参数都不应该硬编码在代码里。建议统一走配置管理本地开发用.env文件生产环境用环境变量或配置中心。配置修改后应该能够通过热更新生效而不是每次改配置都要重新发版。8.5 成本控制与限流Agent 的一个隐藏成本问题是一次用户请求可能触发多次模型调用。一个复杂任务可能调用模型 5 到 10 次成本会线性增长。工程上可以做下面几件事对单次任务的模型调用轮次设置上限。对单用户请求的频率做限流。对模型输入输出 token 数量做统计和监控。提供任务级别的取消机制让用户在 Agent 卡住时能主动终止。优先使用性价比高的模型处理简单任务复杂推理再切换到更强的模型。8.6 从最小实现走向框架封装自己手写完这套代码之后再做技术选型时会有完全不一样的判断力。你会发现主流 Agent 框架解决的核心问题和这篇文章里的执行循环是类似的只是它们做了更多的抽象、兼容性和生态集成。你在实际项目中不一定需要自己维护工具链但了解底层机制能让你选择框架时有更清晰的依据也能在框架不满足需求时做出合理的扩展。9. 总结与后续学习方向这篇文章没有直接带你去读某个框架的文档而是先把 Agent 工具链的最小组成拆开从配置、工具、记忆、执行循环四个模块带你从零搭了一套可以运行的智能体。到这里你应该已经理解了一个 Agent 程序的核心运行机制模型负责推理决策工具负责真实行动记忆负责上下文管理循环负责把两者连接起来直到任务完成。下一步的实践建议很简单把这份代码跑通然后改造成你自己的第一个 Agent 项目。你可以给工具层增加一个新的业务工具比如查询数据库、调用内部接口、操作文件等然后写一个针对你的业务场景的评测集跑几轮看它在哪里会出错。如果你准备继续深入 Agent 开发可以沿着下面几个方向走深入看主流 Agent 框架的源码理解它们如何实现多工具编排、重试和异常恢复。研究多 Agent 协作和 Agent Graph尝试把一个复杂任务拆成多个角色。完善记忆系统把简单的裁剪策略升级为摘要记忆和向量检索记忆。建立更完整的评测体系包括单任务成功率、工具调用准确率、上下文注入准确率和端到端耗时。关注 Agent 安全测试包括提示注入、工具滥用、越权访问等与 AI 应用密切相关的新风险。这套代码只是一个起点但它的价值在于你亲手写过之后Agent 对你不再是一个黑盒。以后无论用什么框架、什么模型、什么工具链你都知道那层“魔法”背后发生的是什么。建议把这篇文章收藏备用等你开始改造自己的第一个 Agent 项目时再对照着一步步来会顺手很多。