从零搭建AI智能体:Agent架构核心与工具调用实战

发布时间:2026/10/22 7:58:28
从零搭建AI智能体:Agent架构核心与工具调用实战 做AI应用落地这两年我越来越觉得很多人把AI智能体的“架构”想复杂了。一聊起来就是多智能体协同、复杂规划、长期记忆、强化学习微调……听起来确实高级但真正动手写代码的时候大多数人第一步就卡住了根本不知道从哪里把第一行代码敲下去。这篇文章我不讲那些玄乎的概念直接带你把一个可运行的AI智能体从零搭出来核心代码全部贴出来每一个设计点都解释清楚为什么这么做。如果你正在入门AI应用开发或者已经在业务里接了大模型接口却总觉得“差一层”那你来对地方了。这个最小闭环跑通之后你会发现所谓Agent架构并不神秘本质就三件事让模型看见可用工具、按循环执行工具调用、把结果沉淀回对话里继续推理。后面再谈记忆、规划、并发、安全都是在往这个核心闭环上做增强。我会用Python做示例尽量避开某个特定厂商的SDK让你能平滑迁移到自己服务的模型接口上。先把架构骨架看清楚再谈其他。1. 先理解AI智能体的架构骨架1.1 从“能对话”到“能干活”Agent解决的本质问题过去一年的变化很明显单纯聊天问答的应用已经越来越没有竞争力了。你问一个大语言模型“帮我查一下项目目录下有哪些文档”它只会跟你道歉因为它压根碰不到你的文件系统。但AI智能体可以做到本质差异在于它多了一层“干活”的能力也就是工具调用。你可以把大模型理解成一个知识渊博但被困在封闭房间里的顾问。他什么都知道一点但就是没有手没有脚没办法翻资料、查系统、发请求。AI智能体要做的就是给这个顾问配上一个传话筒、一双手让他可以通过一系列预设好的工具去收集信息、执行操作再把结果拿回来整理成答复。这个比喻基本就是Agent架构的核心逻辑模型负责推理和决策工具负责落地和交互。所以我在设计Agent时第一个想清楚的问题永远是模型这次到底要解决什么问题需要碰哪些外部资源。资源抽象成工具问题拆成多步任务模型在循环里反复“想一步、动一步”最终收敛到结果。有了这个视角再去看各种Agent框架你就不会迷路。1.2 一个Agent需要的核心模块长什么样一个能跑通任务的Agent至少包含几个模块。不一定要很重但职责必须清晰任务理解模块把用户输入转成结构化目标弄清楚要做什么、有哪些约束工具注册表维护所有可调用函数及其参数说明让模型知道“我有哪些牌可以打”推理与决策模块本质是模型本身负责分析当前状态、选择下一步动作执行器根据模型选择的工具名和参数去真实调用对应函数记忆模块分短期和长期短期处理当前多轮上下文的裁剪长期沉淀历史经验和事实数据校验与修正模块发现工具调用失败或结果不合理时反馈给模型纠正。很多文章会把Agent描述得很玄实际拆开就是这些部件。我给你打个比方工具注册表有点像餐厅菜单模型是顾客菜单越清晰顾客越容易点对菜执行器是后厨菜单上有的菜才做得出来记忆是服务员记忆力既不能把前几桌的菜搞混也不能忘了客人刚说过忌口。模块之间的关系比模块本身更重要。模型并不是直接调用函数而是输出一个“想调用哪个工具、参数是什么”的结构化描述Agent代码再把它翻译成真实函数调用。这个解耦设计是Agent架构里最关键的一步。1.3 最容易被误解的三个架构观念我见过不少团队在Agent架构上栽跟头往往不是因为代码难写而是三个观念没掰正。第一个错误观念是“Agent就是调大模型接口”。实际上调接口只是一次对话而Agent是一整个循环。模型回一句、Agent执行一步工具、把新的观察回填给模型、模型再推理下一步。这个循环的次数和终止条件才是架构里要重点设计的。第二个错误观念是“工具越多越强大”。工具定义如果混乱、描述含糊、参数文档不完整模型反而更容易选错或手足无措。我自己的经验是工具注册表宁可精简每个工具描述里写清楚“什么时候用”“参数代表什么”比堆二十个模棱两可的工具好用得多。第三个错误观念是“提示词能解决一切”。提示词确实重要但工程上必须有兜底方案工具可能抛异常、模型可能连续调用同一个工具死循环、上下文可能膨胀到溢出。这些都要靠代码机制去约束不是多写两句“请小心谨慎”就能解决的。2. 手把手搭建最小可用Agent代码与运行流程2.1 准备环境与基础依赖这个项目对Python版本要求不高3.9以上完全够用。整个Agent核心其实只需要一个第三方库那就是requests用来向模型服务端发起HTTP请求。其他标准库如json、os、time足够。我建议先建一个独立目录再用虚拟环境隔离依赖避免把系统Python环境搞乱。命令行操作如下mkdir agent-demo cd agent-demo python3 -m venv .venv source .venv/bin/activate pip install requests接着设置两个环境变量一个指向模型服务的接口地址一个放密钥。我特意把接口地址做成可配置而不是写死就是为了让你能对接自己实际在用的模型服务export LLM_API_ENDPOINThttps://your-llm-server.example.com/v1/chat/completions export LLM_API_KEYyour-key-here现在的模型服务商基本都兼容同一种工具调用格式也就是模型会返回一个结构化结果告诉你它想调用哪个工具、参数是什么。我用HTTP请求的方式直接对接这个通用格式不需要依赖某个厂商的专用SDK这样后续换模型服务商成本会低很多。2.2 工具注册表让大模型“看见”可用的函数工具注册表这个模块我的设计逻辑很简单一个字典存放工具名、描述、参数格式说明和真实处理函数。每次和模型通信之前Agent会把所有工具的描述信息序列化成一个JSON结构发给模型等同于给模型一张完整的菜单。from typing import Callable, Any class ToolRegistry: def __init__(self): self._tools {} def register(self, name: str, description: str, schema: dict, handler: Callable): self._tools[name] { description: description, schema: schema, handler: handler, } def specs(self): tools [] for name, info in self._tools.items(): tools.append({ type: function, function: { name: name, description: info[description], parameters: info[schema], }, }) return tools def run(self, name: str, **kwargs): if name not in self._tools: raise KeyError(f工具 {name} 未注册) return self._tools[name][handler](**kwargs)这里参数格式schema用的是JSON Schema结构。为什么要这个结构因为模型的工具调用结果需要根据它生成正确的参数。比如你告诉模型某个工具需要“query”字段模型就会在返回内容里带上{query: 监控告警}。如果参数说明不清晰模型会乱传参数所以注册表里每一个工具的description和schema都要认真写。为了方便给函数打标注我再加一个装饰器工厂让工具定义看起来更干净def register_tool(name: str, description: str, schema: dict): def decorator(func): registry.register(name, description, schema, func) return func return decorator现在定义两个模拟的本地知识库工具先不接真实数据库但整个调用链路是通的FAKE_DOCS { 监控告警设计: 核心建议告警分级、自动通知、关联分析, 容量规划方案: 核心建议月度评估、预留20%冗余、关键路径降级, 发布流程规范: 核心建议灰度发布、回滚预案、变更审批, 日志采集治理: 核心建议统一格式、采样降噪、冷热分层存储, 故障应急预案: 核心建议定期演练、明确角色、告警与处置联动, } register_tool( search_docs, 在本地知识库中检索与query关键词相关的文档返回文件名和摘要, { type: object, properties: { query: {type: string, description: 检索关键词} }, required: [query], } ) def search_docs(query: str): result {} for title, summary in FAKE_DOCS.items(): if query in title or query in summary: result[title] summary return result if result else {提示: 没有匹配的文档} register_tool( list_docs, 列出本地知识库中的所有文档名称, {type: object, properties: {}} ) def list_docs(): return list(FAKE_DOCS.keys())工具定义里有一点要注意description一定要写清楚“什么场景下用”。因为模型是根据文字描述去匹配用户意图的描述越具体选错工具的概率越低。比如这里我写“检索与query关键词相关”模型遇到“找一找监控告警相关文档”这类请求时就会优先想到search_docs而不是list_docs。2.3 Agent主循环ReAct推理与工具调用的完整实现核心还没登场Agent主循环。先讲思路。ReAct模式通俗说就是“想一步做一步”。模型先思考当前要用什么工具、传什么参数执行完之后把结果塞回对话里模型再根据结果决定是继续调用工具还是给最终回答。这个循环我给它设了个最大步数上限避免模型卡在死循环里。先实现一个模型客户端封装接口调用逻辑import json import os import time import requests class LLMClient: def __init__(self, endpointNone, api_keyNone, modelNone): self.endpoint endpoint or os.getenv(LLM_API_ENDPOINT) self.api_key api_key or os.getenv(LLM_API_KEY) self.model model or os.getenv(LLM_MODEL, default-model) self.timeout int(os.getenv(LLM_TIMEOUT, 60)) def chat(self, messages, tools): headers { Authorization: fBearer {self.api_key}, Content-Type: application/json, } payload { model: self.model, messages: messages, temperature: 0.2, } if tools: payload[tools] tools resp requests.post(self.endpoint, headersheaders, jsonpayload, timeoutself.timeout) resp.raise_for_status() data resp.json() return data[choices][0]这里有个细节temperature我设成了0.2。工具调用任务追求的是确定性和准确性温度太高会导致模型偶尔输出很随机的参数同一个任务两次结果不一致。如果后面你要用Agent做创意类任务可以适当调高但工具调用的主流程建议保持低温度。然后是Agent本体class Agent: def __init__(self, client: LLMClient, registry: ToolRegistry, system_prompt: str, max_steps: int 6): self.client client self.registry registry self.system_prompt system_prompt self.max_steps max_steps def run(self, user_input: str): messages [ {role: system, content: self.system_prompt}, {role: user, content: user_input}, ] for step in range(self.max_steps): try: result self.client.chat(messages, self.registry.specs()) except Exception as e: return f模型调用失败: {e} message result[message] messages.append(message) reason result.get(finish_reason) if reason stop or not message.get(tool_calls): return message[content] or 任务执行结束 for call in message[tool_calls]: fn call[function] name fn[name] args json.loads(fn[arguments] or {}) try: tool_output self.registry.run(name, **args) except Exception as e: tool_output {error: str(e)} messages.append({ role: tool, tool_call_id: call[id], content: json.dumps(tool_output, ensure_asciiFalse), }) return 达到最大步数任务未完成这个循环的逻辑可以这样理解messages是Agent的完整工作记忆模型每一步都基于这份记忆做决策。模型想调用工具我就去执行工具结果作为一条role为tool的消息追加进来模型再读一遍直到它觉得信息够了给出一段最终答复此时finish_reason通常是stop。这就是完整的ReAct循环。还要配一个系统提示词。系统提示词其实就是给这个Agent设定“职业身份”和操作约束SYSTEM_PROMPT 你是某本地知识库助手。 你需要根据用户请求选择合适的工具检索资料。工具返回结果后请整理成简洁、准确的中文回答。 如果工具没有返回任何内容请直接告知用户未找到相关资料。 不要编造工具结果一切结论以工具返回为准。 这里那句“不要编造工具结果”不是摆设。我在实际使用中遇到过不少模型在没有工具返回的时候强行给一个看似合理的回答这非常危险尤其是在知识库类任务里。所以系统提示词里把这条约束写清楚虽然不能百分百杜绝但能明显降低幻觉概率。2.4 跑通一个真实任务现在把整个流程串起来跑一次。假设用户提问“搜索与监控告警有关的文档并总结核心建议”你可以把下面的代码作为入口文件if __name__ __main__: client LLMClient() agent Agent(client, registry, SYSTEM_PROMPT) answer agent.run(搜索与监控告警有关的文档并总结核心建议) print(answer)整个执行流程在内部是这样的第一步模型看到用户问题结合工具清单规划出动作search_docs参数query设为“监控告警”。于是返回一个tool_calls结构。第二步Agent执行search_docs找到“监控告警设计”这篇文档的摘要。第三步模型读到工具结果后整合成最终回答“监控告警设计的核心建议是告警分级、自动通知、关联分析”。整个流程大概在几秒内完成。我建议你拿到代码后先跑一遍然后再去改数据、改工具、改系统提示词看看同一个任务在不同参数组合下会有哪些变化。我在调试时最喜欢的做法是打印出每一轮messages内容这样能直观看到模型决策的过程比猜问题根源高效得多。3. 让Agent更聪明记忆、规划与自我修正的工程实现基础Agent已经能跑通单轮工具调用任务但离“好用”还有距离。真实场景往往是多轮对话、长文本检索、多步骤拆解要处理这些就必须给Agent加上记忆管理和任务规划能力。3.1 短期记忆管理消息窗口的裁剪与摘要短期记忆是什么其实就是当前对话里那串messages数组。问题是每调用一次工具就会增加至少两条消息模型决策工具结果几十步下来messages会非常长既占token又可能超出模型上下文窗口。所以必须有裁剪策略。我常用的策略是滑动窗口加摘要压缩保留系统提示词和最近N轮对话把更早的内容浓缩成一小段摘要拼在窗口前面。这样既不会完全丢上下文也能控制长度。class SlidingMemory: def __init__(self, keep_rounds10): self.keep_rounds keep_rounds def compress(self, messages): if len(messages) self.keep_rounds * 2 1: return messages head messages[:1] rest messages[1:] recent rest[-self.keep_rounds * 2:] dropped rest[:-self.keep_rounds * 2] summary self._summarize(dropped) return head [{role: user, content: f之前对话摘要{summary}}] recent def _summarize(self, dropped): parts [] for msg in dropped: content msg.get(content, ) if isinstance(content, str) and content: parts.append(content[:80]) elif msg.get(tool_calls): for call in msg[tool_calls]: params call[function][arguments] parts.append(f调用工具{call[function][name]}({params[:50]})) return .join(parts[-20:]) if parts else 无关键历史信息这个实现是轻量级的实际生产里我更推荐用模型做摘要比如“请把以上内容压缩成50字以内的要点”但代价是额外一次模型调用。所以压缩频率要控制好不必每一轮都做只有当消息数超过阈值时才触发。还有一个容易被忽略的点tools本身也会占上下文工具描述越长、数量越多留给对话的空间就越少。所以注册表的描述要精炼schema里的properties只放必要字段一些啰嗦的说明可以挪到description里。3.2 长期记忆把关键信息沉淀到可检索的存储中长期记忆解决的是另一个问题这次任务学到的知识下次还能不能复用。比如用户上次明确说“告警阈值不要写死”如果Agent没有长期记忆下次生成方案时还是老样子这就很可惜。我设计了一个极简版本的长期记忆存储先不做重向量库但保证接口语义清晰以后要换成向量检索时改动很小。核心思路就是把一段文本保存下来再按关键词相关性召回。class LongTermMemory: def __init__(self, storage_pathmemory.json): self.path storage_path self.items [] self._load() def _load(self): if os.path.exists(self.path): with open(self.path, r, encodingutf-8) as f: self.items json.load(f) def add(self, text, metaNone): self.items.append({text: text, meta: meta, time: time.time()}) self._flush() def _flush(self): with open(self.path, w, encodingutf-8) as f: json.dump(self.items, f, ensure_asciiFalse, indent2) def ngrams(self, text, n2): text text.replace( , ) return {text[i:in] for i in range(len(text) - n 1)} def search(self, query, top_k3): q_grams self.ngrams(query) scored [] for idx, item in enumerate(self.items): doc_grams self.ngrams(item[text]) score len(q_grams doc_grams) / max(len(q_grams), 1) scored.append((score, idx)) scored.sort(reverseTrue) return [self.items[i] for _, i in scored[:top_k] if _ 0]这里用二元字组的重叠度做相似度匹配是纯朴素的实现适合没有embeddings服务的场景。但要注意真正的语义检索需要向量化比如用某embedding模型把文本转成向量再用余弦相似度找最近邻。只要对外暴露add和search两个方法后续切换内部实现非常容易这也是我把存储抽象成两个方法的原因。实际使用时机也很关键不是每轮对话都往长期记忆里写。我通常只在任务结束或者用户给出明确反馈时写入避免把中间状态的噪音也存了进去。3.3 任务拆解从一次问答到多步执行有些任务太复杂比如“整理项目全部文档输出一份周报”靠模型在单个循环里可能绕来绕去。更稳妥的方式是把任务先拆成几个子任务再逐个执行。一种做法是外部编排用一个额外模型调用生成子任务列表然后Agent顺序执行。这个过程完全可以写代码实现。先准备一个拆解提示词PLAN_PROMPT 把下面的用户目标拆解为最多3个可交给智能体执行的子任务。 每个子任务输出为一行以 - 开头。 只输出任务列表不要做额外解释。 用户目标{goal} 然后解析模型返回的文本提取每行任务def parse_plan(raw: str): steps [] for line in raw.strip().splitlines(): line line.strip() if line.startswith((-, *)): steps.append(line.lstrip(-* ).strip()) elif any(line.startswith(f{i}.) for i in range(1, 10)): steps.append(line.split(., 1)[1].strip()) return steps拿到子任务列表后让一个Agent逐个执行再把结果汇总给一个“总结Agent”整理输出。这就是很常见的主从式Agent结构。举个例子用户目标是“整理故障应急文档并生成建议清单”。拆解结果可能是第一步检索故障应急相关文档第二步读取文档摘要第三步提炼核心建议。每个子任务都是普通Agent最擅长的单步调用整体执行质量和可控性都比让一个Agent自由发挥要好很多。值得强调的是拆解不是越细越好。子任务之间如果有依赖拆太细反而增加通信成本如果子任务之间没有共享上下文还可能丢失关联信息。我一般控制在3到5个子任务并且尽量让每个子任务目标单一、彼此独立。4. 从Demo到生产那些文档里不会写的实战坑代码跑通只是第一步真正麻烦的是让它稳定运行在生产环境。我在这里把踩过的一些坑集中说出来每一个都是花钱买来的经验。4.1 工具执行异常不能中断流程要把错误回喂给模型这是新手最容易犯的错。工具执行时如果遇到参数异常、文件不存在、网络超时直接把异常抛出Agent就会直接中断返回错误。但更好的做法是把异常信息转化成一条tool消息让模型看到“工具执行失败了原因是……”然后自己决定怎么办。我在前面Agent代码里已经写了try: tool_output self.registry.run(name, **args) except Exception as e: tool_output {error: str(e)}这样模型看到错误信息后通常会有两类反应一是重新调整参数再试一次二是换一个更合适的工具三是诚实告诉用户当前能力不足。这三种结果都比直接抛异常强得多。我在实际调试中见过很多次模型第一次调用工具参数写错看到错误后第二次就自己纠正了。这种自愈能力正是Agent区别于普通脚本的关键。但也要设防错误信息返回给模型会导致模型反复用同样的错误参数重试。所以max_steps要设上限并且可以在错误信息里附带一句“请不再尝试相同参数”引导它换思路。4.2 模型超时与限流重试策略要讲究大模型服务经常因为负载过高返回5xx错误或者因为触发限流返回429。如果不做重试线上任务会大量失败。但重试也不能无脑重试必须做指数退避。不推荐对401、403这类鉴权错误做重试那是配置问题重试一百次也没用。只对429、500、502、503、504这类瞬时错误重试比较合理。def chat_with_retry(client: LLMClient, messages, tools, retries3, base_delay1.0): for attempt in range(retries): try: return client.chat(messages, tools) except requests.HTTPError as e: status e.response.status_code if status in (429, 500, 502, 503, 504): time.sleep(base_delay * 2 ** attempt) continue raise except requests.Timeout: time.sleep(base_delay * 2 ** attempt) raise RuntimeError(模型调用多次重试失败)有一个细节我特别想提醒不要用固定间隔重试。当服务已经过载时所有客户端同时用相同间隔重试等于再制造一波流量冲击。指数退避能让客户端自动拉开请求时间这是减轻服务压力的基本修养。超时时间也要仔细调。Agent的每次调用都可能因为工具结果很长而变慢我把超时设在60秒左右。如果你上游模型推理慢还要适当拉长否则会出现“服务其实在正常处理但客户端已经放弃”的假失败。4.3 可观测性给Agent装上日志探针Debug Agent比Debug普通程序更难受因为你不知道模型内部在“想什么”。唯一的办法是把每一步的外部行为记录清楚。我习惯给每个任务生成一个trace_id贯穿整个链路。import logging import uuid logger logging.getLogger(agent) trace_id uuid.uuid4().hex[:8] for step in range(max_steps): logger.info([%s] step%d messages_len%d, trace_id, step, len(json.dumps(messages, ensure_asciiFalse))) ... start time.perf_counter() tool_output registry.run(name, **args) latency_ms (time.perf_counter() - start) * 1000 logger.info([%s] tool%s args%s result%s cost_ms%.1f, trace_id, name, args, str(tool_output)[:200], latency_ms)在日志里至少要看几类信息当前step、消息体长度、调用的工具名、参数、返回结果、耗时。这些能让你快速判断问题属于哪一类是模型反复调用工具规划问题是参数传错工具定义问题还是工具本身太慢性能问题。还有一个建议是给工具结果做截断日志。有些工具返回很长文本全量打日志会把日志文件撑爆。我通常只截取前200个字符记录需要细节时再单独把完整结果写入调试文件。4.4 权限与安全边界工具不该什么都让你干Agent的工具本质上是把一段代码的入口开放给模型模型又受用户输入影响这就意味着攻击者可能通过恶意构造用户输入诱导模型调用危险工具。这个话题很容易被忽略但一旦出事影响很严重。我给自己定了几个基本原则。第一工具运行环境要和核心系统隔离至少不能用拥有生产库最高权限的账号去跑工具我通常会在独立服务进程里执行工具代码。第二对于写操作类工具比如删除文件、修改配置、发送消息必须在工具内部加二次确认机制或者限制为“预览模式”。第三从外部读取的文本如果可能包含敏感信息在回填给模型之前先做脱敏处理。第四永远不要在系统提示词或日志里出现密钥、证书、内部地址等敏感信息。不要觉得这些步骤繁琐Agent越强大它被滥用的破坏力就越大。工具注册表加一个字段来表示“权限等级”执行前统一校验是很简单但很有价值的做法。5. 成本控制、效果评估与后续扩展方向5.1 token成本怎么估算与控制Agent每走一步messages里追加的内容都会被完整发到模型端所以token消耗比普通对话要快得多。一个5步工具调用的任务光是消息体本身体积就可能翻几倍再加上tools描述成本一下就上来了。业界有个粗略估算方法消息体JSON字符串的长度除以3可以当做一个近似的token数因为1个英文字符约等于0.25到0.3个token但这只是粗略值中文字符占用更多。真实成本看服务商返回的usage字段最准。代码里可以写一个小函数做前置预算def estimate_tokens(messages): text json.dumps(messages, ensure_asciiFalse) return len(text) // 3控制token成本有几个方向。第一精简工具描述每个工具的description控制在50字以内schema只保留必要字段。第二缩短工具结果回填长度比如文件检索结果只保留前几个字段不要整个文件内容都塞回去。第三及时使用短期记忆模块裁剪早期消息。第四为不同任务选择不同规格的模型简单检索任务用轻量模型复杂规划任务用强模型。我在一个内部项目里做过一个对比同样的任务不裁剪消息时平均消耗约1万token加了滑动窗口压缩后降到4000多。这个差距在每日上万次调用时就是实打实的成本差距。5.2 如何给Agent建立效果评估体系Agent效果评估比普通算法模型更主观但不能因此就不评估。我通常准备一个固定任务集大约十来个典型场景每次改动架构或提示词后都跑一遍。评价指标如下指标含义我关注的原因任务完成率最终是否产出有效结果最核心指标反映整体可用性平均调用步数完成任务用了多少轮工具调用步数越多成本越高、失败风险越大工具错误率工具调用时报错的比例报错多往往代表工具定义或上下文有问题上下文峰值长度任务过程中messages最长的时刻防止模型卡在长上下文里溢出单次任务成本估算token数或费用决定方案能否规模化有一点很重要测试用例要覆盖边界场景。比如“工具没有返回结果时模型会不会诚实告知”“工具连续失败时模型会不会换策略”这些比测试理想场景更能暴露问题。我自己调试时常做的一件事就是把失败案例的完整日志保存下来过一段时间集中复盘。有时候你会惊讶地发现同一个问题反复出现原因往往不是模型笨而是某个工具描述一直有歧义。5.3 什么时候该把单体Agent拆成多Agent文章开头提到多Agent很多人会觉得那是架构的终极形态但其实大部分业务阶段不需要它。我判断的标准是三条工具数量超过二十个且互相之间职责差异大、不同任务对模型能力要求差距明显、任务本身有明显的阶段划分且需要隔离权限。满足任何一条再考虑拆分。典型拆分方式是先把工具按领域分群比如“知识检索类Agent”管搜索、摘要、文档读取“业务执行类Agent”管下单、审批、数据变更。上层有一个规划器负责把用户请求分发给对应Agent。拆多Agent的好处是职责单一、权限好控制、上下文干净代价是通信成本增加、排查问题链路变长。所以我的建议始终是先单体跑起来观察真实瓶颈再决定是否拆分。没有一个Agent框架能替你做这个业务判断。把上面这些代码和思路组合起来你会发现Agent工程其实不复杂一个注册表、一个循环、一套记忆管理再加上工程层面的容错和可观测性就已经是一个相当完整的智能体底座了。后续加规划器、加长期向量库、加多Agent协作都是在这个底座上做扩展而不是推翻重来。我自己在维护这类系统时最大的感受就是“稳定压倒一切”先让它在小范围内可靠地完成任务再慢慢扩大它的工具边界和能力范围。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询