跳转至

多 Agent 架构与通信

多 Agent 系统的核心优势与适用场景

🌟 1. 多 Agent 系统相比单 Agent 有哪些核心优势?

单 Agent 就像一个全能但只有一个大脑的工人。多 Agent 则是一个分工明确、各有所长的团队。这个结构差异带来了四个核心优势:

赛博多Agent机器人解析.jpg

  1. 优势一:专业分工,深度优于广度

一个 Agent 的上下文窗口和注意力都是稀缺资源。把所有工具和指令塞给一个模型,它会变得“什么都会、什么都不精”。多 Agent 让每个 Agent 只掌握一个领域的工具和 System Prompt,比如财务分析 Agent 深谙会计准则,法律审查 Agent 专攻合同条款。这种认知负载的降低直接提升了输出的专业性和准确率。

  1. 优势二:并行处理,突破单线程瓶颈

单 Agent 执行复杂任务必须串行:先查数据,再分析,再写报告。多 Agent 可以把无依赖的子任务同时派发出去——竞品分析、用户调研、趋势预测三个 Agent 并行工作,总耗时由最慢的那个决定,而不是三者之和。这在长链路任务中能带来数倍的效率提升。

  1. 优势三:独立记忆与上下文隔离

单 Agent 在多轮工具调用后,上下文窗口会被大量中间结果污染,导致“迷失中间”问题。多 Agent 各自拥有独立的短期记忆,每个 Agent 的上下文只包含自己领域的相关历史,不会被其他子任务的噪音干扰。这对于需要严格逻辑链的推理任务尤为关键。

  1. 优势四:鲁棒性与可维护性

单 Agent 一个模块出错,整个流程崩溃。多 Agent 可以实现“某个 Worker 挂了,Orchestrator 换另一个备选”的容错机制。同时,各 Agent 可以独立迭代、独立部署,修改竞品分析 Agent 的 prompt 不会影响用户调研 Agent 的稳定性,降低了系统的耦合度和变更风险。


⚖️ 2. 什么情况下该用多 Agent,什么情况下反而不该用?

用还是不用,核心看一个比值:分工带来的增益 能否覆盖 引入的协调成本。我们可以用一个决策矩阵来判断。

科技风机器人解析图.jpg

你的任务是否满足以下条件?
  ├─ 任务可以自然分解为多个相互独立的子任务?  (是 → +1)
  ├─ 子任务需要不同的专业工具或知识领域?      (是 → +1)
  ├─ 子任务之间存在可并行执行的无依赖环节?     (是 → +1)
  ├─ 单个 Agent 的上下文窗口已经不足以承载全流程?(是 → +1)
  └─ 系统未来需要独立迭代或分配给不同团队维护?   (是 → +1)

总分 ≥ 3? → 用多 Agent,收益大于成本。
总分 1~2? → 单 Agent + 良好设计的工具组合即可,无需引入多 Agent 的调度复杂度。
总分 = 0? → 绝对不要用多 Agent。协调开销(状态传递、错误处理、协议开销)远大于收益。

具体来说,这些场景适合单 Agent:

  • 单一类型的任务:如“帮我总结这篇 PDF”,没有分解的必要。

  • 对延迟敏感:多 Agent 通信、序列化、网络往返会增加秒级延迟,实时对话场景可能不适用。

  • 工具集有限:如果所有操作都围绕同一个数据库和一组 API,一个精心设计的 Agent 足够覆盖。

  • 团队规模小、维护成本敏感:多 Agent 意味着多套 prompt、多个部署单元、更复杂的监控,小团队容易被拖垮。

这些场景必须上多 Agent:

  • 企业级复杂工作流:如“入职流程”,涉及 HR 系统、IT 权限开通、财务报税,需要不同领域的专业 Agent。

  • 需要异构能力的组合:一个 Agent 擅长逻辑推理,另一个擅长创意写作,第三个专门做代码生成,Orchestrator 根据子任务类型动态路由。

  • 高可用性要求:关键任务不能单点故障,需要 Agent 冗余和故障转移。

一个反例: 你的需求是“根据用户输入的描述,搜索产品库并返回价格”,这个任务明确、步骤少,用单 Agent + Function Calling 就很好。如果你硬拆成“意图识别 Agent + 搜索 Agent + 格式化 Agent”,不仅增加延迟,还引入序列化开销,完全是过度设计。


🏗️ 3. 一个市场分析任务同时需要分析竞品、用户、趋势,你会怎么设计 Agent 架构?

这个需求天然适合多 Agent:三个分析维度相互独立,各自需要不同的数据源和专业知识。我采用 Orchestrator + Worker 模式,结合 MCP 和 A2A 协议思想,实现一个松耦合、可扩展的架构。

架构蓝图:

image.png

各 Agent 的具体设计:

  • 竞品分析 Agent
  • System Prompt:你是一位竞争情报分析师,擅长识别竞品的功能优劣势、定价策略和市场定位。
  • 工具:web_scraper(抓取官网)、product_db_query(查询产品参数)、pricing_api(获取定价信息)。
  • 输出:结构化 JSON,包含竞品对比矩阵和 SWOT 要点。

  • 用户洞察 Agent

  • System Prompt:你是用户研究专家,能从海量用户反馈中提炼出痛点、需求和满意度。
  • 工具:survey_api(调研数据)、review_scraper(电商/社媒评论)、sentiment_analyzer(情感分析)。
  • 输出:用户画像摘要、核心需求列表、满意度评分。

  • 趋势分析 Agent

  • System Prompt:你是行业趋势分析师,擅长从专利、论文、投融资事件中捕捉技术走向和市场机会。
  • 工具:patent_search(专利检索)、news_api(行业新闻)、report_db(券商研报)。
  • 输出:关键技术趋势、市场规模预测、风险因素。

  • Orchestrator Agent

  • 负责解析用户指令,判断需要启动哪几个 Worker,设定并行/串行顺序(这里三个分析 Agent 完全独立,可以并行)。它同时也处理异常:如果竞品分析 Agent 返回“数据不足”,它可以指示该 Agent 缩小范围或使用备份数据源。
  • 所有 Worker 完成后,激活 Reporter Agent 汇总。

示例代码:用 Python asyncio 模拟编排

import asyncio, json

class MarketAnalysisOrchestrator:
    def __init__(self, agents):
        self.agents = agents  # {"competitor": agent_obj, ...}

    async def run(self, topic):
        # 并行派发三个独立分析任务
        tasks = [
            self.agents["competitor"].analyze(topic),
            self.agents["user_insight"].analyze(topic),
            self.agents["trend"].analyze(topic)
        ]
        # 并行执行,return_exceptions=True 防止某一个失败阻塞全部
        competitor, user_insight, trend = await asyncio.gather(*tasks, return_exceptions=True)

        # 结果后处理:异常降级
        results = {"competitor": self._safe_result(competitor),
                   "user_insight": self._safe_result(user_insight),
                   "trend": self._safe_result(trend)}

        # 启动汇总 Agent,整合三份分析
        report = await self.agents["reporter"].synthesize(results)
        return report

    def _safe_result(self, result):
        if isinstance(result, Exception):
            return {"error": str(result), "partial_data": None}
        return result

通信机制选择: 如果这三个 Worker 是同一进程内的对象,直接调用即可。如果是分布式部署,可以让 Orchestrator 通过 HTTP + JSON 异步调用各个 Worker 的 /analyze 端点,遵循类似 A2A 的 Task 模型:提交任务 → 返回 task_id → 轮询或 Webhook 获取结果。这样架构上更具扩展性。

关键设计考量:

  • 数据流与依赖:三个分析任务互不依赖,所以并行。如果趋势分析需要先知道竞品名单,那么趋势 Agent 就必须等竞品 Agent 完成后再启动,这时就是串行+并行的混合 DAG 编排。

  • 去重与冲突解决:汇总 Agent 不能简单拼接三份报告。它要识别出“用户洞察说价格是痛点,竞品分析显示头部竞品在降价”这种交叉信号,提炼出有战略意义的洞察。这需要汇总 Agent 的 System Prompt 里明确其“综合分析”的职责。

  • 容错与弹性:如果趋势分析 Agent 超时(比如第三方研报 API 挂了),汇总 Agent 应能基于竞品和用户洞察给出“有限但仍有价值”的报告,而不是整体失败。

最终效果:

用户只需要输入“分析智能手表市场”,数分钟内就能得到一份涵盖竞争格局、用户需求、技术趋势的结构化报告,且每个板块都有专业 depth,而非单 Agent 那种“大而全但浅”的泛泛之谈。这种架构可以轻松复用到任何多维度分析场景:比如“新产品可行性评估”、“企业数字化转型方案”等。


Supervisor 模式 vs Peer-to-Peer 模式的架构对比

🧬 1. 什么是 Supervisor 模式和 Peer-to-Peer 模式?

这两种模式的核心区别在于控制流的集中程度:谁来决定下一步做什么?是有一个总指挥,还是大家地位平等、互相商量?

Supervisor 模式(监督者模式)

image.png

  • 决策权:完全集中在上方的 Supervisor。它理解全局目标,将复杂任务拆解为子任务,根据各个 Worker 的能力进行分派,并监控执行结果。Worker 之间不直接通信,所有信息和结果都回流到 Supervisor。

  • 角色:Supervisor 是“大脑”,Workers 是“手脚”。典型的星型拓扑。

Peer-to-Peer 模式(对等模式/去中心化模式)

image.png

  • 决策权:分散在各个 Agent 之间。没有固定的全局指挥官。每个 Agent 拥有自己独立的视角和局部目标,当它认为需要其他 Agent 的信息或能力时,可以主动发起对话、传递任务或请求协助。

  • 角色:所有 Agent 地位平等,是一个“团队协作”模式。可以是全连接拓扑,也可以是基于某种共识机制的动态链接。

最直观的类比:

  • Supervisor 模式:交响乐团,指挥(Supervisor)统一控制节奏、声部进出,乐手(Worker)只看指挥,互相之间不需要交流。

  • Peer-to-Peer 模式:爵士乐队即兴演奏,乐手们互相听、互相给信号,谁都可以发起一段新的旋律,没有固定的指挥。


⚖️ 2. Supervisor 模式和 Peer-to-Peer 模式各有什么优缺点?生产中如何选型?

Supervisor 模式的优缺点:

优点 缺点
可控性强:执行路径完全由你设计的 Supervisor 逻辑(状态图或 LLM 路由)决定,易于调试和理解。 单点瓶颈:Supervisor 成为性能和可靠性的集中瓶颈。它挂了,全系统停止。
简单高效:Worker 之间无需复杂的发现和协商协议,架构清晰,开发成本低。 灵活性受限:当任务需要 Worker 之间大量互动时(如共同创作),Supervisor 的串行分派效率低下。
易于监控和干预:所有任务流经 Supervisor,你可以在一个节点上记录所有状态、做人工审批。 Supervisor 上下文爆炸:所有 Worker 的结果都回流到 Supervisor,其上下文窗口很快会超限,需要压缩策略。

