1. 从单体Agent到协作网络:为什么企业AI工作流需要架构升级
1.1 一个Agent打天下的时代正在过去
2024年初的时候,我帮一家做供应链管理的公司搭过一套基于大模型的智能问答系统。当时思路很简单:一个Agent,挂上几个工具函数,接一个向量数据库做RAG,用户问什么它答什么。上线第一周效果确实惊艳,业务部门的人觉得像变魔术一样。但到了第三周,问题开始集中爆发——采购部门问库存预测,Agent给出的回答里混着销售部门的口径;财务那边要的成本分析,它又把采购合同里的条款理解错了。一个Agent试图服务所有场景,结果就是每个场景都做得不够好。
这不是模型能力的问题,而是架构的问题。单体Agent的本质上是一个“全能但全不精”的通用处理器,它的上下文窗口是有限的,工具集是混杂的,系统提示词是试图覆盖所有场景的。当企业业务复杂度上升到一定程度,这种架构必然遇到天花板。
Agentic Collaboration这个概念,说白了就是把一个“什么都干的通才”拆成一组“各管一摊的专才”,再让它们按照一定的协议和流程协同工作。这个思路其实不新鲜,微服务架构在传统软件工程里已经验证了十几年,现在只不过是把服务换成了Agent,把API调用换成了自然语言交互和结构化消息传递。
1.2 企业AI工作流的三个核心痛点
在展开技术架构之前,先把企业场景下最要命的三个问题说清楚,后面所有的架构设计都是围绕解决这三个问题来的。
第一个痛点是上下文污染。一个Agent如果同时处理采购、销售、财务三个领域的信息,它的上下文窗口里会混杂不同领域的术语、规则和数据。大模型在处理这种混合上下文时,注意力机制会被稀释,导致输出质量下降。我实测过一个对比:同一个模型,在单一领域上下文下回答准确率能到92%,混合三个领域后掉到67%。这个差距在业务场景里是致命的。
第二个痛点是工具冲突。企业里不同部门用的系统不一样,采购用ERP,销售用CRM,财务用专门的记账系统。如果把这些工具全部挂给一个Agent,工具描述会非常长,模型在选择工具时容易出错。更麻烦的是,有些工具的操作是互斥的——比如采购系统的“创建订单”和财务系统的“冻结预算”在某些情况下不能同时执行,但单体Agent很难理解这种跨系统的业务约束。
第三个痛点是可观测性差。当一个Agent处理完一个复杂任务后出了问题,你很难定位是哪个环节出了错。是检索到的文档不对?是工具调用参数错了?还是模型推理本身就偏了?单体Agent的日志是一团乱麻,排查起来非常痛苦。
Agentic Collaboration的架构思路,就是通过角色分离、协议标准化和流程编排,把这三个问题系统性地解决掉。
1.3 从单体到协作的演进路径
我梳理了一下自己经手过的项目,企业AI工作流的演进大致可以分成四个阶段:
| 阶段 | 架构形态 | 典型特征 | 适用场景 |
|---|---|---|---|
| 第一阶段 | 单体Agent | 一个模型+若干工具+RAG | 单一场景的问答、简单任务 |
| 第二阶段 | 路由分发 | 一个路由Agent+多个专业Agent | 多部门共用入口,按意图分发 |
| 第三阶段 | 流水线协作 | Agent按预定义流程串行/并行工作 | 有明确步骤的复杂业务流程 |
| 第四阶段 | 动态协作网络 | Agent自主协商、动态组队 | 高度不确定的探索性任务 |
大部分企业目前处在第二阶段向第三阶段过渡的时期。路由分发解决了“找对人”的问题,但还没有解决“怎么配合”的问题。流水线协作开始定义Agent之间的交互协议和状态传递机制,这才是Agentic Collaboration真正落地的地方。
2. 协作架构的核心组件拆解
2.1 角色定义与能力边界划分
做Agentic Collaboration的第一步,不是写代码,而是画一张“角色能力矩阵”。这张矩阵要回答三个问题:每个Agent负责什么领域?它需要哪些工具?它的输出格式是什么?
我通常会用下面这个模板来梳理:
agent_roles: - name: "采购分析Agent" domain: "供应链采购" tools: - "erp_query" # 查询ERP系统 - "contract_parser" # 合同解析 - "price_compare" # 价格比对 input_schema: type: "object" properties: query: { type: "string" } time_range: { type: "string" } output_schema: type: "object" properties: analysis: { type: "string" } data_points: { type: "array" } confidence: { type: "number" } boundaries: - "不处理销售数据" - "不执行预算冻结操作" - "超出采购领域的问题转交路由Agent"这个模板的关键在于boundaries字段。很多团队做多Agent系统时只定义了“能做什么”,没有定义“不能做什么”,结果Agent之间互相越界,协作变成互相干扰。明确边界之后,每个Agent的提示词可以写得更聚焦,工具集可以更精简,输出格式可以更规范。
角色划分的粒度也需要权衡。分得太粗,等于没分;分得太细,Agent数量爆炸,协作开销超过收益。我的经验值是:一个企业AI工作流里,核心Agent数量控制在5到9个之间比较合适。这个数字不是随便说的——它对应的是人类团队的管理跨度理论,一个协调者有效管理的直接协作者数量在5到9之间。Agent协作虽然没有人际沟通那么复杂,但协调开销的规律是类似的。
2.2 通信协议:Agent之间怎么说话
Agent之间怎么传递信息,这是协作架构里最容易出问题的地方。我见过几种常见的做法,各有优劣。
第一种是纯自然语言传递。Agent A把结果用一段话描述出来,Agent B读这段话然后继续处理。这种方式最灵活,但信息损耗最大。我做过一个测试:让采购Agent把“A供应商报价比B供应商低12%,但交期长5天”这个信息用自然语言传给决策Agent,决策Agent能准确提取出两个关键数字的概率只有78%。如果中间经过两轮传递,准确率降到61%。
第二种是结构化消息传递。Agent之间用JSON Schema定义的消息格式通信,每个字段都有明确的类型和含义。这种方式信息损耗小,但灵活性差,新增字段需要改Schema。
第三种是混合模式,也是我目前最推荐的。核心数据用结构化字段传递,补充说明用自然语言放在一个context字段里。这样既保证了关键信息的准确传递,又保留了自然语言的灵活性。
{ "message_id": "msg_20240115_001", "from_agent": "procurement_analyst", "to_agent": "decision_maker", "intent": "supplier_recommendation", "structured_data": { "supplier_a": { "price": 100, "lead_time_days": 15 }, "supplier_b": { "price": 112, "lead_time_days": 10 }, "recommendation": "supplier_a", "confidence": 0.85 }, "context": "A供应商价格优势明显,但交期较长。如果当前库存能覆盖额外5天的需求,建议选A。", "timestamp": "2024-01-15T10:30:00Z" }这个格式里,intent字段很关键。它相当于消息的“主题”,接收方Agent可以根据intent快速判断这条消息是否需要自己处理,以及用哪个处理流程。没有intent的话,接收方每次都要全文理解一遍,效率很低。
2.3 编排引擎:谁来决定下一步谁干活
编排引擎是协作架构的大脑。它决定了一个任务进来之后,先给谁、再给谁、什么时候并行、什么时候串行、什么时候需要人工介入。
目前主流的编排方式有三种:
第一种是硬编码流程。用代码写死每一步调用哪个Agent,什么条件下走哪个分支。这种方式最可控,但灵活性最差,业务一变就要改代码。
第二种是基于规则引擎的编排。把流程规则抽出来放在配置里,用规则引擎来驱动。比硬编码灵活一些,但规则复杂到一定程度后,维护成本也很高。
第三种是基于LLM的动态编排。用一个专门的“编排Agent”来理解任务、决定调用顺序。这种方式最灵活,但可控性最差,而且编排Agent本身也可能出错。
我的建议是分层混合:主干流程用硬编码或规则引擎保证稳定性,分支和异常处理用LLM动态决策保证灵活性。具体来说,80%的常规任务走预定义流程,20%的异常和新型任务交给编排Agent动态处理。
class OrchestrationEngine: def __init__(self, workflow_config, agents, llm_orchestrator): self.workflow = workflow_config # 预定义流程 self.agents = agents # Agent注册表 self.llm_orchestrator = llm_orchestrator # 动态编排器 def execute(self, task): # 先尝试匹配预定义流程 matched_workflow = self.match_workflow(task) if matched_workflow: return self.execute_workflow(matched_workflow, task) # 没有匹配的流程,交给LLM动态编排 return self.llm_orchestrator.plan_and_execute(task, self.agents) def match_workflow(self, task): # 根据任务类型、关键词、历史模式匹配 for wf in self.workflow: if wf.matches(task): return wf return None这个引擎的核心逻辑是“能走老路就走老路,走不通再探索新路”。预定义流程覆盖了大部分常规场景,保证了稳定性和可观测性;LLM动态编排兜底,保证了系统面对新情况时的适应能力。
2.4 共享状态与记忆管理
多个Agent协作时,它们需要共享一些上下文信息。比如采购Agent查到的供应商报价,决策Agent需要知道;决策Agent做出的选择,执行Agent需要知道。这些信息怎么存、怎么取、怎么保证一致性,是协作架构里另一个关键问题。
我通常会把共享状态分成三层:
第一层是任务级状态。跟当前任务直接相关的数据,比如用户输入、中间结果、最终输出。这层状态存在内存里,任务结束就释放。
第二层是会话级状态。跟当前用户会话相关的上下文,比如用户偏好、历史交互记录。这层状态存在会话存储里,会话过期后清理。
第三层是领域级知识。跟业务领域相关的长期知识,比如产品目录、供应商信息、业务规则。这层状态存在向量数据库或知识图谱里,长期保留。
class SharedStateManager: def __init__(self, session_store, vector_store): self.task_state = {} # 任务级 self.session_store = session_store # 会话级 self.vector_store = vector_store # 领域级 def get_context(self, task_id, session_id, query): context = { "task": self.task_state.get(task_id, {}), "session": self.session_store.get(session_id, {}), "domain": self.vector_store.search(query, top_k=5) } return context def update_task_state(self, task_id, key, value): if task_id not in self.task_state: self.task_state[task_id] = {} self.task_state[task_id][key] = value # 记录变更日志,方便排查 self._log_state_change(task_id, key, value)这里有个容易踩的坑:状态更新的一致性。如果Agent A和Agent B同时更新同一个任务状态,可能会互相覆盖。我的做法是给每个状态字段加一个版本号,更新时检查版本号,冲突时走合并逻辑或重新读取。
3. 实操落地:搭建一个企业级协作工作流
3.1 环境准备与技术选型
假设我们要搭建一个供应链场景的协作工作流,涉及采购分析、库存管理、财务审核三个核心环节。先说一下技术选型。
Agent框架方面,我对比过几个主流方案。LangGraph在状态管理和流程编排上比较成熟,适合做复杂的协作流程;AutoGen在多Agent对话方面有优势,但生产环境的稳定性还需要打磨;CrewAI的角色定义比较清晰,适合快速原型。我最终选的是LangGraph,因为它的状态图模型跟协作工作流的思路最匹配。
消息队列用Redis Stream或者RabbitMQ都可以。Redis Stream更轻量,适合中小规模;RabbitMQ的消息可靠性保证更好,适合对消息丢失零容忍的场景。
状态存储分两块:任务级状态用Redis,读写快;领域知识用向量数据库,我常用的是Milvus或者Qdrant,前者生态更成熟,后者部署更简单。
可观测性这块强烈建议从第一天就加上。我用的是OpenTelemetry做链路追踪,每个Agent的输入输出、工具调用、耗时都打点。没有可观测性的多Agent系统,出了问题就是黑盒。
# 依赖安装 pip install langgraph redis pymilvus opentelemetry-api opentelemetry-sdk pip install fastapi uvicorn # API服务3.2 定义Agent角色与工具集
按照前面说的角色能力矩阵,我们先定义三个核心Agent。
采购分析Agent负责查询供应商信息、解析合同、比对价格。它的工具集包括ERP查询接口、合同解析器、价格比对函数。
库存管理Agent负责查询库存水平、计算安全库存、生成补货建议。它的工具集包括库存查询接口、需求预测模型、补货计算函数。
财务审核Agent负责检查预算余额、审核采购金额、生成财务意见。它的工具集包括预算查询接口、审批规则引擎、财务报告生成器。
from langgraph.graph import StateGraph, END from typing import TypedDict, Annotated import operator class WorkflowState(TypedDict): task_id: str user_query: str procurement_result: dict inventory_result: dict finance_result: dict final_decision: str messages: Annotated[list, operator.add] # 采购分析Agent def procurement_agent(state: WorkflowState): query = state["user_query"] # 调用ERP查询 erp_data = erp_query(query) # 解析合同 contracts = contract_parser(erp_data["contract_ids"]) # 价格比对 comparison = price_compare(erp_data["quotes"]) result = { "suppliers": comparison, "contract_terms": contracts, "recommendation": comparison["best_supplier"], "confidence": comparison["confidence"] } return { "procurement_result": result, "messages": [f"采购分析完成,推荐供应商:{result['recommendation']}"] } # 库存管理Agent def inventory_agent(state: WorkflowState): procurement = state["procurement_result"] # 查询当前库存 current_stock = inventory_query(procurement["recommendation"]) # 计算安全库存 safety_stock = calculate_safety_stock(current_stock) # 生成补货建议 replenishment = generate_replenishment_plan(current_stock, safety_stock) result = { "current_stock": current_stock, "safety_stock": safety_stock, "replenishment_plan": replenishment, "can_cover_lead_time": replenishment["days_coverable"] >= procurement["lead_time_days"] } return { "inventory_result": result, "messages": [f"库存分析完成,可覆盖天数:{replenishment['days_coverable']}"] }每个Agent的函数签名统一为(state) -> dict,输入是当前工作流状态,输出是要更新的状态字段。这种统一接口让编排引擎可以灵活地组合Agent。
3.3 编排流程与条件分支
有了Agent定义之后,用LangGraph把它们串起来。核心是定义节点和边,以及条件分支逻辑。
def build_workflow(): workflow = StateGraph(WorkflowState) # 添加节点 workflow.add_node("procurement", procurement_agent) workflow.add_node("inventory", inventory_agent) workflow.add_node("finance", finance_agent) workflow.add_node("decision", decision_agent) # 设置入口 workflow.set_entry_point("procurement") # 采购分析后,并行执行库存和财务检查 workflow.add_edge("procurement", "inventory") workflow.add_edge("procurement", "finance") # 库存和财务都完成后,进入决策节点 workflow.add_edge("inventory", "decision") workflow.add_edge("finance", "decision") # 决策节点根据结果决定是否结束或需要人工介入 workflow.add_conditional_edges( "decision", should_continue, { "end": END, "human_review": "human_review_node" } ) return workflow.compile() def should_continue(state: WorkflowState): decision = state["final_decision"] if decision["confidence"] < 0.7 or decision["amount"] > 100000: return "human_review" return "end"这个流程里,采购分析是串行的第一步,库存和财务检查是并行的,最后汇总到决策节点。决策节点有一个条件分支:如果置信度低于0.7或者金额超过10万,就转人工审核。这个阈值是根据业务风险偏好设定的,不同企业可以根据自己的情况调整。
3.4 消息传递与状态同步的实现
Agent之间的消息传递用Redis Stream实现。每个Agent处理完自己的部分后,把结果写入共享状态,同时发一条消息通知下游Agent。
import redis import json class MessageBus: def __init__(self, redis_url): self.redis = redis.from_url(redis_url) def publish(self, stream_name, message): self.redis.xadd(stream_name, {"data": json.dumps(message)}) def subscribe(self, stream_name, consumer_group, consumer_name): # 创建消费者组 try: self.redis.xgroup_create(stream_name, consumer_group, id="0") except redis.exceptions.ResponseError: pass # 组已存在 while True: messages = self.redis.xreadgroup( consumer_group, consumer_name, {stream_name: ">"}, count=1, block=5000 ) for stream, msgs in messages: for msg_id, data in msgs: yield msg_id, json.loads(data["data"]) self.redis.xack(stream_name, consumer_group, msg_id)状态同步的关键是版本控制。每次更新共享状态时,先读取当前版本号,更新时带上版本号,如果版本号不匹配就重试。
def update_state_with_version(state_manager, task_id, key, value): max_retries = 3 for i in range(max_retries): current = state_manager.get_task_state(task_id) version = current.get("_version", 0) # 乐观锁更新 success = state_manager.compare_and_set( task_id, key, value, expected_version=version ) if success: return True raise Exception(f"状态更新冲突,重试{max_retries}次后仍失败")3.5 可观测性埋点与日志规范
多Agent系统的可观测性比单体系统重要十倍。我的做法是在三个层面埋点:
Agent层面:每个Agent的输入、输出、耗时、工具调用次数。这些数据用来分析单个Agent的性能和瓶颈。
消息层面:每条消息的发送方、接收方、消息类型、处理耗时。这些数据用来分析协作效率。
任务层面:整个任务的端到端耗时、各阶段耗时占比、人工介入次数、最终结果。这些数据用来分析业务流程的健康度。
from opentelemetry import trace tracer = trace.get_tracer(__name__) def traced_agent_call(agent_func, state): with tracer.start_as_current_span(f"agent.{agent_func.__name__}") as span: span.set_attribute("task_id", state["task_id"]) span.set_attribute("agent_name", agent_func.__name__) start_time = time.time() result = agent_func(state) elapsed = time.time() - start_time span.set_attribute("elapsed_seconds", elapsed) span.set_attribute("output_keys", list(result.keys())) return result日志格式统一用JSON,方便后续用ELK或者Loki做聚合分析。每条日志必须包含task_id、agent_name、timestamp、level、message这几个字段。
4. 踩坑实录与排查技巧
4.1 Agent之间互相等待的死锁问题
这是我在实际项目里遇到的第一个大坑。采购Agent等库存Agent的结果,库存Agent等财务Agent的结果,财务Agent又等采购Agent的结果——三个Agent互相等待,整个流程卡死。
排查这个问题的关键是画出Agent依赖图。把每个Agent的输入依赖和输出产出列出来,检查有没有循环依赖。如果有,要么打破循环(把某个依赖改成异步通知),要么引入超时机制。
# 给每个Agent调用加超时 import signal class TimeoutError(Exception): pass def timeout_handler(signum, frame): raise TimeoutError("Agent调用超时") def call_agent_with_timeout(agent_func, state, timeout_seconds=30): signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(timeout_seconds) try: result = agent_func(state) signal.alarm(0) return result except TimeoutError: # 超时后走降级逻辑 return fallback_result(state)超时时间设多少合适?我的经验是根据P99耗时来定。先跑一周收集数据,算出每个Agent的P99耗时,超时时间设为P99的1.5倍。这样既能覆盖绝大多数正常情况,又不会让异常情况拖太久。
4.2 上下文膨胀导致Token超限
多Agent协作时,每个Agent都会往共享上下文里写东西。如果不加控制,上下文会迅速膨胀,最终超过模型的Token限制。
我遇到过最夸张的一次:一个任务跑了20轮Agent交互,共享上下文里堆了15万Token的历史消息,模型直接报错。
解决办法有三个:
第一是上下文压缩。定期把历史消息用LLM总结成简短摘要,只保留关键信息。比如每5轮交互做一次压缩,把5轮的消息压缩成一段200字以内的摘要。
第二是分层上下文。把上下文分成“必须传递”和“可选传递”两层。必须传递的是结构化数据,体积小;可选传递的是自然语言说明,体积大,只在需要时加载。
第三是设置硬上限。给共享上下文设一个Token上限,比如8万Token,超过后自动触发压缩或丢弃最旧的非关键消息。
def compress_context(messages, max_tokens=8000): total_tokens = sum(count_tokens(m) for m in messages) if total_tokens <= max_tokens: return messages # 保留最近的消息 recent = messages[-5:] older = messages[:-5] # 压缩旧消息 summary = llm_summarize(older) return [{"role": "system", "content": f"历史摘要:{summary}"}] + recent4.3 工具调用参数错误的排查思路
Agent调用工具时参数传错,这是最常见的错误类型。排查这类问题,我总结了一个“三步定位法”:
第一步:看工具描述是否清晰。很多时候参数传错是因为工具描述写得模糊。比如一个查询函数叫query_data,参数叫param1,模型根本不知道该怎么传。工具描述要写清楚每个参数的含义、类型、示例值。
第二步:看上下文是否提供了足够信息。如果模型不知道当前日期,它就没法正确传start_date和end_date。确保上下文里包含了工具调用所需的所有信息。
第三步:看是否有参数校验和自动修正。在工具调用层加一层参数校验,类型不对的自动转换,缺失的必填参数自动从上下文里找。
def validate_and_fix_params(tool_name, params, context): schema = get_tool_schema(tool_name) fixed = {} for param_name, param_spec in schema["properties"].items(): if param_name in params: value = params[param_name] # 类型转换 if param_spec["type"] == "integer" and isinstance(value, str): value = int(value) fixed[param_name] = value elif param_name in schema.get("required", []): # 尝试从上下文推断 inferred = infer_from_context(param_name, context) if inferred is not None: fixed[param_name] = inferred else: raise ValueError(f"缺少必填参数:{param_name}") return fixed4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 流程卡死不动 | Agent循环依赖 | 检查依赖图是否有环 | 打破循环或加超时 |
| Token超限报错 | 上下文膨胀 | 统计每轮Token增量 | 上下文压缩+硬上限 |
| 工具调用失败 | 参数错误 | 检查工具描述和上下文 | 参数校验+自动修正 |
| 输出质量下降 | 上下文污染 | 检查共享状态是否混杂 | 隔离领域上下文 |
| 响应时间变长 | 串行环节过多 | 分析各环节耗时 | 并行化可并行的环节 |
| 结果不一致 | 状态更新冲突 | 检查版本号机制 | 乐观锁+重试 |
| Agent越界 | 边界定义不清 | 检查角色能力矩阵 | 明确boundaries字段 |
| 人工介入频繁 | 置信度阈值过高 | 统计置信度分布 | 调整阈值或优化Agent |
4.5 性能优化的几个实操技巧
第一个技巧是预热。Agent的提示词和工具描述在第一次调用时会有编译开销,提前预热可以显著降低首次响应时间。我的做法是在服务启动时跑一遍空任务,把所有Agent都触发一次。
第二个技巧是缓存。有些工具调用结果是可缓存的,比如查询产品目录、获取汇率。给这些工具加缓存层,能减少重复调用,提升响应速度。
第三个技巧是批处理。如果多个Agent需要查询同一个数据源,把查询合并成一次批量查询,比分多次查要快得多。
第四个技巧是异步化。不是所有Agent都需要同步等待结果。比如日志记录、数据上报这些操作,完全可以异步执行,不阻塞主流程。
import asyncio from concurrent.futures import ThreadPoolExecutor async def parallel_agent_calls(agents, state): loop = asyncio.get_event_loop() with ThreadPoolExecutor(max_workers=len(agents)) as executor: tasks = [ loop.run_in_executor(executor, agent, state) for agent in agents ] results = await asyncio.gather(*tasks) return results5. 协作架构的扩展与演进方向
5.1 从固定流程到动态组队
目前大部分企业的协作工作流还是预定义流程为主。业务变化时,需要人工调整流程配置。下一步的演进方向是动态组队:系统根据任务特征,自动选择合适的Agent组合和协作模式。
实现动态组队的关键是建立一个Agent能力注册中心。每个Agent注册自己的领域、工具、输入输出格式、性能指标。当新任务进来时,编排引擎根据任务需求匹配最合适的Agent组合。
class AgentRegistry: def __init__(self): self.agents = {} def register(self, agent_id, capabilities): self.agents[agent_id] = { "capabilities": capabilities, "performance": {"avg_latency": 0, "success_rate": 1.0}, "load": 0 } def find_best_agents(self, task_requirements, top_k=3): candidates = [] for agent_id, info in self.agents.items(): score = self._match_score(task_requirements, info["capabilities"]) score *= info["performance"]["success_rate"] score *= (1 - info["load"] * 0.1) # 负载惩罚 candidates.append((agent_id, score)) candidates.sort(key=lambda x: x[1], reverse=True) return [c[0] for c in candidates[:top_k]]这个方向目前还在探索阶段,主要挑战在于能力匹配的准确性和动态组队的稳定性。能力匹配可以用向量相似度做初步筛选,再用LLM做精细匹配。稳定性则需要通过大量的测试和调优来保证。
5.2 人机协作的边界设计
Agentic Collaboration不只是Agent之间的协作,还包括人与Agent的协作。哪些环节必须人工介入,哪些可以完全自动化,这个边界设计直接影响系统的实用性和安全性。
我的经验是按风险等级划分:
- 低风险操作:查询类、分析类、建议类,完全自动化。
- 中风险操作:创建订单、发送通知、更新记录,自动化但需要事后审核。
- 高风险操作:资金转账、合同签署、数据删除,必须人工确认。
RISK_LEVELS = { "query": "low", "analyze": "low", "recommend": "low", "create_order": "medium", "send_notification": "medium", "update_record": "medium", "transfer_funds": "high", "sign_contract": "high", "delete_data": "high" } def requires_human_approval(action_type, amount=None): risk = RISK_LEVELS.get(action_type, "high") if risk == "high": return True if risk == "medium" and amount and amount > 50000: return True return False人工介入的体验也很重要。不要只给人工审核者一堆原始数据,要把Agent的分析结果、推荐方案、置信度、风险提示都整理好,让人工审核者能快速做决策。
5.3 多模态协作的想象空间
目前大部分协作工作流还是文本为主的。但随着多模态模型的发展,Agent可以处理图像、音频、视频等多种模态的信息,协作的想象空间会大很多。
比如在供应链场景里,质检Agent可以通过图像识别判断货物质量,采购Agent根据质检结果决定是否收货,财务Agent根据收货情况触发付款。整个流程涉及图像、文本、结构化数据多种模态,Agent之间的消息传递也需要支持多模态内容。
class MultiModalMessage: def __init__(self): self.text = None self.images = [] self.audio = None self.structured_data = {} def to_dict(self): return { "text": self.text, "images": [img.to_base64() for img in self.images], "audio": self.audio.to_base64() if self.audio else None, "structured_data": self.structured_data }多模态协作目前还在早期阶段,主要的挑战在于消息体积大、处理成本高、格式标准化程度低。但方向是明确的,值得提前布局。
5.4 协作架构的评估指标体系
最后说一下怎么评估一个协作架构好不好。我通常用下面这几个指标:
| 指标 | 含义 | 目标值 |
|---|---|---|
| 任务完成率 | 成功完成的任务占比 | >95% |
| 端到端延迟 | 从任务发起到完成的耗时 | <30秒 |
| 人工介入率 | 需要人工介入的任务占比 | <10% |
| Agent利用率 | 各Agent的负载均衡程度 | 方差<0.2 |
| 消息传递效率 | 有效消息占总消息的比例 | >80% |
| 状态一致性 | 状态更新冲突的发生率 | <1% |
| 故障恢复时间 | 从故障发生到恢复的耗时 | <5分钟 |
这些指标需要持续监控,定期复盘。我一般会每周看一次趋势,每月做一次深度分析。指标异常时,顺着可观测性数据往下查,通常都能定位到具体原因。
这套协作架构我在几个项目里落地过,最深的体会是:技术架构只是骨架,业务理解才是灵魂。Agent怎么划分、流程怎么编排、边界怎么设定,这些决策都建立在对业务的深刻理解上。脱离业务谈架构,很容易做出一个技术上很漂亮但业务上不好用的系统。所以我的建议是,先花时间把业务流程和痛点摸清楚,再动手设计Agent协作架构,磨刀不误砍柴工。