“从 0 到 1 搭建你的 AI Agent 平台当 Agent 有了工厂人人都能造同事”——这句话真正值得琢磨的不是“Agent”这个流行词而是“工厂”。搭一个能聊天的Agent现在的模型能力已经足够真正难的是把一个一个“会聊天的原型”变成“能批量上岗的数字同事”。我过去半年一直在折腾这件事踩过的坑比写过的代码多。这篇文章不打算做概念科普就按我从零搭平台的真实路径把AI Agent和LLM、AI模型的区别讲清楚把最小闭环、工具调用、记忆设计、多Agent编排、可观测性这些环节一个个拆开顺便把Spring AI DeepSeek这套企业级玩法完整过一遍。适合正在选型或者已经决定自建Agent平台的团队参考。1. 先搞清楚AI Agent、LLM、AI 模型到底差在哪很多团队上来就喊“我们要做个Agent平台”但拉通之后发现大家说的根本不是一回事。有人觉得Agent就是ChatGPT套壳有人觉得把大模型API接上就完事了还有人纠结“DeepSeek和GPT哪个是Agent”——这几个概念必须先在团队里对齐否则后面所有架构讨论都是鸡同鸭讲。AI模型是最底层的东西本质是一个参数化函数输入一串token输出一串token或者向量。GPT系列、DeepSeek-V3/R1、Qwen这些都属于这一层。LLM是AI模型里专攻语言理解和生成的那一类现在大家口中的“大模型”“基座模型”通常指的就是LLM。它们本身不产生行动只产生“下一步该说什么”的预测。Agent是什么它不是模型而是拿着模型去干活的完整程序。一个Agent要有明确目标要有记忆来存储对话和历史决策要能调用外部工具去影响真实世界还要有个循环调度机制来决定下一步做什么。你可以把LLM想成一个刚毕业的聪明新人而Agent是给这个新人配好了工位、电脑、通讯录、任务清单和社保卡的完整员工。同一个新人可以干不同岗位同一个LLM也能被多个Agent共用。1.1 DeepSeek 到底属于哪一层这个热搜问题很典型。DeepSeek比如deepseek-chat、deepseek-reasoner属于“模型层”它就是一个LLM。你可以把它接到自己的Agent里当大脑但如果你只是打开DeepSeek官网聊了几句那你既没有在搭建Agent也没有在使用Agent你只是在调用一个聊天机器人。Agent和普通聊天的分水岭在于模型有没有主动调用工具、有没有为了完成目标做多轮推理、有没有记住关键信息。我经常用一句话跟团队里的人对齐**模型是发动机Agent是整车。**发动机可以单独卖但你要运货必须把发动机装进底盘、接上方向盘、加上油箱。DeepSeek很便宜、能力也不错作为Agent平台的首个模型接入是很务实的选择但它只解决“大脑”那一层的问题平台要解决的是剩下所有的“身体”和“流程”。1.2 为什么需要“Agent工厂”而不是“一个Agent走天下”单个Agent只能解决一个具体的任务闭环。比如“售后工单分类Agent”你把工单文本传给它它返回分类结果这已经很好了。但企业要的是“造50个数字同事”一个负责工单分类一个负责知识库问答一个负责定时巡检一个负责生成日报每个都有不同的工具权限、不同的知识库、不同的会话策略。这时候你再一个个手工去写、去调、去部署维护成本就会爆炸。“Agent工厂”的价值就在于把重复的部分抽象出来模型接入统一管理、工具注册统一规范、记忆逻辑统一实现、权限审计统一治理。新同事的上线流程从“开发两周”压缩到“配置半天”这才是平台存在的意义。所以我把“当一个Agent跑通之后如何让第2个、第50个Agent快速产出”当成整个从0到1建平台的第一目标。2. 从0到1拆解最小闭环Agent必须要有的4个零件先看一个最简单的Agent长什么样。不带花哨架构抛掉K8s、抛掉多租户一个能跑的Agent闭环至少要包含四个零件大脑LLM负责理解、推理、生成。比如DeepSeek、通义千问、GPT系列。记忆短期记忆是当前会话的上下文窗口长期记忆是存在向量数据库里的历史事实、偏好、业务规则。工具让Agent具备行动能力。查天气、查订单、写数据库、发邮件、调内部API都属于工具。调度循环决定“下一步做什么”的循环逻辑。先规划、再调用工具、观察结果、再规划直到任务完成或到达最大轮数。在这四件套里工具和调度是普通对话系统不会碰的东西也是Agent能够“干活”而不是“聊天”的关键。2.1 工具调用的真实流程一个“查天气”的例子以“查天气”为例。用户问“北京今天适合穿短袖吗”没有工具时模型只能凭训练数据里的模糊记忆回答而且大概率是错的。接入工具后调用链是这样的用户提问进入Agent调度器把“当前问题 可用的工具列表”发给LLMLLM判断需要实时天气数据返回一个结构化指令调用getWeather参数{city: 北京}Agent平台捕获这个指令执行真实天气API拿到“晴、28℃、北风3级”把工具结果连同原始问题一起回传给LLMLLM最终给出“北京今天28℃体感偏热建议穿短袖或薄衬衫”。这个流程很多人叫Function Calling本质上是模型在你定义好的工具清单里做选择题。工具描述写得越清晰模型选对的概率越高工具返回的数据越规范最终回答质量越可控。2.2 技术选型Java 系还是 Python 系这是我在各个团队被问最多的问题。我的答案其实很直接如果你的团队主要搞业务系统、现有技术栈是Spring Cloud那就别犹豫走Spring AI。如果你的目标是快速做研究和算法验证、团队以Python为主那就走LangChain/LlamaIndex。Python生态在Agent领域确实起步早LangChain、LangGraph、LlamaIndex、CrewAI你都能找到大量参考资料。但Python体系下做生产级平台工程化成本一点都不低。LangChain的API大版本之间经常改接口升级一次想骂人多Agent编排在Python里往往要靠自己写状态机。而Spring AI后发有个好处就是背靠Spring Boot的成熟工程体系配置管理、依赖注入、监控埋点、网关安全通通可以复用。我用Spring AI的一个很直接的原因是企业内部已经有很多Java写的服务Agent平台要调用订单系统、CRM、ERP的APIJava这边直接封装SDK就能接入不用跨语言再包一层HTTP。统一技术栈带来的维护收益在平台进入长期迭代后会越来越明显。3. 亲手造一个“同事”Spring AI DeepSeek 实现可对话的Agent光讲概念没有用直接上手把第一个Agent跑起来。这里用Spring AI接入DeepSeek因为DeepSeek API兼容OpenAI协议所以可以直接用OpenAI的starter来对接成本低、接入快。3.1 环境准备与依赖引入基础环境JDK 17 或 21Spring Boot 3.2 或更高版本Maven 3.8DeepSeek API Key没有就去官方平台申请充值几块钱就够测试Maven依赖核心就这两个dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-openai/artifactId version1.0.0/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency这里要注意Spring AI版本迭代很快1.0.0之后的API和之前0.8.x有较大差异。建议直接用一个稳定版本后面所有代码示例都基于Spring AI 1.0.0。然后配置application.ymlspring: application: name: agent-factory ai: openai: base-url: https://api.deepseek.com/v1 api-key: ${DEEPSEEK_API_KEY} chat: options: model: deepseek-chat temperature: 0.6base-url指向DeepSeek的OpenAI兼容接口就行。如果你后面要接其他模型比如通义千问也兼容OpenAI协议改这个base-url和model就完事平台支撑多模型的能力从第一行配置就开始铺垫了。3.2 注册工具让Agent具备行动力注册一个“查询天气”的工具。在Spring AI里工具通过FunctionCallback注册然后交给ChatClient调用。先定义入参对象public record WeatherRequest(String city) {}再定义返回对象public record WeatherResponse(String city, String condition, Integer temperature) {}接着实现一个工具类import org.springframework.ai.model.function.FunctionCallback; import org.springframework.ai.model.function.FunctionCallbackWrapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class AgentToolsConfig { Bean public FunctionCallback weatherFunction() { return FunctionCallbackWrapper.builder(getWeather, (WeatherRequest req) - { // 真实项目中这里调用天气API比如和风天气、高德天气 // 测试阶段可以先返回固定数据 return new WeatherResponse(req.city(), 晴, 28); }) .setDescription(查询指定城市的实时天气情况) .setInputType(WeatherRequest.class) .build(); } }这个description特别重要。模型不理解Java方法名它只读这段描述来决定“要不要用这个工具”。描述要写清楚“什么时候用、参数含义是什么”比如“当用户询问某个城市当前天气、温度、是否适合出行时调用此工具”。千万不要只写“查询天气”。3.3 写一个带工具的ChatClient用ChatClient完成对话循环import org.springframework.ai.chat.client.ChatClient; import org.springframework.stereotype.Service; Service public class AgentService { private final ChatClient chatClient; public AgentService(ChatClient.Builder builder) { this.chatClient builder.build(); } public String chat(String userMessage) { return chatClient.prompt() .user(userMessage) .functions(getWeather) // 绑定天气工具 .call() .content(); } }写个Controller跑起来RestController public class AgentController { private final AgentService agentService; public AgentController(AgentService agentService) { this.agentService agentService; } PostMapping(/chat) public String chat(RequestBody MapString, String body) { return agentService.chat(body.get(message)); } }启动后POST一个{message: 北京现在适合穿短袖吗}Agent会先通过getWeather拿到北京天气再结合温度回答你。如果你没有绑定functions(getWeather)模型就只会瞎猜。这一个区别就是“聊天机器人”和“Agent”的分水岭。3.4 给Agent加上记忆别让它“转身就忘”这个阶段的问题马上会出现用户说“那上海呢”Agent不知道“那”指的是什么。因为每次请求都是独立的没有上下文。短期记忆最简单的实现是维护一个Conversation会话对象public class Conversation { private String conversationId; private ListMapString, Object messages new ArrayList(); public void addUserMessage(String content) { messages.add(Map.of(role, user, content, content)); } public void addAssistantMessage(String content) { messages.add(Map.of(role, assistant, content, content)); } }调用时把历史消息一起传进去。Spring AI的ChatClient支持messages()传历史public String chat(String conversationId, String userMessage) { Conversation conv conversationStore.get(conversationId); conv.addUserMessage(userMessage); String reply chatClient.prompt() .messages(conv.toMessageList()) .functions(getWeather) .call() .content(); conv.addAssistantMessage(reply); conversationStore.save(conversationId, conv); return reply; }长期记忆更复杂。简单说就是把业务事实提取出来向量化后存进向量数据库比如Redis或独立的Milvus、pgvector下次用户提问时先做相似度检索把相关记忆塞进提示词里。这个在平台设计里再接但不能不做因为Agent最怕“每句话都当第一次见面”。4. 从“单个Agent”到“Agent工厂”平台化的六个核心设计一个Agent跑通是第一步但离“工厂”还有很大距离。下面这六个设计是我认为平台化过程中最核心、也最容易踩坑的地方。4.1 多Agent编排与消息路由50个Agent上线后用户应该找谁这需要一个路由层。常见的做法是“主管Agent 专业Agent”模式。主管Agent主要负责意图识别把任务分发给对应的专业Agent专业Agent各自维护自己的提示词、工具集和知识库。比如售后Agent负责退换货、订单问题工具权限绑定订单API、售后API知识Agent负责员工制度问答挂载HR制度知识库运维Agent负责日志查询、告警摘要工具权限绑定日志平台、监控平台。主管Agent本身不做具体业务它只做“应该让谁处理这件事”的分类。这个设计能大幅降低单个Agent提示词的复杂度也方便后续新增Agent新同事注册到工厂主管Agent的工具列表里多一项选择即可。4.2 任务队列与异步执行不是所有Agent都需要实时响应。批量生产日报、定时巡检、大数据量分析这些任务如果同步跑用户会一直卡在加载里。平台需要一个统一的异步任务队列。我用RabbitMQ做任务分发的时候核心流程是用户提交任务API返回taskIdAgent编排器把任务发送到对应队列消费者拉取任务调用Agent执行执行进度写回任务状态表用户通过轮询或WebSocket查询进度完成后获取结果。任务状态机至少要设计这几个状态状态含义常见流转PENDING排队中提交 - PENDINGRUNNING执行中PENDING - RUNNINGWAITING_TOOL等待工具调用结果RUNNING - WAITING_TOOL - RUNNINGSUCCEEDED成功RUNNING - SUCCEEDEDFAILED失败RUNNING - FAILEDCANCELLED取消任意 - CANCELLED为什么状态机这么重要因为Agent执行过程中有大量外部工具调用一个HTTP请求可能几十秒如果进程重启至少要知道任务跑到哪一步了。4.3 可观测性与成本控制Agent平台有一个非常现实的问题不可观测。传统接口慢你打一个日志就能看到耗时。Agent慢可能是模型推理慢、可能是工具调用慢、可能是规划循环太多轮而且每次调用都在花钱。我强制要求平台记录以下指标每次调用的模型名称输入Token数和输出Token数工具名称和每次工具的耗时执行总耗时总轮数估算成本用户和租户标识。用OpenTelemetry把追踪接到企业现有的监控体系里同时在日志中输出这次Agent调用的完整轨迹[AgentTrace] taskId63a91f, userIdu1002 - plan: need weather - tool: getWeather(city北京), cost120ms, ok - plan: final answer - llm: modeldeepseek-chat, promptTokens680, completionTokens210 - total: 1.84s, cost0.0021 CNY这样每次用户投诉“这个Agent怎么这么慢”你都不用猜直接看轨迹链路是卡在哪个环节。成本控制也一样按租户聚合Token消耗月底一算清清楚楚。成本失控往往不是模型贵而是提示词里塞了太多历史记录和没用的检索上下文后面排查章节会说。4.4 权限模型与安全隔离Agent能调用什么工具必须跟着用户权限走不能跟着Agent自己的“热情”走。一个普通员工问“帮我查询所有人的工资”工资查询工具虽然存在但如果这个用户没权限Agent就算生成了调用意图平台也要拦截。工具权限要做两层校验注册时声明工具可见范围比如salaryQuery工具标记为roleHR_MANAGER执行时校验用户身份拿到当前用户上下文校验角色、部门、数据权限。另外API Key绝对不能出现在前端代码里。平台统一管理模型API Key用户只能通过后端的Agent服务间接使用。如果Agent配置了写数据库这种破坏性工具建议加一个人工审批节点Agent生成SQL和执行计划后先推送给管理员审核确认后才真正执行。4.5 知识库与RAG的接入Agent如果没有企业知识库支撑就是个“通才但不是行家”。要让Agent回答“公司报销流程是什么”光靠提示词写进去是不现实的得接入RAG。这里的标准链路是文档上传 - 文本切片 - 向量化 - 存入向量库 - 用户提问时检索TopK - 拼进提示词。我做RAG时被教育了两次值得说一下切片大小不能一刀切。制度文档适合按章节切技术手册适合按标题代码块切500字固定切片效果通常一般。检索结果必须标注来源。多文档之间有冲突时Agent如果选错了信息源后果很严重。把来源文档名和段落编号一起传给模型能让它在引用时更谨慎。4.6 Agent注册中心与统一生命周期管理工厂的最后一块拼图是“注册中心”。每上线一个Agent应该像一个应用服务一样被登记agent: id: after-sale-assistant name: 售后助手 model: deepseek-chat systemPrompt: 你是售后客服负责处理订单和退换货问题 tools: - getOrderDetail - createReturnOrder - queryLogistics knowledgeBaseId: kb_after_sale maxIterations: 5 owner: customer-service-team这个配置应该DB化、平台化管理而不是写死在代码里。新Agent上线 填一张配置表 做好工具权限评审下线 关闭一个开关。这样“造同事”才真正变成流水线操作。5. 常见问题与排查技巧实录这节全是我自己踩过的坑每个都有血有泪但踩完之后能形成平台的反面教材清单。5.1 工具调用失效模型不调用或者乱调用症状用户问“今天天气怎么样”模型完全忽略你注册的getWeather工具直接凭记忆回答。排查思路确认模型是否支持function calling。DeepSeek的deepseek-chat是支持的但有些小模型不支持确认工具描述写得是否具体。查询天气和当用户询问某个城市的天气、气温、风力、是否适合出行时调用此工具参数city为城市名命中率高一个量级确认FunctionCallback有没有绑定到当前ChatClient我经常改了配置却忘了重启服务。另一个常见情况是参数格式不匹配。LLM返回的参数和你的Java入参类型对不上Spring AI会在执行时报JSON parse error。解决办法是把入参结构写得尽量简单用String接后再解析比强类型对象更抗变。5.2 上下文越塞越满Token成本失控这是我最心疼的教训。第一次上线Agent时为了让它“记住”用户说的每一句话我把整个对话历史每次请求都完整发给模型。结果用户聊了20句之后一次请求的输入Token飙到8000多成本直线上升而且模型响应变慢反而会遗忘早期的重要信息。可行的方案滑动窗口只保留最近N轮对话老对话截断历史摘要每过N轮让模型把之前的对话压缩成一段摘要只保留关键信息用户目标、已确认事实、未解决问题长期记忆单独存向量库需要时才检索回来。个人建议从滑动窗口开始够用、简单、不折腾。等使用量上来再考虑摘要和向量记忆。5.3 Agent陷入死循环症状Agent反复调用同一个工具拿着相同的结果规划下一步一跑就是几十轮费用狂飙。原因一般是模型在复杂任务里“绕不出去”或者工具的返回信息不足以让它做出决策。我采用的兜底策略强制最大迭代次数比如5轮超过就停重复动作检测如果最近3次都是同一个工具相同参数主动打断把“已尝试过同样的方法”写进提示词再试一次还不行就放弃设置单任务成本上限执行中累计Token成本超过阈值自动终止返回人工介入。这三条直接落到平台层面根本不给单次任务无限跑的机会。5.4 Agent输出格式不稳定症状你要求“用JSON格式返回”模型有时候给你返回Markdown代码块包裹的JSON有时候给JSON后面还带一句“以上是我的回答”。下游程序一解析就抛异常。靠提示词约束格式不稳定一定要用结构化输出。Spring AI里可以要求模型返回指定类型的对象DeepSeek也有JSON Output模式来强制输出合法JSON。另外提醒一句即使开了JSON模式返回的仍然可能被套在json代码块里解析前先做一次字符串清洗把起止标记去掉。String raw content; raw raw.replaceFirst(^(json|JSON)?\\s*, ); raw raw.replaceFirst(\\s*$, );这个小处理帮我省掉了无数次解析报错。5.5 多Agent之间互相混淆症状售后服务Agent突然回答员工制度问题或者知识Agent被用户绕过去查订单一片混乱。原因多半是路由Agent的判定不严格或者专业Agent的系统提示词边界不清。我的经验是每个专业Agent在系统提示词里必须明确写“你负责处理什么、不负责什么、遇到超出范围的内容怎么回答”。如果主管Agent把任务分错了专业Agent要能拒绝而不是硬答。6. 我对Agent平台落地的一些体会平台跑了大半年最深的感受是Agent平台的工程难点90%不在模型而在模型之外。工具注册、权限校验、任务状态机、Token成本监控、记忆管理这些工作没有AI含量但每一个都能让一个看似聪明的模型变成真正靠谱的同事。第二点体会是不要一上来追求“全自动”。平台前期可以先做“人审环节”兜底比如Agent生成的对外回复关键操作先人工确认再发出去。这不是倒退这是给系统上保险等运行数据积累够了再把人工占比慢慢降下来。我见过太多团队一上来就搞全自动化结果出了一次严重事故整个项目被叫停。第三点从0到1搭建的时候选一个顺手的框架然后专注在业务工具和平台能力上别总想着从底层自研模型编排。当前阶段的竞争不在模型而在于谁把Agent和业务流程、组织权限、知识资产结合得更顺滑。最后分享一个实用小技巧给每个Agent起一个“人设”版本号。提示词和工具配置改了一个字都要在后台留下变更记录。Agent是你造出来的“同事”但它不是一个可以随便口头交代两句就能改明白的人。把每次变更都当成一次发布这是让Agent工厂稳定运转的重要习惯。
企业数字化 ERP 产品动态
相关推荐
AI生产力系统实战:50个知识管理Skill的分层设计与落地方法 从印象笔记到Notion,再从本地文件夹到各类知识库工具,我做个人知识管理快十年了。坦白说,唯一坚持下来的习惯就是往收藏夹里扔东西——文章存了三千多篇,真正回看的不超过三十篇。去年开始把AI引入这个流程,把信息处理… · 2026/9/26 14:02:31
UI专用小模型实战:从数据构造到量化部署的完整方案 1. 从"大模型画UI"到"小模型专精"的转折点过去一年多,我一直在折腾用AI生成界面这件事。最开始和大家一样,拿通用大模型直接对话,让它吐HTML、吐Tailwind、吐React组件。刚开始确实惊艳,但用久了问题就暴露出… · 2026/9/26 14:02:31
基于CLI的本地化LLM代码评审工作流实战 1. 这不是又一个“LLM玩具”,而是一套可落地的代码评审工作流 open-code-review 这个名字听起来像某个开源项目,但其实它代表的是一类正在快速成型的技术实践:用大语言模型(LLM)作为核心能力,嵌入到真实开发… · 2026/9/26 14:35:01
Atlas 300V 24G 推理卡部署 YOLOv5 实战:模型转换与调优指南 如果你身边有人突然丢过来一句“帮我看看 atlas 这个卡能不能跑 yolo”,大概率不是指那家做数据管理平台的公司,也不是某个拿人当数据表操作的 AI,而是华为昇腾生态里的 Atlas 系列推理设备。最近这个词在技术社区的热度明显上来了࿰… · 2026/9/26 14:35:01
Higgsfield实操指南:AI视频生成的可控工作流与参数调优 我最早注意到Higgsfield,是去年底做短视频压力测试的时候。当时项目组临时要求三天内出一支产品宣传demo,传统渲染流程根本来不及,我几乎把所有能跑的AI视频方案都试了一遍。Higgsfield是最后跑通的那个,也是让我第一次觉得“文生… · 2026/9/26 14:35:01
YooAsset资源管理设计哲学:三态模式、Handle与热更新全解析 在Unity项目里,资源管理大概是讨论热度最高、翻车率也最高的模块之一。AssetBundle怎么打、怎么加载、怎么卸载、怎么热更,每个项目都能讲出一段血泪史。YooAsset这个名字近两年在国内团队里越来越常见,很大一个原因是它把“资源管理”从一堆… · 2026/9/26 14:35:01
从0到1搭建AI Agent平台:核心架构、技术选型与工程实践 先给你讲个真实场景:上个月有朋友跑来问我,说团队每天要花两小时整理报表、回客服消息、写日报周报,问我有什么办法。我给他搭了一套 AI Agent 平台,现在他的“团队”里多了几个不用交社保的“同事”——一个盯着数据报表… · 2026/9/26 14:35:01
自建桌面通信型CRM系统:客户管理、多渠道整合与任务提醒实战 1. 项目概述:DeskcommCRM到底要解决什么先聊一个很多团队都绕不开的真实场景:客户在微信上问了一句“你们这个报价还能不能再低点”,负责接待的同事回复完就切去做别的事了,三天后老板问这个客户进展如何,谁都想不起来… · 2026/9/26 14:34:54
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46