Peer-to-Peer 模式的优缺点:

优点 缺点
鲁棒性高:没有单点故障。一个 Agent 离线,其他 Agent 可以尝试寻找替代路径或动态重组。 协调复杂:需要设计复杂的通信协议(消息路由、冲突解决、共识机制),开发成本高。
灵活、涌现能力强:Agent 之间自发、多向的交互可能产生 Supervisor 模式下无法预见的创新解。 行为难预测:系统整体行为是多个 Agent 交互的涌现结果,调试、审计、复现问题极其困难。
去中心化扩展:新 Agent 加入只需遵循通信协议,不必修改中心节点,理论上扩展性更好。 消息风暴与死锁风险:无节制的对等通信会消耗大量 token,且容易出现循环依赖导致死锁。

生产环境选型决策树:

你的任务是否具备这些特征?
  ├─ 任务的步骤、依赖关系清晰,可以事先规划?
  │    └─ 是 → Supervisor 模式。用 DAG 定义流程,稳定可控。
  ├─ 需要严格遵循合规流程、每一步都可审计?
  │    └─ 是 → Supervisor 模式。集中控制 = 天然审计点。
  ├─ 对延迟敏感,希望尽可能并行处理?
  │    └─ 是 → 优先 Supervisor,它可以轻易调度并行 Worker。
  ├─ 任务高度动态、需要 Agent 之间频繁交换信息或共同创作?
  │    └─ 是 → 考虑 Peer-to-Peer,但要做好状态管理和冲突解决。
  └─ 团队规模较小、希望快速落地第一个版本?
       └─ 是 → Supervisor 模式。它是上手最快、最易维护的选择。

实战经验法则:

90% 的生产级多 Agent 系统应该从 Supervisor 模式起步。 原因很简单:它为你提供了最清晰的掌控力。先用 Supervisor 跑通业务,在运行中识别出哪些 Worker 之间有极强的实时协作需求后,再把那部分局部重构为 Peer-to-Peer 的“微协作域”,形成一种“联邦式”的混合架构。不要一上来就追求完全去中心化——那往往会导致一个不可调试的黑洞。


🏗️ 3. 用 LangGraph 实现 Supervisor 模式,关键代码怎么写?

LangGraph 的状态图机制天生适合 Supervisor 模式。关键在于:

  • 定义一个包含next_worker的共享状态。

  • Supervisor 节点是一个 LLM 调用,它根据当前状态决定下一个应该执行的 Worker。

  • 用条件边根据next_worker的值动态路由。

架构图(LangGraph 视角):

image.png

关键代码实现:

from typing import TypedDict, Literal, List
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
from langchain_core.messages import HumanMessage, AIMessage

# 1. 定义全局状态
class SupervisorState(TypedDict):
    messages: List[dict]          # 全局对话历史
    next_worker: str              # Supervisor 决策:下一个 Worker 名称
    task: str                     # 初始任务

# 2. 定义各 Worker 节点(示例简化,实际每个都是完整的 LLM 调用)
def analyst_worker(state: SupervisorState):
    # 这里实际会用 LLM + 工具执行分析任务
    result = f"[Analyst] 完成市场分析,发现3个关键趋势"
    state["messages"].append({"role": "assistant", "name": "Analyst", "content": result})
    return state

def writer_worker(state: SupervisorState):
    result = f"[Writer] 根据分析报告,生成初稿..."
    state["messages"].append({"role": "assistant", "name": "Writer", "content": result})
    return state

def reviewer_worker(state: SupervisorState):
    result = f"[Reviewer] 审核完成,通过。"
    state["messages"].append({"role": "assistant", "name": "Reviewer", "content": result})
    return state

# 3. 定义 Supervisor 节点(LLM 决策大脑)
def supervisor(state: SupervisorState):
    # 构造决策 prompt,让 LLM 根据历史消息决定下一步
    system_prompt = """
你是项目 Supervisor。根据当前任务和对话历史,决定下一步应该激活哪个 Worker。
可选 Worker:
- Analyst: 负责分析研究
- Writer: 负责撰写内容
- Reviewer: 负责审核内容
- FINISH: 任务完成,结束

请只输出下一个 Worker 的名字,不要输出其他内容。
"""
    messages = [{"role": "system", "content": system_prompt}] + state["messages"]
    response = llm.invoke(messages)  # 假设 llm 已定义

    next_action = response.content.strip()
    state["next_worker"] = next_action
    return state

# 4. 定义路由函数(条件边)
def route_to_worker(state: SupervisorState) -> str:
    next_worker = state["next_worker"]
    if next_worker == "FINISH":
        return END
    return next_worker

# 5. 构建图
builder = StateGraph(SupervisorState)

# 添加节点
builder.add_node("Supervisor", supervisor)
builder.add_node("Analyst", analyst_worker)
builder.add_node("Writer", writer_worker)
builder.add_node("Reviewer", reviewer_worker)

# 设置入口
builder.set_entry_point("Supervisor")

# 添加条件边:Supervisor 决策后路由到具体 Worker
builder.add_conditional_edges(
    "Supervisor",
    route_to_worker,
    {
        "Analyst": "Analyst",
        "Writer": "Writer",
        "Reviewer": "Reviewer",
        END: END
    }
)

# 添加普通边:每个 Worker 执行完后,无条件返回 Supervisor
for worker_name in ["Analyst", "Writer", "Reviewer"]:
    builder.add_edge(worker_name, "Supervisor")

# 编译(可加 checkpointer 做持久化/人工介入)
app = builder.compile(checkpointer=MemorySaver())

# 6. 运行示例
config = {"configurable": {"thread_id": "1"}}
initial_state = {
    "messages": [{"role": "user", "content": "分析新能源汽车市场并生成报告"}],
    "next_worker": "",
    "task": "分析新能源汽车市场并生成报告"
}
result = app.invoke(initial_state, config)

关键设计解读:

  • 路由归 Supervisor 独有:只有 Supervisor 节点后有条件边,Worker 节点后都是无条件的回到 Supervisor。这严格保证了控制流不失控。

  • 状态透明:SupervisorState 是整个图的全局状态,任何节点都能读写它。这让你可以在任何时候(如人工介入)暂停并检查当前所有信息。

  • 持久化与暂停:通过 checkpointer,你可以序列化整个状态到数据库。这意味着如果 Supervisor 在等待人工审批,系统可以暂停,几小时后从断点完美恢复。

  • 易于扩展:新增一个 Worker 只需 1) 实现它的节点函数,2) 在 Supervisor 的决策 prompt 里加上它的名字和能力描述,3) 在条件边的映射字典里加上它的路由,4) 添加一条它返回 Supervisor 的边。完全不需要改动其他 Worker 的逻辑。

混合扩展:在 Worker 内部使用自己的工具

每个 Worker 节点内可以有自己的工具调用循环。比如 Analyst 内部可以用 ReAct 模式调用数据库和搜索引擎,而 Supervisor 完全不关心这些细节。Supervisor 只看 Analyst 最终输出的摘要。这种分层设计是真正生产可用的架构。


多 Agent 的任务分解与动态分配策略

🧩 1. 静态预规划和动态分配分别是什么?

在多 Agent 系统中,这二者是任务分配策略的两种极端,本质区别在于 “分配决策的时间点”。

静态预规划:执行前,一次性画好整张地图。
动态分配:  执行中,一步一步问路。

静态:Plan → Assign → Execute (不可变)
动态:Sense → Decide → Act → Sense → ... (循环)

① 静态预规划

定义:在 Agent 开始执行之前,由一个 Planner(可以是 LLM,也可以是固定算法)根据任务描述,分解出完整的任务依赖图(DAG),并明确每个子任务由哪个 Agent 负责。执行阶段按图索骥,不再修改分配。

特点:

  • 确定性:执行路径固定,易于审计、调试、复现。

  • 高效:无运行时决策开销,可直接并行化无依赖的子任务。

  • 僵硬:无法应对执行中出现的意外(如某个 Worker 返回异常结果,需要插入新步骤)。

代码示例:静态 DAG 定义与并行执行

import asyncio

# 任务 DAG 定义:每个任务有 id,依赖列表,执行函数
dag = {
    "T1": {"deps": [], "func": agent_a_work},
    "T2": {"deps": [], "func": agent_b_work},
    "T3": {"deps": ["T1", "T2"], "func": agent_c_work},
    "T4": {"deps": ["T3"], "func": agent_d_work},
}

async def execute_dag(dag):
    results = {}
    # 简单的拓扑执行:每次找出所有依赖已满足的任务并行执行
    while len(results) < len(dag):
        ready = [tid for tid, t in dag.items() if tid not in results
                 and all(d in results for d in t["deps"])]
        tasks = [asyncio.create_task(dag[t]["func"](results)) for t in ready]
        completed = await asyncio.gather(*tasks)
        for tid, res in zip(ready, completed):
            results[tid] = res
    return results

这种模式非常适合流程标准化、变化极少的场景,比如金融行业的合规审批流。

② 动态分配

定义:由一个运行时的 Supervisor 或协商机制,在每一步根据“当前全局状态”来决定“下一个激活哪个 Agent”。它没有事先写死的完整计划,而是每一步都重新评估。

特点:

  • 灵活:能处理异常、中间结果不符合预期时及时调整策略(如增加验证步骤、换 Agent)。

  • 强适应性:对开放式、探索型任务效果极好,能走出设计者未预料到的路径。

  • 成本与风险:每步都需要 LLM 决策(烧 Token),且可能陷入循环或做出错误路由。

动态分配的伪代码(Supervisor 循环):

while True:
    next_agent = supervisor_llm(state)   # 根据当前状态,LLM 决定下一步
    if next_agent == "FINISH":
        break
    result = agents[next_agent].run(state)  # 交给该 Agent 执行
    state.update(result)                    # 更新全局状态

这适用于用户意图多变、任务结构不固定的场景,如“帮我深入研究一下这家公司,看值不值得投资”。

搭配使用:实际生产中,通常是“宏观静态,微观动态”。顶层用 DAG 划定大阶段,每个阶段内部再用动态 Supervisor 处理具体执行的不确定性。


📝 2. Supervisor 的路由 Prompt 应该怎么设计?有哪些关键要素?

Supervisor 的路由 Prompt 是动态分配模式的大脑。它需要具备准确理解现状 + 严格遵循输出协议的能力。设计不佳的 Prompt 会导致 Supervisor 乱路由、过早结束或死循环。

