ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent团队化改造:从个人外挂到多人可用的异步服务

Agent团队化改造:从个人外挂到多人可用的异步服务 把 Agent 从“个人外挂”升级成“团队服务”会发生什么过去一年不少开发者在自己的电脑上搭起了 AI Agent自动跑代码检查、生成测试用例、整理技术方案。用得好的时候确实有种“开了外挂”的感觉。但问题随之而来——你的 Agent 只是你的 Agent别人用不了也看不到它的生产记录。它像一个私人助理只认你的口音和习惯。但如果把 Agent 从“个人外挂”升级成“团队服务”事情就完全不一样了团队的每个人都能提交任务能看到历史记录能统一管理模型调用成本甚至能对 Agent 的输出质量做复盘。这不是简单的“共享脚本”而是把 Agent 变成了软件开发流程里的一个基础设施。这篇文章想讨论的不是“Agent 多厉害”而是“当你把一个 Agent 从一个 .py 文件改造成一个多人可用的服务时到底需要做哪些技术决策”。我会从架构拆分、状态存储、权限控制、队列化、可观测性这几个维度展开并给出一个可以直接跑通的最小示例。如果你正在经历“个人写提示词很爽团队落地就乱套”的阶段这篇内容会比较适合你。1. 个人 Agent 与团队 Agent 的本质区别很多团队在引入 Agent 时第一步是让每个人自己写 Prompt、自己调模型。这种做法的好处是启动成本低坏处是每个人都在重复造轮子而且质量参差不齐。我个人观察到一个比较普遍的现象个人 Agent 的核心资产是“上下文”而团队 Agent 的核心资产是“共识”。上下文包括对话历史、当前项目的代码结构、个人偏好共识则包括提示词模板、输出标准、评审维度、敏感信息处理规则。这两个东西目标不同技术实现路径也会分开。从开发者的角度看个人 Agent 是客户端应用的思路——它只需要适配一个用户状态可以保存在本地失败后重试也简单。团队 Agent 则是服务端应用的思路——需要考虑并发、排队、超时、审计、限流。这里真正容易踩坑的地方在于很多人直接把个人脚本放到服务器上就以为这是“团队版”了其实差得很远。如果在技术上更精确地描述个人 Agent 和团队 Agent 之间至少有四个关键差异状态是否共享个人 Agent 的状态在本地团队 Agent 的状态需要持久化到数据库或对象存储。输入是否可控个人 Agent 默认信任用户输入团队 Agent 必须对输入做格式校验、敏感信息过滤、白名单控制。输出是否可复盘个人 Agent 的输出看一眼就关了团队 Agent 的输出要留痕方便后续追溯和优化。成本是否可核算个人 Agent 用多少模型 Token 是个人的事团队 Agent 的 Token 消耗必须能被路由追踪。如果只看表面很容易误以为团队 Agent 只是加了登录注册和数据库但真正决定它能否落地的是任务队列和反馈闭环。没有任务队列多人同时发起请求时模型接口会被打爆而且任务一多就分不清是谁的任务没有反馈闭环Agent 的输出质量只能靠人肉判断时间长了大家就不再信任它了。2. 团队级 Agent 的核心概念与适用场景在讲架构之前需要先统一几个概念。2.1 AgentAgent 可以理解为一个“能自己理解目标并能调用工具分步执行的程序”。相比传统的 if-else 脚本它的特点在于可以接收自然语言指令可以拆解任务可以根据中间结果调整后续动作。但 Agent 不是万能魔法它的能力上限取决于模型能力、可用工具和上下文质量。在实际的团队场景中Agent 常见的落地形态包括代码评审助手拉取 MRMerge Request的变更按团队规范给出评审意见。知识库问答服务对接内部文档回答新人提问。自动化测试生成器读取代码仓库生成基础测试用例。运维巡检代理人定时检查日志和指标异常时输出分析报告。这篇文章的示例会用一个“代码评审助手”来演示原因很简单它既能体现 Agent 的推理能力又需要对接真实数据而且团队里对它的需求最普遍。2.2 MCP 与工具调用Agent 要发挥作用通常需要调用外部工具。MCPModel Context Protocol是一个开放协议用来统一大模型与外部工具之间的通信方式。简单一点理解没有 MCP 时Agent 的“手”很有限所有工具都要自己写函数去调有了 MCP工具可以像插件一样被 Agent 发现和加载。不过需要说明的是本文的示例不依赖 MCP 也能跑通因为会直接把“获取变更文件”和“读取文件内容”实现为普通函数。是否引入 MCP 要看你的项目复杂度——如果 Agent 需要连接的内部系统很多MCP 是合适的选择如果只需要两三个函数手动接入反而更直观。2.3 记忆与上下文团队的 Agent 必须有“记忆”能力但这里说的记忆不是指让 AI 记住聊天记录而是指关键决策和任务状态的结构化存储。比如一个代码评审 Agent 需要记住这次评审的是哪个分支、哪个 MR、发现过哪些问题。这些信息如果不存下来每次任务之间没有连续性就很难产生长期价值。一个常见的误解是Agent 的上下文越长越聪明。实际上超过一定长度后模型的注意力会分散输出质量反而下降。团队级 Agent 要做的是“精准召回”根据任务类型从人设提示词、任务上下文、检索到的相关文档三个层面组装上下文而不是把历史聊天记录一股脑塞进去。3. 团队级 Agent 的整体架构设计从个人脚本升级到团队服务首先要改掉“线性执行”的思维。个人脚本是读取输入 - 调用模型 - 输出结果。团队服务则需要变成接收请求 - 校验权限 - 写入队列 - Worker 异步执行 - 回调通知 - 结果持久化 - 支持查询。为什么会变成异步因为大模型接口的响应时间通常以秒甚至分钟为单位如果让 HTTP 请求一直挂着前端会超时用户的体验会很差。更稳定的方式是让请求先返回“任务已受理”用户在结果出来后去查看。团队级 Agent 的最小架构可以拆成五层接入层提供 HTTP 接口或命令行客户端负责接收用户请求。权限层校验“谁可以提交任务”“谁能查看结果”。调度层把任务写入队列Worker 从队列中拉取任务调用模型和工具。存储层保存任务状态、中间日志、最终结果、Token 用量。反馈层把失败任务重新入队或触发告警把高质量结果纳入后续参考。为了让读者能快速产生体感我用一张表格来描述个人 Agent 与团队 Agent 的架构差异维度个人 Agent团队 Agent调用方式终端逐条执行提交任务后异步获取结果状态位置本地内存或本地文件数据库或对象存储权限控制无默认本机可信用户身份校验与任务级授权上下文组装简单拼接按任务类型进行提示词管理和检索异常处理失败后手动重跑自动重试、死信队列、告警通知成本追踪不关心 Token按用户、项目维度统计 Token可观测性不太需要需要日志、指标、链路追踪这张表做出来读者应该能理解团队级 Agent 不是“把一个函数变成 API”它是从使用逻辑到运维逻辑的整体转变。4. 环境准备与前置条件下面开始进入实操环节。本文示例选择 Python FastAPI Redis RQ PostgreSQL 这套组合是因为它在真实团队中比较常见而且结构清晰。如果你所在团队使用 Node.js 或 Go也可以按同样思路迁移。4.1 运行时环境建议准备如下环境Python 3.10 及以上版本本文示例基于 Python 3.10 编写。Redis 6.x 或以上版本用于任务队列。PostgreSQL 12 或以上版本用于保存任务记录。也可以先用 SQLite 做本地 demo。一个可用的模型 API key。本次示例会以 OpenAI 风格的 Chat Completions 接口为例代码里预留了接口地址和模型参数。请注意版本号在这里只是为了给你一个参考方向不同系统、不同云平台上的安装方式会有差异实际操作时以你的环境和项目要求为准。4.2 安装依赖创建一个新的虚拟环境并安装核心依赖python3 -m venv venv source venv/bin/activate pip install fastapi uvicorn rq redis psycopg2-binary pydantic openai这里简单解释一下每个库的用途FastAPI提供 HTTP API。uvicorn运行 FastAPI 应用。rqRedis 队列库负责把任务放入队列并由 Worker 消费。redis连接 Redis。psycopg2-binary让 Python 连接 PostgreSQL。pydantic做请求参数校验。openai调用模型 API 的 SDK。如果你使用其他兼容接口的模型服务可以改 base_url。4.3 准备基础服务要启动 Redis 和 PostgreSQL最简单的本地验证方式是 Dockerdocker run -d --name redis-queue -p 6379:6379 redis:7-alpine docker run -d --name postgres-agent -p 5432:5432 \ -e POSTGRES_USERagent_user \ -e POSTGRES_PASSWORDagent_password \ -e POSTGRES_DBagent_db \ postgres:14-alpine如果你的机器上没有 Docker也可以直接安装 Redis 和 PostgreSQL 的系统包。这里不依赖任何特殊 Docker 网络配置端口保持默认即可。4.4 数据库表结构本文示例使用 PostgreSQL 来保存任务核心表只需要两张一张存任务主信息一张存评审结果明细。CREATE TABLE agent_tasks ( id SERIAL PRIMARY KEY, task_id UUID NOT NULL UNIQUE, creator VARCHAR(64) NOT NULL, task_type VARCHAR(32) NOT NULL, status VARCHAR(16) NOT NULL DEFAULT pending, payload JSONB NOT NULL, result JSONB, error_message TEXT, model_name VARCHAR(64), token_usage INTEGER DEFAULT 0, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE TABLE review_comments ( id SERIAL PRIMARY KEY, task_id UUID NOT NULL, file_path TEXT NOT NULL, line_number INTEGER, severity VARCHAR(8) NOT NULL, comment TEXT NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );为什么要有 task_id 和 creator 字段因为团队服务必须能够回答“这个任务是哪个同事提交的”“它的最终结论是什么”这既是审计需求也是后续反馈闭环的基础数据。5. 核心流程拆解任务从提交到落库要走几步这一节我先拆流程下一节给完整代码。如果代码看得头晕可以按这个流程来对应理解。第一步客户端提交任务。调用方使用 HTTP POST 发送“请评审这个 MR”的请求请求体里包含仓库地址、分支名、MR 编号、评审要点等信息。第二步服务端校验。FastAPI 接口收到请求后先做两件事用当前登录用户信息填充 creator 字段用 Pydantic 校验请求体是否符合规范。如果请求体里包含不支持的字段直接返回 422 错误。第三步写入任务队列。我们把任务 ID 和请求体一起传给 RQ 的 Queue。注意这里不直接调用模型而是立即返回“任务已受理”并给出一个 task_id 给客户端轮询。第四步Worker 执行任务。RQ Worker 从队列里取到任务在 execute_review_task 函数里完成拉取代码变更、组装提示词、调用模型、解析模型输出、把结果写回数据库。第五步结果查询。客户端拿着 task_id 去 GET 接口查询状态如果 status 是 completed就直接返回评审结果如果是 failed返回 error_message。这个流程的关键是“提交与执行分离”。它带来的直接影响是无论团队的请求量是每分钟 1 个还是每分钟 100 个API 都不会被阻塞。你只需要在前端加一个“正在处理中”的轮询状态就能解决体验问题。6. 完整示例与代码实现下面给出一个最小可用的团队代码评审 Agent文件路径和代码都按可落地的方式组织。6.1 配置文件创建config.pyimport os class Config: REDIS_URL os.getenv(REDIS_URL, redis://localhost:6379/0) DATABASE_URL os.getenv(DATABASE_URL, postgresql://agent_user:agent_passwordlocalhost:5432/agent_db) MODEL_API_KEY os.getenv(MODEL_API_KEY, your-api-key) MODEL_BASE_URL os.getenv(MODEL_BASE_URL, https://api.openai.com/v1) MODEL_NAME os.getenv(MODEL_NAME, gpt-4o-mini)实际部署时API Key 必须放在环境变量或密钥管理服务里不能写死在代码中。下面的示例为了演示方便才使用环境变量。6.2 数据库操作模块创建db.pyimport json import psycopg2 from contextlib import contextmanager from config import Config contextmanager def get_connection(): conn psycopg2.connect(Config.DATABASE_URL) try: yield conn finally: conn.close() def create_task(task_id, creator, task_type, payload): with get_connection() as conn: with conn.cursor() as cur: cur.execute( INSERT INTO agent_tasks (task_id, creator, task_type, status, payload) VALUES (%s, %s, %s, pending, %s) , (str(task_id), creator, task_type, json.dumps(payload)) ) conn.commit() def update_task_status(task_id, status, resultNone, error_messageNone, model_nameNone, token_usageNone): with get_connection() as conn: with conn.cursor() as cur: cur.execute( UPDATE agent_tasks SET status %s, result %s, error_message %s, model_name %s, token_usage %s, updated_at NOW() WHERE task_id %s , (status, json.dumps(result) if result else None, error_message, model_name, token_usage, str(task_id)) ) conn.commit() def get_task_by_id(task_id): with get_connection() as conn: with conn.cursor() as cur: cur.execute( SELECT task_id, creator, task_type, status, payload, result, error_message, token_usage, created_at FROM agent_tasks WHERE task_id %s , (str(task_id),) ) row cur.fetchone() if not row: return None return { task_id: row[0], creator: row[1], task_type: row[2], status: row[3], payload: row[4], result: row[5], error_message: row[6], token_usage: row[7], created_at: row[8], }这一段把 Agent 的“状态持久化”落实到了最简单的 CRUD 操作上。这里真正重要的不是 SQL 本身而是我们为自己的任务定义了一个可以被审计的状态机。6.3 Agent 核心执行逻辑创建agent_core.pyimport json import uuid from openai import OpenAI from config import Config from db import create_task, update_task_status client OpenAI( api_keyConfig.MODEL_API_KEY, base_urlConfig.MODEL_BASE_URL, ) SYSTEM_PROMPT 你是一个严谨的代码评审助手。你负责对提交的代码变更进行评审。 请按以下维度输出评审意见 1. 潜在 Bug 或逻辑错误 2. 安全风险 3. 可读性与维护性 4. 性能问题 输出格式为 JSON 数组每个元素包含以下字段 { file_path: 文件名, line_number: 行号 severity: high|medium|low, comment: 问题描述 } 如果代码没有问题返回空数组。 .strip() def collect_changes(payload): 演示用函数实际上应该根据仓库地址和 MR 编号调用代码托管平台 API 例如 GitLab API、GitHub API获取本次变更的文件列表和 diff 内容。 return payload.get(changes, []) def build_user_prompt(changes): return json.dumps(changes, ensure_asciiFalse, indent2) def call_model(messages): resp client.chat.completions.create( modelConfig.MODEL_NAME, messagesmessages, temperature0.2, response_format{type: json_object}, ) content resp.choices[0].message.content token_usage resp.usage.total_tokens if resp.usage else 0 return content, token_usage def execute_review_task(task_id, payload): 这个函数会被 Redis RQ Worker 调用注意它不能直接依赖 FastAPI 的请求对象。 create_task(task_id, payload.get(creator, unknown), code_review, payload) try: changes collect_changes(payload) if not changes: update_task_status(task_id, completed, result[]) return user_prompt build_user_prompt(changes) messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_prompt}, ] content, token_usage call_model(messages) review_result json.loads(content) update_task_status( task_id, completed, resultreview_result, model_nameConfig.MODEL_NAME, token_usagetoken_usage, ) except Exception as e: update_task_status(task_id, failed, error_messagestr(e)) raise e def generate_task_id(): return str(uuid.uuid4())这里容易让新手困惑的点是create_task 为什么是在 Worker 里执行而不是在 API 里执行原因是队列任务可能被重试。如果我们只在 API 里写一次任务记录Worker 执行失败后重入队就没有一条“任务最初提交时间”的准确记录。把 create_task 放在 Worker 执行函数里配合状态机能更真实地还原任务生命周期。6.4 Redis 队列模块创建queue.pyfrom redis import Redis from rq import Queue from config import Config redis_conn Redis.from_url(Config.REDIS_URL) task_queue Queue(agent-tasks, connectionredis_conn)这一步其实只有几行代码但它是“个人脚本”走向“团队服务”的分水岭。没有队列你的 Agent 只能单线程执行一旦多人使用就会出现请求互相阻塞。6.5 FastAPI 接口创建main.pyimport json from fastapi import FastAPI, Header, HTTPException from pydantic import BaseModel, Field from typing import List, Optional from agent_core import generate_task_id, execute_review_task from queue import task_queue from db import get_task_by_id, update_task_status app FastAPI(titleTeam Agent Service) class ReviewRequest(BaseModel): repo: str mr_id: str branch: str main changes: Optional[List[dict]] None review_focus: Optional[str] None class TaskResponse(BaseModel): task_id: str status: str class QueryResponse(BaseModel): task_id: str status: str result: Optional[list] None error_message: Optional[str] None def get_current_user(x_user: Optional[str] Header(defaultNone)): if not x_user: raise HTTPException(status_code401, detailMissing X-User Header) return x_user app.post(/v1/review, response_modelTaskResponse) async def create_review_task( req: ReviewRequest, x_user: Optional[str] Header(defaultNone), ): user get_current_user(x_user) if not req.changes and not req.mr_id: raise HTTPException(status_code422, detailchanges or mr_id must be provided) task_id generate_task_id() payload { creator: user, repo: req.repo, mr_id: req.mr_id, branch: req.branch, changes: req.changes, review_focus: req.review_focus, } job task_queue.enqueue( agent_core.execute_review_task, task_idtask_id, payloadpayload, job_timeout600, result_ttl3600, ) return TaskResponse(task_idtask_id, statusaccepted) app.get(/v1/tasks/{task_id}, response_modelQueryResponse) async def get_task(task_id: str, x_user: Optional[str] Header(defaultNone)): user get_current_user(x_user) task get_task_by_id(task_id) if not task: raise HTTPException(status_code404, detailTask not found) return QueryResponse( task_idtask[task_id], statustask[status], resulttask[result], error_messagetask[error_message], )这一版接口做了两件最关键的事从 Header 里读取当前用户实现最简版身份识别。提交任务后立即返回不阻塞调用方。6.6 启动服务与 Worker开发环境下需要两个终端窗口。终端 A启动 FastAPI 服务uvicorn main:app --host 0.0.0.0 --port 8000终端 B启动 RQ Workerrq worker agent-tasks --url redis://localhost:6379/0如果你想让 Worker 自动从模块中导入函数也可以这样启动rq worker agent-tasks --url redis://localhost:6379/0 --path .7. 运行结果与效果验证启动完成后可以先提交一个最小请求。我们需要准备一个模拟的 changes 数据因为本文示例没有对接真实的 GitLab 或 GitHub API。示例请求curl -X POST http://localhost:8000/v1/review \ -H Content-Type: application/json \ -H X-User: zhangsan \ -d { repo: demo/project, mr_id: 123, branch: feature/agent, changes: [ { file_path: src/login.py, line_number: 42, content: def login(user_input):\n password user_input[password]\n if password 123456:\n return True\n return False } ] }正常情况下响应应该是{ task_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, status: accepted }随后查询任务结果curl -X GET http://localhost:8000/v1/tasks/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ -H X-User: zhangsan如果任务已经完成你会看到 status 是 completedresult 里是一个数组包含模型给出的评审意见。如果模型返回的评审意见格式不是 JSON 数组我们的代码会进入异常分支最终 status 是 failederror_message 会记录解析异常。如何判断整个链路是否成功三个方面Redis 队列里的任务被 Worker 消费后队列长度应该减少。PostgreSQL 的 agent_tasks 表里出现了一条记录status 从 pending 变为 completed。API 查询返回的最终结果符合预期。如果失败第一步看哪里先看 Worker 的标准输出再看数据库里 error_message 字段。大多数问题集中在模型 API Key 无效、模型返回内容不是合法 JSON、数据库字段类型不匹配这三类。8. 常见问题与排查思路团队化改造过程中最容易遇到下面这些问题。它们很多不是 AI 模型本身的问题而是工程化过程中的典型故障。问题现象可能原因排查方式解决方案Worker 不消费任务Redis 地址配置不一致或 Worker 未启动检查 RQ 队列里的任务数量确认 Worker 进程在运行用rq info --url redis://localhost:6379/0查看队列和 Worker 状态任务一直 pendingRQ 的 job_timeout 过短模型响应超时查看 Worker 日志中的超时信息根据模型实际耗时调大 job_timeout模型返回不能解析为 JSON模型理解提示词不到位或者用了不支持 JSON 模式的模型直接在终端手工拼接 messages 调试模型输出调整 system prompt增加 few-shot 示例使用 response_format数据库连接失败数据库地址、用户或密码错误用psql命令行连一下看是否报错修正 DATABASE_URL确保网络可通用户信息无法获取调用方没有传 X-User 请求头查看 FastAPI 的访问日志统一网关层注入用户信息接口层不再读请求头重复评审同一 MR没有做任务去重查询 agent_tasks 中同一 mr_id 是否已有 pending 任务在业务代码里增加唯一键判断或幂等逻辑Token 成本超预期没有按项目或用户维度统计在数据库按 creator 和 model_name 分组查询在接口层增加 Budget 控制设置单用户单日 Token 上限这里单说一个最隐蔽的问题任务重复。个人脚本时代重复运行也没人在意团队服务里一个误点击可能会让模型把同一个 MR 评审三次既浪费 Token又污染历史记录。解决办法是在提交逻辑里增加幂等控制例如使用 mr_id 和 branch 的组合生成业务幂等键若存在进行中的任务就直接复用。9. 从“能跑”到“能用”的最佳实践上面这套代码可以跑通但距离真正生产可用还有距离。下面这几个工程建议是从“个人外挂”走向“团队服务”时最容易给人带来长期收益的部分。9.1 分离提示词和代码很多 Agent 项目早期会把 Prompt 直接写在代码里我用我自己的真实感受来说这会成为一个很大的维护负担。当团队里每个人都想加一句“请用中文回答”时代码会变得难以 review。更好的做法是把 Prompt 独立成模板文件存到数据库或配置中心甚至为不同提示词设计版本号。这样换模型时只需要改模板不需要改代码。9.2 建立评审结果的反馈闭环模型输出的评审意见不一定是正确的。团队服务一定要允许用户对结果进行确认或否决。可以把“用户是否接受这条评审意见”作为一条反馈数据回存到数据库。当积累到一定量级后你就可以分析出模型在哪些文件类型上的意见命中率高在哪些场景下误报多。这比盲目更换模型参数更有针对性。9.3 审计与安全边界团队 Agent 能访问的数据范围比个人 Agent 大得多所以权限控制一定要前置。建议至少做到以下三点每个用户有独立的身份标识任务记录追溯回个人。模型外部调用记录包含输入、输出、Token方便审计。对敏感信息做脱敏处理比如日志中不要把完整 API Key 打出来。安全边界的底线是即使请求被恶意构造也不能让 Agent 去读取你没有授权给它的敏感数据。这需要接入层有清晰的项目级权限映射。9.4 指数退避重试模型接口偶尔会超时或返回 5xx这是客观存在的。在队列任务里建议给模型调用加上指数退避重试比如第一次等 1 秒重试第二次等 2 秒第三次等 4 秒。这个逻辑与业务代码无关但能显著提升任务的完成率。实现时可以用 Tenacity 库也可以在 RQ 的 worker 层做。9.5 为每个任务定义可观测性指标至少记录四个关键指标任务排队耗时、模型调用耗时、Token 消耗、失败率。有了这些指标你才能判断 Agent 服务是变快了还是变慢了是模型本身的问题还是代码逻辑的问题。在初期你可以只在日志里输出这些数据等规模上来后再接到 Prometheus 或 Grafana。10. 从“工具”到“服务”仍有一段路要走把 Agent 从个人外挂升级成团队服务本质上是把一份“只可意会”的个人能力变成一套“可追溯、可评估、可迭代”的团队基础设施。代码只是其中一部分真正的挑战在于如何定义任务的边界、如何管理上下文、如何收集反馈。本文的示例虽然小但它覆盖了团队 Agent 最核心的几个步骤任务提交、队列调度、模型调用、结果持久化、用户身份识别。你可以基于这套骨架继续接入真实的 GitLab、飞书机器人、内部知识库把它扩展成真正对团队有用的服务。如果你所在团队刚好在尝试 Agent 落地我的建议是不要一上来就追求大而全的框架先挑一个重复性最高的场景按本文的思路做一个最小闭环。跑通闭环之后再根据真实使用数据决定下一个迭代放在哪个模块。这样既能控制成本也能持续验证 Agent 的价值。
返回列表