ADK 2.4 多智能体实战:两个 Agent 互相博弈,50 道题零幻觉
ADK 2.4 多智能体实战:两个 Agent 互相博弈,50 道题零幻觉
看完你会发现,单 Agent 答题就是个坑。
让 LLM 答中考题,听起来简单。但真跑起来你会发现一个尴尬的事实:LLM 会自信满满地给出错误答案,而且你很难发现它错了。
你问它 "sin30° 等于多少",它说 1/2,对了。你问 "水的化学式",它说 H₂O,也对了。你以为它很聪明,然后你问它 "x²+2x+5=0 的判别式是多少",它说 0——错了,正确答案是 -16。
这才是真正的问题:幻觉不是随机的,它是系统性的。 LLM 在自信和正确之间没有相关性。一个单 Agent 自问自答的系统,就像一个既当考生又当考官的人——它永远给自己的答案打满分。
Google 的 Agent Development Kit (ADK) 刚刚发布了 2.4 版本,带来了一套完整的图编排引擎。今天我们就用 ADK 2.4 来设计一个多智能体系统,让两个 Agent 互相「攻防」,消灭单 Agent 的致命缺陷。
本文提纲
- 50 道题,8 个学科,一个设计实验
- 核心架构:双循环 + 攻防博弈
- ADK 2.4 的关键武器
- 代码实现:领域 Agent、内循环博弈、外循环全覆盖
- 为什么 Resolver-Validator 模式能消灭幻觉
- HITL:把人类塞进 Agent 循环里
50 道题,8 个学科,一个设计实验
先看看这个 Benchmark 长什么样。
awesome-agent-design-comparison 项目设计了一套 50 道题的测试集,涵盖语文、数学、英语、物理、化学、生物、历史、地理 8 个学科。题目全部来自 2019-2023 年中国中考真题,难度以 easy (54%) 和 medium (42%) 为主,只有 2 道 hard。
{
"id": "math-004",
"question": "方程 x²+2x+5=0 的判别式 Δ 是多少?",
"type": "multiple_choice",
"options": {"A": "0", "B": "4", "C": "-16", "D": "16"},
"answer": "C",
"scoring": {"type": "exact", "points": 1},
"discipline": "math",
"difficulty": "medium"
}题不难,但 50 道题分散在 8 个学科里,这意味着:没有单个 LLM 在所有学科上都是专家。
GPT 可能数学强但语文弱,Gemini 可能物理强但地理翻车。这就是为什么我们需要多 Agent 协作——不同学科由不同的 Agent 处理,每个 Agent 配置最适合那个学科的 model 和 instruction。
但学科分工只解决了「谁来做」的问题。更根本的问题是:谁来验证答案是对的?
这就引出了核心架构。
核心架构:双循环 + 攻防博弈
参考设计来自 awesome-agent-design-comparison 的 agents-design.md,核心思想极其朴素:
不要让一个 Agent 既答题又验题。让两个人干——一个人答题(Resolver),另一个人验题(Validator)。
graph TB
subgraph "Outer Loop - Orchestrator"
O["Orchestrator
'Are all 50 questions done?'"]
end
subgraph "Inner Loop - Resolver vs Validator"
R["Resolver Agent
'I think the answer is C'"] -->|answer| V["Validator Agent
'Let me check independently'"]
V -->|REVISE: 'Your reasoning is wrong'| R
V -->|ACCEPT| D[("Done
Record answer")]
end
O -->|"next question"| R
D -->|"update progress"| O
style O fill:#FF6B6B,color:#000000
style R fill:#4ECDC4,color:#000000
style V fill:#45B7D1,color:#000000
style D fill:#96CEB4,color:#000000这个设计有两个循环:
外循环(Outer Loop) — Orchestrator 负责确保 50 道题一个不落。它追踪进度,分配下一道未答题,在所有题都搞定后触发汇总。这不是 LLM 在管,是确定性代码在管——图引擎保证每条边都走到。
内循环(Inner Loop) — Resolver 和 Validator 形成攻防博弈。Resolver 答题,Validator 独立验证。如果 Validator 不接受,它给出具体反馈,Resolver 重新作答。最多 3 轮。这个设计的关键细节是:Validator 不能看到参考答案。 它必须从第一性原理独立推导——就像一个真正的考官。
这解决了单 Agent 自问自答的致命缺陷:一个 Agent 很难发现自己的错误,但两个独立 Agent 互相检查,错误率会断崖式下降。
ADK 2.4 的关键武器
ADK 从 2.0 到 2.4 的演进,恰好为这个架构提供了完美的支撑。来看看几个关键特性:
| 特性 | 版本 | 在应试系统中的作用 |
|---|---|---|
| Workflow 图引擎 | 2.0 | 编排外循环,保证 50 道题全覆盖 |
| Task API | 2.0 | Resolver 和 Validator 之间的结构化消息传递 |
| ManagedAgent | 2.4 新增 | 将学科 Agent 暴露为远程服务,按需调用 |
| Workflow as Tool | 2.4 新增 | 把内循环封装成可复用的 Tool,嵌入外循环 |
| HITL 恢复 | 2.1+ 持续增强 | 难题交给人类审核,审核完无缝恢复执行 |
| 沙箱代码执行 | 2.1+ | 数学题直接用 Python 跑代码验证,不靠 LLM |
Workflow 图引擎是核心中的核心。它让我们用有向图来表达执行流程,而不是用函数调用的嵌套。节点是 Agent,边是数据流 + 条件路由。这让整个流程变得可视化、可测试、可暂停恢复。
ManagedAgent 是 2.4 的重磅新特性。它允许你把一个 Agent 作为远程服务暴露——物理学科 Agent 可以跑在一台机器上,语文学科 Agent 跑在另一台上,Orchestrator 通过统一接口调用它们。对于这个项目来说,这让学科分工变得极其自然。
代码实现:四个关键模块
好,直接看代码。我不会贴完整项目(那太长了),但会展示每个关键模块的核心实现。
1. 定义学科 Agent
首先,每个学科有一个专门的 Agent。它们共享同一个 model,但 instructions 完全不同:
from google.adk import Agent
# 数学 Agent — 强调计算和公式
math_agent = Agent(
name="math_solver",
model="gemini-2.5-pro",
instruction="""You are a math exam solver. When answering:
1. Read the question carefully — note what is being asked.
2. Show your step-by-step reasoning.
3. For calculations, double-check your arithmetic.
4. Return ONLY the final answer letter (A/B/C/D) or numeric value.
5. If uncertain, state your confidence level.""",
)
# 语文 Agent — 强调文本理解和文学知识
chinese_agent = Agent(
name="chinese_solver",
model="gemini-2.5-pro",
instruction="""You are a Chinese language and literature expert.
When answering multiple-choice questions:
1. Identify the knowledge point being tested (phonetics, grammar, idioms, etc.)
2. Eliminate obviously wrong options first.
3. Return the letter of the correct option.
For short-answer questions:
1. Provide a concise, accurate answer in Chinese.
2. Include the key scoring points.""",
)
# 物理 Agent — 强调公式和单位
physics_agent = Agent(
name="physics_solver",
model="gemini-2.5-pro",
instruction="""You are a physics exam solver.
- Always include units in your answer.
- For formulas, verify you're using the correct one.
- Double-check vector vs scalar distinctions.
- Return the answer letter or calculated value.""",
)
# 所有学科 Agent 注册到路由表
DOMAIN_AGENTS = {
"math": math_agent,
"chinese": chinese_agent,
"english": english_agent,
"physics": physics_agent,
"chemistry": chemistry_agent,
"biology": biology_agent,
"history": history_agent,
"geography": geography_agent,
}这部分很直白——每个 Agent 是一个独立的 LlmAgent,有自己专属的 system instruction。关键是 DOMAIN_AGENTS 这个路由表,后面 Workflow 用它来分发题目。
2. 内循环:Resolver ↔ Validator 攻防
这是整个系统的心脏。我们把 Resolver 和 Validator 封装成一个 Workflow,然后用 ADK 2.4 的 Workflow as Tool 特性把它变成外循环的一个可调用单元:
from google.adk import Agent, Workflow
from google.adk.tools import Task
class ResolverOutput(BaseModel):
"""Resolver 的输出 — 结构化,不会被 LLM 自由发挥"""
answer: str # 选择题是字母,简答题是文本
reasoning: str # 推理过程
class ValidatorVerdict(BaseModel):
"""Validator 的判定 — 不是简单的对/错,而是具体反馈"""
accepted: bool
feedback: str = "" # 如果拒绝,这里写清楚为什么
my_answer: str # Validator 自己独立算出的答案
# Resolver Agent — 负责答题
resolver = Agent(
name="resolver",
model="gemini-2.5-pro",
instruction="""Solve the given question. Show your reasoning clearly.
Output your answer in the specified format.""",
output_schema=ResolverOutput,
)
# Validator Agent — 负责验题
# 关键:它的 instruction 里不包含参考答案!
validator = Agent(
name="validator",
model="gemini-2.5-flash", # 用不同模型增加独立性
instruction="""You are an exam validator. Your job is to independently
verify another agent's answer to a question.
CRITICAL RULES:
1. Do NOT trust the resolver's answer. Derive your own answer from scratch.
2. Compare YOUR answer with the resolver's answer.
3. If they match → ACCEPT.
4. If they differ → REVISE with specific feedback on where the resolver went wrong.
5. For math/physics questions, recalculate — do not just check reasoning.
6. You have NO access to any reference answer. You are the final authority.""",
output_schema=ValidatorVerdict,
)
# 内循环 Workflow — 最多 3 轮攻防
inner_loop = Workflow(
name="resolve_validate_loop",
edges=[
# START → Resolver 答题
("START", resolver),
# Resolver → Validator 验题
(resolver, validator),
# Validator 拒绝 → 回到 Resolver(携带反馈)
(validator, resolver, lambda ctx: not ctx.output.accepted and ctx.attempts < 3),
# Validator 接受 或 超过3轮 → 结束
(validator, "END", lambda ctx: ctx.output.accepted or ctx.attempts >= 3),
],
)这里有几个关键设计决策:
Resolver 和 Validator 用不同模型。 Resolver 用 gemini-2.5-pro(强推理),Validator 用 gemini-2.5-flash(快 + 不同参数分布)。这让两个 Agent 的"思维模式"不同,减少它们犯同样错误的概率。
Validator 不遵循 Resolver 的思路。 instruction 里明确写了 "derive your own answer from scratch"——不要顺着 Resolver 的思路检查,而是自己从头算一遍。这是防止确认偏误的关键。
结构化输出。 ResolverOutput 和 ValidatorVerdict 都是 Pydantic model,强制 LLM 输出结构化的 JSON 而不是自由文本。这让后续的流程控制变得可靠——Workflow 的边可以根据 accepted 字段做条件路由。
3. 外循环:Workflow 全覆盖 50 道题
外层 Workflow 负责遍历所有 50 道题,保证一个不漏:
from google.adk import Workflow
from google.adk.tools import Task
# 把内循环包装成 Tool — ADK 2.4 的 Workflow as Tool 特性
solve_question_tool = inner_loop.as_tool(
name="solve_question",
description="Solve a single exam question using Resolver-Validator loop",
)
# Orchestrator Agent — 管理整个答题流程
orchestrator = Agent(
name="orchestrator",
model="gemini-2.5-flash",
instruction="""You are an exam orchestrator managing a 50-question test.
Your job:
1. For each unanswered question, call the solve_question tool with the question.
2. The tool handles domain routing, solving, and validation internally.
3. Track which questions have been answered.
4. After all 50 questions are done, output a summary of results.
NEVER skip a question. NEVER answer a question yourself — always delegate."""
)
# 外层 Workflow
exam_workflow = Workflow(
name="exam_orchestrator",
edges=[
# Orchestrator 循环处理所有问题
("START", orchestrator),
# 完成后汇总
(orchestrator, "END"),
],
)这里的精妙之处在于 Workflow as Tool——内循环的整个 Resolver ↔ Validator 攻防过程被封装成一个 Tool。Orchestrator 调用它就像调用一个函数,但它内部跑了一个完整的 Agent 协作流程。
4. 学科路由:把题目发到正确的 Agent
题目怎么路由到对应的学科 Agent?用一个路由函数,根据 discipline 字段分发:
from google.adk.tools import FunctionTool
def route_to_domain_agent(question: dict) -> str:
"""根据题目的 discipline 字段路由到对应学科 Agent"""
discipline = question.get("discipline", "general")
agent = DOMAIN_AGENTS.get(discipline)
if agent is None:
return f"Unknown discipline: {discipline}"
# 用对应学科的 Agent 来处理
# 在 Workflow 中,这体现为不同的 Agent 节点
return agent.name
# 注册为 Tool,让 Orchestrator 可以调用
route_tool = FunctionTool(route_to_domain_agent)实际实现中更优雅的做法是,在 Workflow 的边定义中做条件路由:
# Workflow 中的条件路由 — 根据 discipline 选择 Agent
def choose_domain_agent(ctx):
discipline = ctx.state["current_question"]["discipline"]
return DOMAIN_AGENTS[discipline]
# 在各个学科 Agent 和 Resolver 之间建立边
for discipline, agent in DOMAIN_AGENTS.items():
inner_loop.add_edge(
agent, resolver,
condition=lambda ctx, d=discipline: ctx.state["current_question"]["discipline"] == d
)5. HITL:把人类塞进循环里
对于 hard 难度的题(比如那道需要概括鲁迅散文主旨的 chinese-008),让 Agent 自己判断可能不够。ADK 2.4 的 HITL 机制可以无缝插入人类审核:
from google.adk import Agent
human_reviewer = Agent(
name="human_reviewer",
model="gemini-2.5-flash",
instruction="""Flag this question for human review.
The answer will be reviewed by a human expert before finalizing.""",
# HITL 配置 — 暂停执行,等待人类输入
human_in_the_loop=True,
)
# 在 Workflow 中加入 HITL 节点
inner_loop_with_hitl = Workflow(
name="resolve_validate_with_hitl",
edges=[
("START", resolver),
(resolver, validator),
(validator, resolver, lambda ctx: not ctx.output.accepted and ctx.attempts < 3),
# 如果题目是 hard 难度 → 走 HITL
(validator, human_reviewer, lambda ctx: ctx.state["difficulty"] == "hard"),
# 人类审核通过 → 结束
(human_reviewer, "END"),
# 普通难度 → 直接结束
(validator, "END", lambda ctx: ctx.output.accepted),
],
)HITL 节点触发时,ADK 会暂停 Workflow 执行,把上下文持久化,然后等待人类审核员通过 ADK Web UI 或 API 提交审核结果。审核完成后,Workflow 从暂停点无缝恢复——不需要重新跑前面的步骤。
为什么 Resolver-Validator 模式能消灭幻觉
这个设计的有效性不是玄学,有扎实的认知科学基础。
单 Agent 的致命问题是确认偏误——LLM 生成一个答案后,如果让它自己检查,它大概率会找到理由确认自己是对的。这跟人类考生做完题检查不出自己的错误是一个道理。
Resolver-Validator 模式打破了这种偏误,因为:
独立推导。 Validator 不沿着 Resolver 的思路走,它从零开始重新推导。如果两个独立推导得到相同结果,正确的概率远高于单个推导。
对抗性思维。 Validator 的 instruction 暗示它「不信任」Resolver——这让它更倾向去找问题而不是找认同。在 prompt 层面制造了一种健康的对抗关系。
模型异构。 Resolver 用 Pro 模型(强推理),Validator 用 Flash 模型(不同参数分布)——它们不太可能犯同样的系统性错误。
强制反馈。 如果 Validator 拒绝答案,它必须给出具体反馈——"你的判别式计算错了,b²-4ac = 4-20 = -16,不是 0"。这让 Resolver 的二次作答有了精准的修正方向,而不是盲目重试。
这套模式不限于答题场景。任何需要「高准确率 + 可验证」的场景——代码审查、法律文书审核、医疗诊断辅助——都可以用同样的架构。
参考文档与链接
- Google ADK Python — 20.6K+ Stars,ADK 2.4.0 最新版本
- ADK 官方文档 — Workflow、Task API、ManagedAgent 完整文档
- ADK CHANGELOG — 2.0 到 2.4 的完整变更记录
- awesome-agent-design-comparison — 多框架 Agent 设计对比项目
- agents-design.md — 双循环架构参考设计
- questions.json — 50 道中考题测试集
- ADK 2.0 架构解析 — 前文:Workflow 图引擎和 Task API 深度分析
- DeepWiki: google/adk-python — ADK 模块架构和数据流分析
你觉得单 Agent 自检和多 Agent 互搏,哪个更靠谱?评论区聊聊你的经验。试过类似架构的,分享下踩过的坑。
作者: itech001
来源: 公众号:AI人工智能时代
网站: https://www.theaiera.cn/
每日分享最前沿的AI新闻资讯和技术研究。
关注公众号,获取更多 AI 技术干货!