一个好的路由 Prompt 包含五个关键要素:

image.png

image.png

## 1. 角色与目标
你是任务调度 Supervisor。你的职责是根据对话历史和当前进度,决定下一步应该激活哪个专家 Agent,或者工作是否已经完成。

## 2. 可调度的 Agent 清单
你可以将任务路由给以下 Agent,请严格选择其中之一:

- **Analyst**:负责数据收集、竞品分析、信息检索。当你需要获取新信息或分析原始数据时选它。
- **Writer**:负责撰写文档、报告、邮件。当已有信息充足,需要生成文本时选它。
- **Reviewer**:负责审核内容、检查事实、提出修改意见。当有草稿需要质量把控时选它。
- **FINISH**:当任务完全达成,可以输出最终结果给用户时选择此项。

## 3. 当前任务进度
用户原始需求:{user_request}
已经完成的步骤和结果:
{completed_steps_summary}
最近一次 Agent 的输出:{last_agent_output}

## 4. 路由逻辑与约束
- 如果缺少必要信息,应优先激活 Analyst。
- 如果已有草稿但未被审核,必须激活 Reviewer。
- 如果 Reviewer 提出修改意见,应激活 Writer 进行修改。
- 只有在 Review 通过且用户需求完全满足时,才选择 FINISH。
- 禁止连续两次激活同一个 Agent,除非有明确的新信息注入。

## 5. 强制输出格式
请只输出下一个要激活的 Agent 名称,不要输出任何其他内容:
Analyst | Writer | Reviewer | FINISH

为什么这样设计?

  1. 角色与目标:设定了 Supervisor 的思考边界——它是个调度员,不是执行者。

  2. Agent 清单:必须清晰、无歧义。每一项都要有明确的触发条件(“当你需要……时选它”),而不是简单的功能描述。这直接决定了路由准确性。

  3. 当前任务进度:这是 Supervisor 的“眼睛”。不要只喂原始的用户请求,必须包含已完成步骤的压缩摘要和上一步的输出,否则 Supervisor 会丧失对进度的感知。

  4. 路由逻辑与约束:这是硬编码的业务规则,用来纠正 LLM 的常见错误(如过早结束、喜欢重复调用同一个工具)。这些规则是你的“方向盘”。

  5. 强制输出格式:越简洁越好。不要让它输出 JSON 或解释,一个单词的决策最不容易出错。在代码里用 response.content.strip() 直接拿。

迭代优化技巧:

  • 如果发现 Supervisor 频繁过早 FINISH,在约束中加一句“在给出 FINISH 前,请确认 {checklist}”。

  • 如果总在 A 和 B 之间来回震荡,增加“禁止连续激活同一 Agent”的硬约束,或在状态中记录 last_agent,在代码层拦截。

一个好的路由 Prompt,50% 在写 Agent 描述,30% 在制定约束,20% 在维护状态摘要。把这三块做扎实,你就能用最小的 Token 开销换来最稳的路由表现。


⚙️ 3. 一个复杂分析任务有 4 个子任务,其中 T1、T2 无依赖,T3 依赖 T1/T2,T4 依赖 T3,如何调度?

这是一个典型的 DAG 调度场景,任务依赖关系是:

T1 ─┐
     ├──→ T3 ──→ T4
T2 ─┘

最优策略是用静态预规划定义依赖,用动态执行器并行调度。

为什么不用纯 Supervisor 动态路由?

这种依赖关系明确、不会变化的任务,用 Supervisor 动态决策是一种浪费。每一轮让 LLM 判断“现在该跑 T3 了吗”既贵又不稳定。最好的方式是:代码层管理依赖图,LLM 只负责每个节点内部的“做事”。

实现方案:基于 asyncio 的 DAG 执行器

import asyncio
from dataclasses import dataclass, field
from typing import List, Dict, Any, Callable

@dataclass
class Task:
    name: str
    deps: List[str]
    executor: Callable  # 实际执行该任务的函数,内部可以调用 LLM
    args: Dict[str, Any] = field(default_factory=dict)

class DAGExecutor:
    def __init__(self, tasks: List[Task]):
        self.tasks = {t.name: t for t in tasks}
        self.results = {}
        self._validate_dag()

    def _validate_dag(self):
        # 检查所有依赖是否已定义
        for t in self.tasks.values():
            for dep in t.deps:
                if dep not in self.tasks:
                    raise ValueError(f"Task {t.name} 依赖的 {dep} 不存在")

    async def run(self):
        pending = set(self.tasks.keys())
        while pending:
            # 找出所有依赖已满足的任务
            ready = [name for name in pending
                     if all(dep in self.results for dep in self.tasks[name].deps)]
            if not ready:
                # 理论上不会发生,除非有循环依赖或死锁
                raise RuntimeError("调度死锁,无就绪任务")

            # 并行执行所有就绪任务
            tasks_coro = []
            for name in ready:
                task = self.tasks[name]
                # 将前置任务的结果注入参数
                deps_results = {dep: self.results[dep] for dep in task.deps}
                tasks_coro.append(task.executor(deps_results=deps_results, **task.args))

            ready_results = await asyncio.gather(*tasks_coro, return_exceptions=True)

            # 保存结果
            for name, res in zip(ready, ready_results):
                if isinstance(res, Exception):
                    print(f"Task {name} 失败: {res}")
                    # 可以在此决定是重试、降级还是整体失败
                    self.results[name] = None  # 标记失败
                else:
                    self.results[name] = res
                pending.remove(name)
        return self.results

# --- 具体任务函数示例 ---
async def execute_T1(deps_results, **kwargs):
    # 实际调用 Analyst Agent
    return await analyst_agent.run("分析竞品A的市场份额")

async def execute_T2(deps_results, **kwargs):
    return await analyst_agent.run("分析竞品B的市场份额")

async def execute_T3(deps_results, **kwargs):
    t1_result = deps_results["T1"]
    t2_result = deps_results["T2"]
    # 将T1/T2结果汇总,交给 Writer Agent
    return await writer_agent.run(f"基于以下数据生成对比分析:\nT1: {t1_result}\nT2: {t2_result}")

async def execute_T4(deps_results, **kwargs):
    t3_result = deps_results["T3"]
    return await reviewer_agent.run(f"审核以下报告:\n{t3_result}")

# --- 构建并运行 ---
dag = [
    Task(name="T1", deps=[], executor=execute_T1),
    Task(name="T2", deps=[], executor=execute_T2),
    Task(name="T3", deps=["T1", "T2"], executor=execute_T3),
    Task(name="T4", deps=["T3"], executor=execute_T4),
]

executor = DAGExecutor(dag)
final_results = asyncio.run(executor.run())

这段代码如何体现最优调度?

  • 最大化并行:T1T2 在第一轮循环中同时被 asyncio.gather 并行执行。如果每个耗时 10 秒,总等待只有 10 秒,而不是 20 秒。

  • 自动依赖管理:T3 只有等到 T1T2 都完成(它们的 key 都在 self.results 中)才会被加入 ready 队列。这完全由代码保证,不需要 LLM 参与。

  • 异常隔离:如果 T1 失败,self.results["T1"] 被设为 NoneT3 依然会被执行(因为它只检查依赖的 key 是否存在)。你可以在 execute_T3 内部检测输入是否为 None 来决定是降级输出还是跳过。

如果其中一步需要动态决策怎么办? 假设 T3 执行完后,发现数据冲突,需要额外增加一个 T3.5(重新核实)才能继续 T4。这时 DAG 是静态的,无法自动插入新节点。解决方案是:在 DAGExecutor 中增加一个动态回调钩子。当任务完成时,允许该任务的执行器返回一个“指令”,比如 INSERT_TASK,然后 DAG 执行器动态修改任务图后再继续调度。

这种“核心静态 + 钩子动态”的混合策略,是生产环境中最实用的模式:在可预见的范围内享受确定性的高效,在不可预见的地方为灵活性开一个口子。


6.2 结果处理与质量优化

多 Agent 的结果聚合:投票、加权、LLM 综合


1、基础题:多 Agent 系统中常见的结果聚合方式有哪些?

难度级别:⭐⭐(结果聚合策略、多数投票、LLM 综合)

常见的结果聚合策略有三种:多数投票(让多个 Agent 独立给出答案,取出现次数最多的)、加权聚合(根据每个 Agent 的历史表现或模型能力动态分配权重)、LLM 综合(用一个聚合 Agent 读取所有子 Agent 的输出,综合生成最终答案)。三种方式在准确性、成本、延迟上的权衡差异很大,需要根据任务类型选择。


2、进阶题:多数投票、加权聚合、LLM 综合各自适用什么场景?Mixture of Agents 的思路是什么?

难度级别:⭐⭐⭐(聚合策略适用边界、MoA 架构、成本与质量权衡)

1️⃣ Common Answer

多数投票就是取最多的答案,适合有对错的问题。加权就是不同 Agent 权重不一样。LLM 综合是用一个 LLM 来汇总,适合生成文本。Mixture of Agents 就是多个模型先给答案,再用一个模型来综合,效果会更好。

2️⃣ Impressive Answer

我会从三种策略的适用边界和 MoA 的系统化思路来分析:

  1. 多数投票适合答案空间有限的任务。比如分类、是/否判断、数学推理等有确定性答案的场景。Self-Consistency 就是这个思路的典型应用——同一问题让 LLM 推理多次,投票过滤偶发错误。但对于开放式生成任务,多个答案语义等价但形式各异,简单投票根本无法工作。

  2. LLM 综合最灵活但成本最高。能处理矛盾输出、给出有理有据的综合判断,但会额外增加一次 LLM 调用,且输入 Token 随子 Agent 数量线性增长,成本要仔细评估。

  3. MoA 是 LLM 综合的系统化版本。来自 Together AI 的研究,分两层:Proposer 层用多个不同 LLM(GPT-4、Claude、Llama)并行生成多样化候选答案,Aggregator 层用强模型综合输出。核心洞见是不同模型有不同偏差,输出具有多样性,综合后能互补,实验表明 MoA 在多个 Benchmark 上能超越单个最强模型。工程上 Proposer 层可以并行化以优化延迟,但总成本仍然较高,要评估 ROI。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 描述三种方法是什么 深入分析每种方法的适用条件、局限性和成本影响
实践经验 无具体工程取舍 点出 Token 随子 Agent 线性增长、MoA 延迟优化等实际问题
思考维度 把三种方法并列对比 梳理方法演进逻辑,引入 MoA 研究成果
给面试官的印象 知道有这三种方法 理解背后的设计权衡,了解前沿研究,有成本意识

3、场景题:同一问题让 3 个 Agent 给出了不同的分析结论,如何做聚合?

难度级别:⭐⭐(聚合策略选择、矛盾输出处理)

1️⃣ Common Answer

可以用投票的方式,选出两个 Agent 都同意的答案,或者直接让一个更强的模型来做最终判断。

2️⃣ Impressive Answer

3 个 Agent 给出不同结论,说明任务是开放式分析类,不能用简单多数投票(答案形式各异,没有"多数"可言)。正确做法是 LLM 综合:把三个 Agent 的输出都传给 Aggregator Agent,让它理解各方论点、识别分歧点、综合给出有依据的最终结论。

Aggregator 的 Prompt 设计很关键:要求它显式指出各 Agent 的共识部分和分歧部分,并说明最终结论采纳哪方观点及原因。这样输出不只是"综合结果",还有可追踪的推理链路,便于后续审核。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 提到投票或用强模型判断,无进一步分析 解释为何开放式任务不适合投票,LLM 综合更合适
实践经验 无 Aggregator Prompt 设计思考 提出 Aggregator Prompt 需要显式处理分歧、保留推理链路
思考维度 选一种方法 先分析任务类型,再选择适合的聚合策略
给面试官的印象 有基本思路 有聚合策略的工程设计经验

4、容易一起考的题

关联题 和本题的关系
Self-Consistency 是什么?和多数投票有什么关系? Self-Consistency 是多数投票在 LLM 推理场景下的具体应用
如何评估多 Agent 系统的输出质量? 结果聚合之后需要有质量评估手段,两个问题紧密关联
MoA 和 Ensemble 方法有什么关系? MoA 是机器学习 Ensemble 思想在 LLM 多 Agent 场景下的延伸

多 Agent 通信的消息格式设计

1、基础题:Agent 之间通信的消息格式应该包含哪些基本字段?

难度级别:⭐⭐(结构化消息设计、链路追踪、task_id 的作用)

一个生产可用的 Agent 消息结构至少应包含:task_id(贯穿整个任务生命周期,用于追踪完整链路)、message_id(消息唯一标识)、sender/receiver(发送方/接收方 Agent 名称)、content(结构化消息内容)、message_type(request/response/error/status)、timestamp(用于排序和超时检测)。其中 task_id 是最关键的字段——所有相关 Agent 调用都携带同一个 task_id,才能在监控系统中把散落各处的调用聚合成一条完整链路。


2、进阶题:LangGraph SharedState 共享内存模式和消息队列解耦模式各有什么优劣?如何选型?

难度级别:⭐⭐(LangGraph SharedState、消息队列、架构选型)

1️⃣ Common Answer

LangGraph 用一个共享的 State 对象来传递信息,所有 Agent 都可以读写。消息队列是把消息发到队列里,其他 Agent 从队列取,可以解耦。两种方式都可以用,看具体情况选择。

2️⃣ Impressive Answer

我会从两种模式的核心机制和适用边界来分析:

  1. LangGraph SharedState 模式:所有 Agent 节点共享同一个 State 对象,每个节点读取 State、执行逻辑、返回增量更新,通过 reducer 合并。优势是简单直接、内置持久化(checkpointer)、天然支持 human-in-the-loop。但有两个工程限制:所有 Agent 都能读到全部数据,无法做权限隔离;State 对象随任务进行持续膨胀,可能触发 Token 超限问题。

  2. 消息队列解耦模式:适合 Agent 跨服务、跨进程通信的场景,用 Redis Stream 或 Kafka 作为消息总线,Agent 订阅自己的 topic。优势是松耦合、独立扩缩容、消息持久化支持断点续处理;代价是引入外部依赖、运维复杂度上升、调试时需要跨多个系统查日志。

  3. 选型建议:单进程、任务流程固定的多 Agent 用 LangGraph SharedState;跨服务、需要高可用、Agent 独立部署的场景用消息队列。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 描述两种方式是什么 深入分析 SharedState 的权限问题和 Token 膨胀风险
实践经验 知道两种方式存在 给出具体的工程局限和对应解决思路
思考维度 描述"是什么" 给出"什么场景选什么"的具体决策标准
给面试官的印象 了解基本概念 有消息系统设计经验,考虑到权限、追踪、运维等多个维度

3、场景题:多 Agent 系统上线后,发现某个任务链路出错但很难定位是哪个 Agent 出了问题,怎么解决?

难度级别:⭐⭐(链路追踪、task_id 设计、可观测性)

1️⃣ Common Answer

可以在每个 Agent 里面加日志,出错的时候打印出来,然后去查日志就能找到是哪里出了问题。

2️⃣ Impressive Answer

这是多 Agent 系统可观测性的核心问题,根本原因是消息设计时没有统一的追踪 ID。解决方案分两层:

第一层是消息设计层面,强制每条 Agent 消息携带 task_idparent_message_id,形成完整的消息追踪树。所有 Agent 的日志都带上 task_id,这样在日志系统里只需过滤 task_id 就能聚合出一条任务的完整执行链路。

第二层是工具层面,接入 LangSmith 或 OpenTelemetry,自动采集每个 Agent 节点的输入输出、耗时、Token 用量,在 UI 上直接可视化完整的调用链路,定位问题从"查日志"变成"看 Trace 图"。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 只想到加日志 从消息设计和工具接入两个层面系统解决
实践经验 无具体追踪设计 提出 task_id + parent_message_id 的消息追踪树设计
思考维度 事后排查 事前设计可观测性基础设施,从根本上解决问题
给面试官的印象 有基本调试思路 有多 Agent 系统可观测性的工程经验

4、容易一起考的题

关联题 和本题的关系
LangSmith 是什么?在多 Agent 系统中如何使用? LangSmith 是 LangGraph 系统的官方可观测性工具,与消息追踪紧密关联
OpenTelemetry 如何接入 AI Agent 系统? 消息队列模式下跨服务追踪的标准解决方案
多 Agent 系统如何做权限隔离? SharedState 模式的核心局限之一,延伸考察安全设计

多 Agent 系统的成本控制:防止 LLM 调用爆炸

1、基础题:多 Agent 系统为什么比单 Agent 更容易出现成本失控?

难度级别:⭐(成本构成理解、Token 计费原理)

多 Agent 系统每个 Agent 调用都独立消耗 Token,成本是单 Agent 的 N 倍起步。如果 Agent 之间形成循环调用或无限重试,Token 消耗会指数级增长。没有预算上限的系统,一个复杂任务可能烧掉几十美元。


2、进阶题:多 Agent 系统的 LLM 调用成本如何控制?有哪些防止调用次数爆炸的有效机制?

难度级别:⭐⭐⭐(Agent 调用轮次上限、上下文复用、早停机制、模型分级)

1️⃣ Common Answer

每个 Agent 都要消耗 Token,所以要控制成本。可以设置最大调用次数,防止死循环。对不变的内容做缓存。结果差不多了就提前停。另外可以用便宜的模型,不是每个 Agent 都要用最强的。

2️⃣ Impressive Answer

我会从调用次数、Token 量、模型选择、监控告警四个维度来回答这个问题:

  1. 调用轮次上限。LangGraph 通过 recursion_limit 设置硬上限,但仅靠这个不够——还需要在 Supervisor 的路由 Prompt 里加规则:同一个 Agent 连续调用超过 3 次仍无进展,就返回当前最优结果,防止无效循环。

  2. 早停机制。不等跑完所有轮次就提前结束。判断信号有三类:置信度达阈值(Supervisor 评判"已足够好")、任务完成信号(Agent 返回 {"status": "complete"})、结果收敛(连续两轮输出相似度 > 0.95)。

  3. 上下文复用。这是最容易被忽视但效果显著的点。子 Agent 不应每次独立做 RAG 检索,应该复用父 Agent 已检索的上下文。对不变的系统规则、API 文档,用 OpenAI Prompt Caching 或 Anthropic Cache Control 缓存 System Prompt,可以节省 50-90% 的 Token 成本。

  4. 模型分级。简单路由和格式转换用 GPT-4o-mini / Claude Haiku;核心推理和代码生成用 GPT-4o / Claude Sonnet;复杂分析和最终综合用 o1 / Claude Opus。在生产中还需设置每次任务的 Token 预算上限,超出时自动降级或停止执行。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 说了三个方向,无实现细节 给出每个机制的具体触发条件和实现思路
实践经验 未提上下文复用这一关键优化 明确指出子 Agent 重复检索是常见浪费点并给出方案
思考维度 只考虑了调用次数和模型选择 从次数、Token 量、模型选择、监控告警四个维度系统性覆盖
给面试官的印象 知道有成本问题 有生产级成本控制经验,考虑周全

3、场景题:生产环境中一个多 Agent 任务突然 Token 消耗飙升,如何快速定位并止损?

难度级别:⭐⭐⭐(成本监控、告警机制、预算守卫)

1️⃣ Common Answer

可以去日志里看一下哪个 Agent 调用次数多,然后降低调用频率。或者换个便宜的模型。如果还是太贵就直接停掉任务。

2️⃣ Impressive Answer

定位和止损需要分两个层次应对:

实时止损:在每次 LLM 调用后更新累计消耗,设置预算守卫(CostGuard),一旦超出阈值立即抛出异常中断任务,防止继续烧钱。同时配置告警(接飞书或 PagerDuty)让人工第一时间感知。

事后定位:通过 LangSmith 或自建 Trace 系统,按 Trace ID 聚合每次任务的各 Agent Token 消耗明细,对比历史基线找出异常 Agent。常见原因是某个 Agent 陷入了重试循环,或上下文窗口被无关内容撑大,定位后针对性修复(加早停、清理上下文)。

class CostGuard:
    def __init__(self, budget_usd: float):
        self.budget = budget_usd
        self.consumed = 0.0

    def check(self, tokens: int, model: str):
        cost = tokens / 1_000_000 * MODEL_PRICE[model]
        self.consumed += cost
        if self.consumed > self.budget:
            raise BudgetExceededError(f"已消耗 ${self.consumed:.2f},超出预算")

3️⃣ Key Differences

维度 Common Answer Impressive Answer
应对策略 被动事后处理 实时止损 + 事后溯因双层应对
工具使用 只提到看日志 明确用 Trace ID 聚合 + LangSmith 定位异常 Agent
思考深度 只知道停或换模型 能分析根因(重试循环、上下文膨胀)并给出修复方向

4、容易一起考的题

关联题 和本题的关系
LangGraph 的 recursion_limit 是什么?如何配置? 防止调用爆炸的基础机制,是成本控制的第一道防线
OpenAI Prompt Caching 的原理和使用条件? 上下文复用的核心实现手段,直接影响 Token 成本
多 Agent 系统的可观测性如何建设? 成本监控依赖完善的 Trace 体系,两者深度绑定

6.3 可观测性、应用与安全

多 Agent 的可观测性:跨 Agent 调用链追踪


1、基础题:什么是 Trace ID?在多 Agent 系统中为什么必须有统一的 Trace ID?

难度级别:⭐(可观测性基础概念、分布式追踪原理)

Trace ID 是一次任务从开始到结束的唯一标识,所有 Agent 调用都携带同一个 Trace ID,形成完整的调用链。多 Agent 系统一次任务可能触发十几次 LLM 调用分散在不同 Agent,没有统一 Trace ID 就无法把它们关联起来,出了问题根本没法定位。


2、进阶题:多 Agent 系统的可观测性如何建设?如何实现跨 Agent 的调用链追踪和 Token 消耗汇总?LangSmith 在其中扮演什么角色?

难度级别:⭐⭐⭐(统一 Trace ID 传播、LangSmith 父子 Trace 结构、跨 Agent Token 消耗汇总)

1️⃣ Common Answer

多 Agent 的调用链很复杂,要给每个任务生成一个唯一 ID,所有 Agent 调用时都带上这个 ID,这样就能在日志里找到同一个任务的所有调用。LangSmith 是 LangChain 的可观测性工具,能记录 LLM 的输入输出和 Token 消耗。

2️⃣ Impressive Answer

我会从 Trace ID 传播、LangSmith 父子结构、Token 汇总三个层次来回答:

  1. Trace ID 的正确传播方式。Trace ID 必须在任务入口统一生成,通过 Python 的 ContextVar 在异步环境中安全透传,不能让每个 Agent 自己生成——否则就失去了关联能力。每个子调用生成自己的 Span ID 并记录父 Span ID,整体形成树状结构。

  2. LangSmith 的父子 Trace 结构。给函数加 @traceable 装饰器,LangSmith 会自动识别调用栈中的嵌套关系,构建父子 Trace 树。在 UI 上可以直接看到完整调用链、每个节点的输入输出、耗时和 Token 消耗,调试效率远高于翻日志。

  3. 跨 Agent Token 消耗汇总。通过 LangSmith Client 的 list_runs API,按 Trace ID 聚合所有 run 的 usage_metadata,可以得到每个 Agent 的分项消耗和全局总量,用于成本分析和异常告警。生产中还需要把指标推送到 Prometheus + Grafana,并对失败 Trace 做 100% 采样、成功 Trace 做 10% 采样,平衡存储成本和调试需求。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 知道需要 Trace ID 和 LangSmith 详细说明 ContextVar 传播机制和父子 Trace 树状结构
实践经验 无具体实现 给出 LangSmith API 聚合 Token 的完整思路和采样策略
思考维度 只提了追踪 涵盖追踪、汇总、告警、采样策略等完整监控体系
给面试官的印象 了解工具名称 有生产级可观测性建设经验,懂得在成本和完整性间取舍

3、场景题:线上某个多 Agent 任务失败率突然升高,如何用可观测性手段快速定位问题?

难度级别:⭐⭐⭐(Trace 分析、错误采样、调用链定位)

1️⃣ Common Answer

去看日志,找报错信息。如果有 LangSmith 就去上面看一下哪个 Agent 出错了,然后针对那个 Agent 去排查。

2️⃣ Impressive Answer

利用完善的 Trace 体系,定位分三步走:

首先,通过 Grafana 看板定位失败率上升的时间窗口,对比该窗口内的 Trace 和正常时段的基线——找出失败 Trace 集中在哪个 Agent 节点(Span)。

其次,对失败的 Trace 做 100% 采样,在 LangSmith 里打开具体 Trace,查看每个 Span 的输入输出,重点看异常 Span 的 LLM 输入是否有上下文截断、工具调用参数是否异常、返回的 JSON 是否解析失败。

最后,如果是偶发性问题,检查是否有外部依赖(如检索服务、工具 API)的延迟或错误率同步升高,排除上下游影响,确认问题根因后修复并验证 Trace 恢复正常。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
定位路径 直接看日志,无系统方法 从指标 → Trace → Span 逐层收窄,有方法论
工具运用 只提到 LangSmith 看错误 结合 Grafana 时序分析 + LangSmith Span 输入输出检查
思考广度 只看 Agent 本身 考虑到外部依赖(工具 API、检索服务)的联动影响

4、容易一起考的题

关联题 和本题的关系
Python ContextVar 的原理和使用场景? Trace ID 在异步环境中安全传播的核心机制
LangSmith 的 @traceable 装饰器是如何工作的? 构建父子 Trace 结构的关键工具,直接影响调用链的可视化
多 Agent 系统的成本控制如何实现? Token 消耗汇总是成本控制的前提,两者共享同一套 Trace 基础设施

Debate 模式:多 Agent 辩论提升推理质量


1、基础题:什么是多 Agent 的 Debate 模式?它的核心思想来自哪里?

难度级别:⭐(Debate 模式概念、Society of Mind 理论)

Debate 模式是让多个 Agent 对同一问题独立给出答案,再相互批判对方观点,最后由仲裁者综合所有意见给出最终答案。思想来自 Marvin Minsky 的 Society of Mind 理论——复杂智能从简单个体的竞争与协作中涌现,多个 LLM 作为独立思维者,通过竞争性对话提升集体推理质量。


2、进阶题:Debate 模式是如何提升推理质量的?最终仲裁者应该如何设计?

难度级别:⭐⭐⭐(Society of Mind 思想、独立生成防止羊群效应、仲裁者角色设计)

1️⃣ Common Answer

让多个 Agent 各自回答同一个问题,然后互相批评,最后一个 Agent 综合大家的意见给出最终答案。这样可以发现单个 Agent 的错误和盲点,提升准确性。最终的仲裁者就是汇总意见的那个 Agent。

2️⃣ Impressive Answer

我会从有效性原理、流程关键设计点、仲裁者设计三个角度来回答:

  1. 为什么有效。单个 LLM 生成时容易陷入"自洽的错误"——它会对自己的错误推理产生高置信度。多个独立 Agent 的答案具有多样性,交叉批判能暴露单个 Agent 忽视的反例和漏洞。MIT 等机构的研究证明这在数学推理、常识问答上显著优于单次生成。

  2. 流程关键设计点。Round 1 必须独立生成,绝对不能让 Agent 看到其他 Agent 的答案——否则会产生羊群效应,第一个 Agent 的答案会主导后续所有人,失去多样性,整个 Debate 的价值就归零了。Round 2 开始才进行交叉批判,每个 Agent 读取其他所有 Agent 的答案并发表批评意见,可以并行执行提升效率。

  3. 仲裁者的设计。仲裁者不能简单"取多数票",而是要做论据质量评估——优先支持论证更充分、逻辑更严密的立场,识别并排除明显错误的论点,并说明为什么采纳某方观点(可解释性)。仲裁者是整个流程认知要求最高的环节,必须用能力最强的模型。此外,Debate 的成本是参与 Agent 数量 × 轮次的倍数,不适合简单问题,最适合高风险决策和容易出现幻觉的复杂推理场景。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 描述了流程,未解释为何有效 从 Society of Mind 理论出发解释多样性和竞争带来的质量提升原理
实践经验 无实现细节 强调 Round 1 必须独立生成这一关键设计点,并解释违反后的后果
思考维度 未提适用边界和成本 分析仲裁者设计要点,给出成本-收益的适用边界
给面试官的印象 了解概念 理解论文背景,有工程化落地经验,知道细节陷阱

3、场景题:一个法律合同审查系统想引入 Debate 模式,但预算有限,如何在控制成本的前提下实现?

难度级别:⭐⭐⭐(Debate 成本优化、适用边界、模型分级)

1️⃣ Common Answer

可以少用几个 Agent,比如只用两个 Agent 辩论一轮,不用辩论太多轮。便宜的地方用便宜的模型,最后汇总的时候用好一点的模型。

2️⃣ Impressive Answer

在预算有限的场景下,Debate 模式的成本优化有三个方向:

选择性触发:不是所有合同条款都需要辩论。对风险评分低的标准条款直接用单 Agent 处理,只对高风险条款(如违约责任、排他协议)触发 Debate,减少 70% 以上的无效辩论成本。

模型分级:辩论 Agent 用中等能力模型(如 Claude Sonnet)保证多样性,仲裁者用最强模型(如 Claude Opus)做最终判断。这样在质量和成本之间取得平衡。

轮次控制:法律场景通常一轮批判已经足够暴露主要分歧,不需要像数学推理那样多轮迭代。固定为"1 轮独立生成 + 1 轮交叉批判 + 仲裁"的三步结构,并设置单次任务的 Token 预算上限,超出时降级为单 Agent 处理。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
成本控制策略 只想到减少 Agent 数量和轮次 从选择性触发、模型分级、轮次控制三个维度系统优化
业务理解 没有结合法律场景的特点 识别高/低风险条款的差异,做差异化处理
兜底设计 超出预算时自动降级为单 Agent,保证服务可用性

4、容易一起考的题

关联题 和本题的关系
Society of Mind 理论是什么?对 AI Agent 设计有什么启发? Debate 模式的理论基础,理解原理才能设计好系统
多 Agent 系统的成本控制有哪些手段? Debate 模式成本是普通多 Agent 的倍数,成本控制是必配能力
LangGraph 如何实现并行节点执行? Debate Round 1 独立生成需要并行执行,LangGraph 的 Send API 是关键实现手段

多 Agent 软件开发系统设计(需求/设计/编码/测试)

1、基础题:MetaGPT 模拟软件公司是什么思路?和普通的单 Agent 代码生成有什么本质区别?

难度级别:⭐(MetaGPT 概念、角色化 Agent 设计)

MetaGPT 的思路是把软件公司的角色(PM、架构师、程序员、QA)映射为不同的 Agent,每个 Agent 有明确的职责,输出结构化文档(PRD、架构设计、代码、测试报告),上游的输出是下游的输入,形成类流水线的工作流。和单 Agent 代码生成的本质区别是:职责分离 + 结构化中间产物,每个环节有专门的 Agent 把关,减少单点失败的影响。


2、进阶题:如果用多 Agent 系统来模拟软件开发流程,如何设计各个角色 Agent 的职责划分?人工审查节点应该在哪些关键环节介入?

难度级别:⭐⭐⭐(各角色 Agent 职责划分、MetaGPT/AutoGen 实现参考、人工审查节点介入时机)

1️⃣ Common Answer

可以设计产品经理 Agent 理解需求、架构师 Agent 做设计、程序员 Agent 写代码、测试 Agent 写测试用例,按顺序依次执行,前一个的输出是后一个的输入。MetaGPT 就是这个思路。人工可以在需求确认和代码审查环节介入。

2️⃣ Impressive Answer

我会从角色职责划分、工作流设计、人工介入节点三个角度来回答:

  1. 角色职责划分。六个角色各有明确的输入输出:PM Agent(用户需求 → 结构化 PRD)、Architect Agent(PRD → 架构设计文档 + API Schema)、Developer Agent(架构文档 + 模块分配 → 代码,可按模块并行)、Code Reviewer Agent(代码 → Review 意见,检查规范和安全)、QA Agent(代码 + PRD → 测试报告,基于验收标准生成用例)、DevOps Agent(代码 + 架构文档 → 部署配置)。

  2. 人工审查节点。有四个必须介入的关键节点——需求确认(PRD 完成后,AI 对需求的理解可能有偏差,是整个开发的起点,理解错了后面全错,成本最高);架构评审(架构决策影响深远,技术债往往源于此);代码合并前(不用每行都看,但对安全和核心业务逻辑做抽样审查);上线审批(最后的门控)。人工介入太多失去自动化价值,太少风险不可控,四个关键节点是经验上的合理平衡点。

  3. LangGraph 实现 Human-in-the-Loop。用 interrupt_before 在指定节点前自动暂停,配合 MemorySaver 做状态持久化,人工审查期间任务挂起。审查完成后调用 update_state 写入反馈,再用 invoke(None, thread_id) 从断点继续,整个流程对任务透明。关于框架选型,MetaGPT 更像"刚性流水线",输出格式有严格约束,适合流程标准化场景;AutoGen 更像"动态协商",灵活但难预测。生产中我倾向于 MetaGPT 的思路——强制结构化输出,减少因格式混乱导致的链路中断。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 列举角色,描述串行流程 给出完整工作流图,分析哪些环节可并行,以及 interrupt_before 的具体用法
实践经验 人工节点只笼统提了一下 明确给出 4 个必须介入的关键节点,并解释每个节点介入的风险理由
思考维度 未对比 MetaGPT 和 AutoGen 对比两种框架设计哲学,给出选型建议
给面试官的印象 知道有这个应用方向 有系统设计能力,能权衡自动化和人工把关的边界

3、场景题:多 Agent 软件开发系统上线后,代码质量仍然不稳定,如何改进?

难度级别:⭐⭐⭐(质量保证机制、反馈循环、Agent 能力边界)

1️⃣ Common Answer

可以让测试 Agent 多写几个测试用例,或者再加一个 Agent 专门做代码审查。如果代码质量不行就让程序员 Agent 重新生成。

2️⃣ Impressive Answer

代码质量不稳定通常有三个根因,对应三个改进方向:

结构化输出约束:如果 Developer Agent 的输出格式不一致(如有时输出 Markdown 有时是纯文本),下游 Code Reviewer 解析失败就会跳过审查。解决方案是强制 Developer Agent 输出符合预定义 Schema 的结构化格式,任何不合规的输出在进入下游前就被拦截并要求重生成。

反馈循环设计:Code Reviewer → Developer 的修复循环需要设置退出条件,否则会无限循环。建议设置最大修复轮次(如 3 轮),超出后人工介入判断是 Agent 能力边界还是需求本身有歧义。

质量基准测试:定期用标准化的测试用例集评估各 Agent 的输出质量,监控 QA Agent 的测试通过率趋势。一旦通过率下滑,及时排查是上游 Architect Agent 的设计文档质量下降还是 LLM 版本更新导致输出风格变化。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
问题诊断 直接加 Agent 或重新生成,未分析根因 识别三类根因并对应三个改进方向
反馈机制 只提到重新生成,无退出条件 明确修复循环的退出条件和人工介入触发点
系统思维 局部修补 从结构化约束、循环设计、质量监控三层系统改进

4、容易一起考的题

关联题 和本题的关系
LangGraph 的 interrupt_before 和 Human-in-the-Loop 如何实现? 人工审查节点的核心实现机制,是软件开发系统中质量把关的关键
MetaGPT 和 AutoGen 的设计哲学有什么区别? 两种框架代表不同的多 Agent 协作范式,直接影响软件开发系统的架构选型
多 Agent 系统如何控制 LLM 调用成本? 软件开发系统角色多、链路长,成本控制是绕不开的工程问题

多 Agent 的安全边界:防止 Agent 间数据越权


1、基础题:什么是最小权限原则?在多 Agent 系统中如何理解它?

难度级别:⭐(最小权限原则概念、Agent 工具白名单)

最小权限原则是指每个 Agent 只能访问完成其任务所必需的工具和数据,不能多给。在多 Agent 系统中,不同 Agent 的职责不同,不能给所有 Agent 一个通用工具包,而应该为每个 Agent 配置工具白名单。一个专门做格式转换的 Agent 不应该有数据库读写权限,哪怕它从不主动使用。


2、进阶题:多 Agent 系统中如何防止 Agent 间的数据越权访问?工具权限隔离和敏感数据保护应该如何设计?

难度级别:⭐⭐⭐(Agent 权限隔离设计、工具访问白名单、敏感数据不传递给不可信 Agent、输出内容安全过滤)

1️⃣ Common Answer

可以给每个 Agent 设置工具白名单,只让它用被授权的工具。对于敏感数据,在传递前做脱敏处理,比如把手机号、身份证号替换掉。不同 Agent 应该按最小权限原则配置。

2️⃣ Impressive Answer

我会用"防御纵深"框架来组织这个问题,从外到内分四层设防:

  1. 权限控制层(最外层)。用集中式工具注册中心管理所有 Agent 的工具权限,通过 grant_tools 为每个 Agent 显式授权,get_tools_for_agent 在运行时动态返回该 Agent 的合法工具列表。任何不在白名单内的工具调用直接拒绝,不给任何 Agent 通用工具包。

  2. 数据脱敏层(传递层)。对数据做三级分类:L0 公开数据可以传给任何 Agent;L1 内部数据只给受信 Agent;L2 敏感数据(PII、API Key、密码)只在专属 Agent 内部处理,绝不作为消息内容传递。消息传递前经过 DataSanitizer 自动正则脱敏。关键原则是 Sensitive by Design——在架构层阻止敏感数据流动,而不是靠运行时过滤兜底。

  3. 工具调用层(工具层)。能执行代码、写文件、发网络请求的工具是最大风险点。安全工具执行器需要做两道检查:先验证 Agent 是否有该工具的执行权限,再做静态代码分析拦截危险导入(如 ossubprocess)。最终在沙箱(RestrictedPython 或 Docker 容器)中执行,防止注入攻击。

  4. 输出过滤层(输出层)。Agent 输出在传递给用户或下游 Agent 前,要做 Prompt Injection 检测——恶意网页内容被检索后可能含有"ignore previous instructions"等注入指令,影响后续 Agent 行为,需要提前拦截。任何一层失效都有其他层兜底,这是防御纵深的核心价值。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 说了白名单和脱敏,无实现细节 给出工具注册中心、数据分级、静态代码分析等具体实现方案
实践经验 未考虑 Prompt Injection 等攻击面 提出 Prompt Injection 防护、第三方 Agent 沙箱隔离等高级威胁模型
思考维度 平面式列举几个措施 用"防御纵深"框架组织,形成层次化的安全体系
给面试官的印象 有基本安全意识 有系统性安全设计思维,考虑到攻击链路的每个环节

3、场景题:系统引入了第三方插件 Agent,如何防止它访问内部数据和工具?

难度级别:⭐⭐⭐(第三方 Agent 隔离、沙箱设计、API 网关审计)

1️⃣ Common Answer

可以不给第三方 Agent 访问内部数据库的权限,只给它公开的接口。对它的行为做一些日志记录,方便事后审计。

2️⃣ Impressive Answer

第三方 Agent 是多 Agent 系统中最高风险的接入点,需要从三个层次做隔离:

运行环境隔离:第三方 Agent 必须在独立的沙箱(Docker 容器或专用进程)中运行,不能和内部 Agent 共享进程空间和内存,防止通过内存读取或文件系统访问绕过权限控制。

访问路径隔离:第三方 Agent 不能直接调用内部工具,所有交互都必须通过受控的 API 网关进行。网关做身份认证(JWT)+ 权限校验(只开放公开接口)+ 请求参数校验(防止 SQL 注入、路径穿越),并对所有请求做 100% 日志记录。

数据传递控制:传递给第三方 Agent 的数据在出境前必须经过最严格的脱敏处理(L2 数据绝对不出境),返回数据在入境前经过 OutputGuard 做 Prompt Injection 检测,防止恶意插件通过输出内容影响内部 Agent 行为。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
隔离深度 只做权限控制,未考虑运行环境 从运行环境、访问路径、数据传递三层做纵深隔离
攻击面认知 只考虑正向访问控制 考虑到内存读取、文件系统访问、Prompt Injection 等多种攻击手段
审计能力 只提到日志记录 明确通过 API 网关做 100% 请求审计,具备事后溯源能力

4、容易一起考的题

关联题 和本题的关系
Prompt Injection 攻击是什么?如何防御? Agent 输出过滤的核心威胁模型,是多 Agent 安全中独有的攻击面
多 Agent 系统的可观测性如何建设? 安全审计依赖完善的 Trace 和日志体系,两者共用同一套基础设施
Docker 容器沙箱和 RestrictedPython 各自的适用场景? 工具层和第三方 Agent 运行环境隔离的具体实现方案,需要根据场景选型

多 Agent 冲突解决与共识

冲突检测与协商机制

1、进阶题:多个 Agent 对同一问题给出矛盾的答案,系统应该如何处理?⭐⭐⭐

难度级别:⭐⭐⭐(冲突检测、投票机制、仲裁 Agent、置信度评分)

1️⃣ Common Answer

可以搞个投票,少数服从多数。或者找个更高级的 Agent 来仲裁。也可以把矛盾的答案都告诉用户,让用户自己选。

2️⃣ Impressive Answer

冲突处理需要检测、协商、仲裁三步机制:

  1. 冲突检测
  2. 比较多个 Agent 的输出:关键事实不一致、结论互斥、推荐方案冲突
  3. 用 LLM 或规则检测矛盾(如"答案 A 说 X>0,答案 B 说 X<0")
  4. 检测到冲突后,标记冲突点,进入协商流程

  5. 协商机制

  6. 投票机制:多个 Agent 对冲突点投票,少数服从多数(适合 Agent 数量≥3)
  7. 置信度评分:每个 Agent 输出时附带置信度,选置信度最高的(需 Agent 有校准能力)
  8. 辩论轮次:让持不同观点的 Agent 进行 1-2 轮辩论,尝试达成共识

  9. 仲裁机制

  10. 设一个 Arbitrator Agent(通常用更强的模型),接收各方观点和证据,做出最终裁决
  11. 仲裁结果附带理由,便于追溯和审计
  12. 如果仲裁也无法确定,降级为"多选一"让用户决定

3️⃣ Key Differences

维度 Common Answer Impressive Answer
结构性 只说了投票和仲裁,无检测 检测→协商→仲裁三层完整流程
技术深度 不了解置信度评分和辩论机制 覆盖三种协商策略和仲裁理由追溯
实践经验 无冲突检测实现细节 提到用 LLM 或规则检测矛盾
面试官印象 方案简单粗暴 有系统的冲突处理框架

2、场景题:在多 Agent 协作中,如何设计一个"共识机制"来确保最终输出的质量?⭐⭐⭐⭐

1️⃣ Common Answer

可以让多个 Agent 各自生成答案,然后对比一下,选最好的。或者搞个审核 Agent,检查输出质量。

2️⃣ Impressive Answer

共识机制的设计需要分层校验、多维度评分、渐进收敛

  1. 分层校验架构
  2. L1 - 独立生成:3-5 个 Agent 并行生成答案,互不干扰
  3. L2 - 交叉评审:每个 Agent 评审其他 Agent 的答案,指出问题和改进建议
  4. L3 - 融合优化:一个 Fusion Agent 综合所有答案和评审意见,生成最终版本
  5. L4 - 终审:一个高级别 Judge Agent 做最终质量把关,不通过则打回 L1 重新生成

  6. 多维度评分

  7. 准确性(事实核查)、完整性(覆盖所有要点)、一致性(无自相矛盾)、可读性(表达清晰)
  8. 每个维度 1-5 分,设置最低门槛(如准确性≥4 分才能进入终审)

  9. 渐进收敛

  10. 设置最大迭代次数(如 3 次),避免无限循环
  11. 每次迭代后对比与上一版的差异,差异过小说明陷入局部最优,触发终止

3️⃣ Key Differences

维度 Common Answer Impressive Answer
结构性 只有"生成 - 对比"两层 L1 独立→L2 评审→L3 融合→L4 终审四层
技术深度 无评分维度和收敛机制 4 个评分维度 + 迭代终止条件
实践经验 无质量门槛意识 设置最低门槛和最大迭代次数
面试官印象 方案粗糙,质量无保障 有完整的质量保障框架,适合生产环境

多 Agent 安全与权限控制

多 Agent 系统的安全防护

基础题:多 Agent 系统中有哪些常见的安全风险?

⭐⭐ 考察要点:Prompt 注入传播、权限越界、工具滥用、数据泄露

1️⃣ Common Answer

主要有 Prompt 注入,Agent 可能被攻击。权限越界,Agent 可能访问不该访问的东西。工具滥用,Agent 可能用工具做坏事。数据泄露,敏感信息可能被泄露。还有就是 Agent 之间互相欺骗。

2️⃣ Impressive Answer

多 Agent 系统的安全风险可以分为输入层、执行层、协作层、输出层四个维度:

  1. 输入层 - Prompt 注入传播
  2. 直接注入:用户输入恶意 Prompt,让 Agent 执行非预期操作
  3. 间接注入:通过外部数据源(网页、文件、数据库)注入恶意内容
  4. 链式传播:一个 Agent 被注入后,将恶意内容传递给其他 Agent,形成攻击链
  5. 多模态注入:通过图片、音频等多模态数据注入隐藏指令

  6. 执行层 - 权限越界与工具滥用

  7. 权限越界:Agent 访问超出其职责范围的资源(如客服 Agent 访问财务数据)
  8. 工具滥用:Agent 使用工具进行非预期操作(如代码执行 Agent 删除系统文件)
  9. 资源耗尽:恶意 Agent 无限循环调用工具,导致系统资源耗尽
  10. 沙箱逃逸:Agent 通过工具组合突破沙箱限制

  11. 协作层 - 数据泄露与欺骗

  12. 数据泄露:Agent 在协作中泄露敏感信息(如 Agent A 将用户密码传给 Agent B)
  13. 信息欺骗:恶意 Agent 提供虚假信息,误导其他 Agent 做出错误决策
  14. 身份冒充:一个 Agent 冒充另一个 Agent,获取更高权限
  15. 拒绝服务:恶意 Agent 拒绝响应,阻塞整个工作流

  16. 输出层 - 内容安全与隐私

  17. 输出注入:Agent 输出中包含恶意内容,影响用户或其他系统
  18. 隐私泄露:Agent 在输出中无意泄露用户隐私信息
  19. 内容合规:Agent 输出违反法律法规或平台规范的内容

风险等级评估:Prompt 注入传播是最高风险,因为它可以触发其他所有风险。其次是权限越界,因为它可能导致直接的数据泄露或系统破坏。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
结构性 零散列举风险点 输入层、执行层、协作层、输出层四层结构
风险深度 只是"访问不该访问的" 具体到沙箱逃逸、链式传播、身份冒充
风险评估 强调 Prompt 注入是最高风险
面试官印象 基本了解风险,但缺乏系统性 有完整的风险分类和评估框架

进阶题:如何设计 Agent 的权限隔离机制,防止工具滥用?

⭐⭐⭐ 考察要点:最小权限原则、沙箱执行、工具白名单、审批流

1️⃣ Common Answer

给每个 Agent 设置权限,只能用需要的工具。用沙箱隔离,不让 Agent 直接访问系统。用白名单,只允许用指定的工具。重要的操作需要审批,用户同意才能执行。

2️⃣ Impressive Answer

Agent 权限隔离需要最小权限原则、沙箱执行、工具白名单、审批流四层防护:

  1. 最小权限原则
  2. 角色定义:每个 Agent 有明确的角色和职责,只分配完成职责所需的最小权限
  3. 权限矩阵:建立 Agent-工具-操作的权限矩阵,细粒度控制
PERMISSION_MATRIX = {
    "客服Agent": {
        "allowed_tools": ["query_user", "update_order"],
        "allowed_operations": ["read", "update"],
        "data_scope": ["user_id", "order_id"]
    },
    "财务Agent": {
        "allowed_tools": ["refund", "audit"],
        "allowed_operations": ["read", "write", "delete"],
        "data_scope": ["transaction_id", "account_id"]
    }
}
  • 动态授权:根据任务上下文动态调整权限(如客服 Agent 处理退款时临时授予财务权限)

  • 沙箱执行

  • 进程隔离:每个 Agent 在独立的容器或进程中运行,资源隔离
  • 网络隔离:限制 Agent 的网络访问,只允许访问白名单域名
  • 文件系统隔离:Agent 只能访问指定的沙箱目录,无法访问宿主机文件
  • 资源限制:限制 CPU、内存、执行时间,防止资源耗尽攻击

  • 工具白名单与参数校验

  • 工具白名单:每个 Agent 只能调用白名单中的工具
  • 参数校验:在工具执行前校验参数的合法性(如防止 SQL 注入)
  • 敏感操作标记:标记高风险工具(如 delete_fileexecute_code),强制走审批流
  • 工具调用审计:记录所有工具调用日志,包括 Agent、工具、参数、结果

  • 审批流机制

  • 分级审批:根据操作风险等级设置不同的审批流程
    • 低风险(如查询):自动执行
    • 中风险(如更新):需要用户确认
    • 高风险(如删除):需要多人审批
  • 审批超时:设置审批超时时间,超时自动拒绝
  • 审批历史:记录审批决策人、时间、理由,便于追溯

  • 动态权限调整

  • 信任评分:根据 Agent 的历史行为动态调整权限(如频繁违规则降权)
  • 异常检测:监控 Agent 行为,检测异常模式(如突然调用未授权工具)
  • 紧急熔断:检测到攻击行为时,立即撤销所有权限

实践要点:权限隔离是纵深防御,任何一层都不应该单独依赖。建议结合使用:白名单 + 沙箱 + 审批流,形成完整的防护体系。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 只是"设置权限" 权限矩阵、参数校验、信任评分等具体技术
架构设计 四层防护体系,纵深防御思想
代码示例 提供完整的权限矩阵示例
动态性 信任评分、异常检测、紧急熔断
面试官印象 基本思路正确,但缺乏工程细节 有完整的生产级权限隔离方案

高级题:在多 Agent 协作中,如何防止 Prompt 注入的链式传播?

⭐⭐⭐⭐ 考察要点:输入消毒、上下文隔离、信任边界、输出校验

1️⃣ Common Answer

过滤用户的输入,去掉恶意内容。每个 Agent 只能看到需要的信息,不要共享太多。检查 Agent 的输出,如果有问题就阻止。还有就是限制 Agent 之间的通信。

2️⃣ Impressive Answer

防止 Prompt 注入链式传播需要输入消毒、上下文隔离、信任边界、输出校验四层防护:

  1. 输入消毒
  2. 内容过滤:使用 LLM 或规则引擎检测输入中的恶意指令
def sanitize_input(user_input: str) -> str:
    # 检测常见的注入模式
    injection_patterns = [
        r"忽略之前的指令",
        r"作为.*,你需要",
        r"请.*不要.*告诉任何人"
    ]
    for pattern in injection_patterns:
        if re.search(pattern, user_input):
            raise SecurityException("检测到潜在的注入攻击")
    return user_input
  • 输入截断:限制输入长度,防止通过超长输入绕过检测

  • 格式验证:对结构化输入(JSON、XML)进行严格验证

  • 敏感词过滤:过滤掉系统指令、管理员权限等敏感词汇

  • 上下文隔离

  • 最小上下文原则:每个 Agent 只接收完成任务所需的最小上下文
  • 上下文脱敏:在传递给 Agent 之前,对敏感信息进行脱敏(如手机号、身份证号)
  • 上下文签名:对上下文进行数字签名,Agent 验证签名后才执行
  • 上下文审计:记录所有上下文传递,便于事后追溯

  • 信任边界

  • 信任等级划分:将 Agent 划分为不同信任等级(如用户 Agent < 业务 Agent < 管理员 Agent)
  • 边界守卫:在信任边界之间设置守卫 Agent,过滤和校验所有跨边界的消息
class BoundaryGuard:
    def check_message(self, message: Message, source_level: int, target_level: int):
        if source_level > target_level:
            raise SecurityException("低信任 Agent 不能向高信任 Agent 发送指令")
        if self.detect_injection(message.content):
            raise SecurityException("检测到注入攻击")
  • 单向通信:高信任 Agent 向低信任 Agent 传递信息,但不接受低信任 Agent 的指令

  • 隔离执行:不同信任等级的 Agent 在不同的沙箱中运行

  • 输出校验

  • 内容安全检测:使用 LLM 或规则引擎检测 Agent 输出中的恶意内容
  • 指令阻断:检测到 Agent 输出中包含指令性内容时,将其转换为描述性内容
def sanitize_output(agent_output: str) -> str:
    # 将 "请删除文件 X" 转换为 "用户请求删除文件 X"
    if re.match(r"请.*删除", agent_output):
        return f"用户请求:{agent_output}"
    return agent_output
  • 输出截断:限制输出长度,防止通过超长输出绕过检测

  • 输出审计:记录所有 Agent 输出,便于事后分析

  • 链式传播阻断

  • 传播链追踪:为每个消息分配唯一 ID,追踪传播链路
  • 传播深度限制:限制消息在 Agent 之间的传播深度(如最多 3 跳)
  • 传播时间限制:限制消息的有效期,过期自动失效
  • 异常熔断:检测到注入攻击时,立即阻断整个传播链

实践要点:Prompt 注入的链式传播是最高风险,需要多层防护。建议的防御优先级:输入消毒 > 信任边界 > 输出校验 > 上下文隔离。同时,要建立应急响应机制,一旦检测到攻击,立即熔断。

3️⃣ Key Differences

维度 Common Answer Impressive Answer
技术深度 只是"过滤输入" 输入消毒、上下文签名、传播链追踪等具体技术
架构设计 信任等级划分、边界守卫、传播深度限制
代码示例 提供完整的输入消毒、边界守卫示例
防御优先级 明确给出防御优先级和应急响应机制
面试官印象 基本思路正确,但缺乏系统性 有完整的链式传播防护体系

多 Agent 编排模式对比与选型

主流编排框架的对比与技术选型

1、进阶题:LangGraph、CrewAI、AutoGen 三大框架的核心差异是什么?如何选型?⭐⭐⭐

  • 问题类型:对比分析

  • 难度级别:⭐⭐⭐

  • 考察要点:编排模型(状态图 vs 角色任务 vs 对话)、灵活性、学习曲线、适用场景

1️⃣ Common Answer

这三个框架都是做多 Agent 的,但不太一样。LangGraph 是用图的方式编排 Agent,状态可以在节点间传递,比较灵活。CrewAI 是基于角色和任务的,每个 Agent 有自己的角色,然后分配任务。AutoGen 是通过对话的方式,Agent 之间互相聊天来完成任务。选型的话,如果需要复杂的流程控制用 LangGraph,如果是明确的任务分工用 CrewAI,如果是对话式的场景用 AutoGen。

2️⃣ Impressive Answer

三大框架的核心差异在于编排模型适用场景,需要根据需求特性进行选型:

  1. LangGraph:状态图编排模式
  2. 核心模型:基于有向状态图(State Graph),节点是 Agent 或工具,边定义状态转换条件
  3. 状态管理:全局状态在节点间传递和更新,支持复杂的状态流转和条件分支
  4. 灵活性优势:支持循环、条件分支、并行执行等复杂控制流,适合需要精确编排的场景
  5. 适用场景:复杂工作流、需要精确控制执行顺序、状态依赖强的任务(如代码生成、数据分析流水线)
  6. 学习曲线:中等,需要理解状态图概念

  7. CrewAI:角色-任务协作模式

  8. 核心模型:基于角色(Role)和任务(Task)的协作,每个 Agent 扮演特定角色,分配特定任务
  9. 任务驱动:任务有明确的输入、输出、依赖关系,Agent 按任务依赖顺序执行
  10. 团队协作:支持多 Agent 团队协作,可以定义 Manager 协调者角色
  11. 适用场景:分工明确的任务(如内容创作团队:研究员、写手、编辑)、结构化工作流
  12. 学习曲线:较低,概念直观,类似项目管理中的任务分配

  13. AutoGen:对话式协作模式

  14. 核心模型:基于多轮对话的协作,Agent 通过自然语言对话协商和完成任务
  15. 自然交互:Agent 可以互相提问、澄清需求、协商分工,更接近人类协作方式
  16. 动态编排:执行路径由对话动态决定,适合不确定性和探索性强的任务
  17. 适用场景:需要探索和协商的任务(如需求分析、创意头脑风暴)、开放性问题求解
  18. 学习曲线:中等偏上,需要设计对话协议和提示词

  19. 技术选型决策树

  20. 需要精确控制执行流程 → LangGraph
  21. 任务分工明确,结构化工作流 → CrewAI
  22. 需要探索和协商,开放性强 → AutoGen
  23. 团队经验:Python 基础强选 AutoGen/LangGraph,快速上手选 CrewAI
  24. 生态集成:LangChain 生态选 LangGraph,微软生态选 AutoGen

3️⃣ Key Differences

维度 Common Answer Impressive Answer
结构性 简单对比三个框架 每个框架单独分析,最后给出选型决策树
技术深度 描述基本特性 深入编排模型、状态管理、适用场景分析
实践经验 缺乏选型依据 提供决策树和实际场景建议
面试官印象 了解框架差异 具备技术选型能力,有架构设计思维

2、进阶题:Orchestrator(中心化编排)和 Choreography(去中心化协作)两种模式有什么区别?

难度级别:⭐⭐⭐(中心协调者 vs 事件驱动、耦合度、可扩展性、故障传播)

1️⃣ Common Answer

Orchestrator 是中心化的,有一个主 Agent 负责协调其他 Agent,所有决策都由它来做。Choreography 是去中心化的,Agent 之间直接协作,没有中心控制。Orchestrator 比较��易控制,但中心节点可能成为瓶颈。Choreography 比较灵活,但可能难以理解和调试。

2️⃣ Impressive Answer

两种编排模式在控制流、耦合度、可扩展性等方面有本质差异:

  1. 控制流与决策机制
  2. Orchestrator(中心化编排):由中心协调者统一决策,负责任务分解、Agent 选择、执行顺序控制
    • 优势:全局视角优化,容易实现复杂的业务逻辑和约束
    • 劣势:中心节点成为单点,决策逻辑复杂时难以维护
  3. Choreography(去中心化协作):Agent 之间通过事件或消息直接协作,每个 Agent 自主决策

    • 优势:去中心化,单个 Agent 故障不影响整体,系统更健壮
    • 劣势:缺乏全局优化,可能出现死锁或循环依赖
  4. 耦合度与依赖关系

  5. Orchestrator:Agent 与 Orchestrator 强耦合,Agent 之间解耦。新增 Agent 只需在 Orchestrator 中注册
  6. Choreography:Agent 之间可能存在强耦合,依赖事件协议。新增 Agent 需要修改现有 Agent 的事件监听逻辑

  7. 可扩展性与性能

  8. Orchestrator:中心节点可能成为性能瓶颈,适合中小规模系统
  9. Choreography:天然支持横向扩展,每个 Agent 独立部署,适合大规模分布式系统

  10. 可观测性与调试

  11. Orchestrator:执行路径明确,Trace 链路清晰,容易追踪和调试
  12. Choreography:执行路径动态,需要完善的分布式 Trace 和事件日志系统,调试复杂度高

  13. 选型建议

  14. 需要精确控制、全局优化 → Orchestrator(如工作流引擎、审批流程)
  15. 高并发、大规模分布式 → Choreography(如微服务架构、事件驱动系统)

3️⃣ Key Differences

维度 Common Answer Impressive Answer
结构性 简单对比优缺点 五个维度系统分析,最后给出选型建议
技术深度 描述基本概念 深入控制流、耦合度、可扩展性等架构层面
实践经验 缺乏场景分析 结合实际场景给出选型依据
面试官印象 了解两种模式 具备架构设计能力,能从多维度分析

3、场景题:如果让你从零设计一个多 Agent 系统,你会如何做技术选型和架构设计?

⭐⭐⭐⭐

QELkHCMJ.png

1️⃣ Common Answer

从零设计多 Agent 系统的话,首先要把需求搞清楚,看要做什么任务。然后选择框架,如果简单点就用 CrewAI,复杂点就用 LangGraph。通信协议可以用 HTTP 或者消息队列。容错设计很重要,要考虑重试、降级、熔断。可观测性也要做好,日志、监控、Trace 都要有。还要考虑成本,Token 用量要控制。

2️⃣ Impressive Answer

从零设计多 Agent 系统需要系统化的方法论,从需求分析到落地实施全链路设计:

  1. 需求分析与场景拆解
  2. 任务特性分析:确定任务的确定性(探索性 vs 结构化)、并发性(可并行 vs 顺序依赖)、实时性要求
  3. 复杂度评估:评估状态空间大小、Agent 数量、交互复杂度,决定编排模式(Orchestrator vs Choreography)
  4. 非功能需求:明确性能要求(延迟、吞吐量)、可用性目标(SLA)、成本预算、合规要求

  5. 框架选型决策

  6. 精确控制需求 → LangGraph(状态图编排)
  7. 分工明确任务 → CrewAI(角色-任务协作)
  8. 探索性任务 → AutoGen(对话式协作)
  9. 考虑团队技能(Python/Java)、生态集成(LangChain/OpenAI)、可维护性
  10. 简单需求直接用开源,复杂需求可能需要基于开源二次开发或自研核心编排引擎

  11. 分层架构设计

  12. 编排层:负责任务分解、Agent 调度、状态管理
  13. Agent 层:实现具体 Agent 逻辑,封装 LLM 调用
  14. 工具层:提供外部工具接口(API、数据库、文件系统)
  15. 可观测性层:日志、监控、Trace、告警

  16. 通信协议设计

  17. 同步通信:HTTP/gRPC,适合低延迟、强一致性场景
  18. 异步通信:消息队列(Kafka/RabbitMQ),适合高吞吐、解耦场景
  19. 协议标准化:定义统一的 Agent 通信协议(输入输出格式、错误码)

  20. 容错与高可用设计

  21. Agent 级容错:重试策略(指数退避)、超时控制、降级逻辑(规则引擎替代)
  22. 系统级容错:熔断机制、限流保护、多可用区部署
  23. 数据一致性:幂等设计、事务补偿、最终一致性保证

  24. 可观测性体系

  25. Trace 传播:全局 Trace ID,Span 层次化设计
  26. 日志管理:结构化日志(JSON),集中收集(ELK/Loki),敏感信息脱敏
  27. 监控告警:核心指标(延迟、成功率、Token 成本),分级告警,基线对比

  28. 渐进式落地策略

  29. MVP 验证:先实现核心功能,小流量验证,快速迭代
  30. 金丝雀发布:新功能先小流量测试,监控指标正常后全量
  31. 持续优化:基于监控数据和用户反馈,持续优化性能和成本

3️⃣ Key Differences

维度 Common Answer Impressive Answer
结构性 简单罗列步骤 七个阶段系统设计,从需求到落地
技术深度 提到基本概念 深入架构设计、容错机制、成本优化等细节
实践经验 缺乏具体方案 包含分层架构、通信协议、渐进式落地等实战经验
面试官印象 了解设计流程 具备系统架构能力,有完整的落地方法论