Agent 工程体系 · 第 56/98 篇。内容以 2026 年 9 月可验证的公开规范和稳定接口为基线;框架版本敏感能力会明确标注,不把实验行为写成通用保证。
多模态 Agent:图像、音频、视频、文档、工具和证据对齐
多模态 Agent 不是“把图片、音频和视频一起塞给大模型”这么简单。它真正要解决的是:不同模态如何进入同一个任务状态,模型如何决定下一步动作,工具如何改变外部世界,以及最终回答中的每个结论如何回指到可验证证据。
如果只做模态理解,系统通常是一个多模态问答接口;如果加入规划、工具调用、状态维护和环境反馈,才接近 Agent。OpenAI 将 Agent 描述为能够规划、调用工具、协作并保留足够状态以完成多步骤工作的应用;Anthropic 则区分了固定代码路径编排的 workflow 与由模型动态决定过程和工具使用的 Agent。(developers.openai.com)
本文采用一个统一问题来组织各个部分:
用户上传一段客服通话、一张设备照片、一份维修手册和一段现场视频,要求判断故障原因、给出处理步骤,并说明每个判断依据。
这个问题同时包含图像、音频、视频、文档、工具和证据。如果其中任意一环没有对齐,最终答案就可能“看起来合理”,但无法复核。
一、先建立统一模型:模态不是答案,模态是带来源的观测
设一次 Agent 任务为:
其中:
- :用户目标,例如“判断设备是否过热”;
- :观测集合,包括图像、音频、视频帧和文档片段;
- :当前任务状态;
- :可执行动作,例如检索、测温、查询工单或请求人工确认;
- :环境反馈,例如工具返回值、传感器结果或人工决策;
- :完成条件,例如“给出故障判断并列出证据”。
Agent 的一次循环可以写为:
模型并不是直接从原始文件生成最终答案,而是在每一步根据当前状态选择动作:
其中 是模型形成的策略。工具执行后得到环境反馈:
这一区分非常重要:
- 图像中的“红色区域”是观测;
- “可能过热”是解释;
- “调用温度查询工具”是动作;
- 工具返回的 86℃ 是环境反馈;
- “确认超过安全阈值”才可能是结论。
如果把模型的解释直接当成事实,系统就失去了证据边界。
1. 证据对象的最小结构
工程上不要只把检索结果表示成字符串。至少应保留以下字段:
{
"evidence_id": "ev-017",
"source_id": "manual-v3.pdf",
"source_type": "document",
"locator": {
"page": 42,
"section": "过热保护"
},
"content": "当壳体温度高于 80℃ 时,应停止运行并等待冷却。",
"timestamp": null,
"region": null,
"confidence": 0.98,
"observed_at": "2026-08-31T10:20:00+08:00"
}
这里的 locator 不只是展示信息,它是证据可验证性的核心:
- 文档使用页码、章节、段落或表格坐标;
- 音频使用起止时间;
- 视频使用时间区间和帧号;
- 图像使用区域坐标;
- 工具使用请求参数、响应摘要和响应时间;
- 人工确认使用操作者、时间和审批记录。
一个答案中的主张 应映射到证据集合:
当 时,系统不能把该主张写成确定事实;它最多只能写成待验证假设。
二、图像:从视觉内容到可引用的空间证据
1. 图像 Agent 需要回答三个不同问题
图像输入通常被混成一个问题:“图片里有什么?”但生产系统至少要区分:
- 检测:是否存在某个对象或状态;
- 定位:对象位于图像什么区域;
- 解释:该视觉现象对当前任务意味着什么。
例如:
图像右上方出现一块深色烧蚀区域。
这是视觉观察。
该区域可能表示外壳局部过热。
这是诊断假设。
设备已经超过允许温度。
这是需要额外证据支持的结论,不能仅凭颜色直接推出。
因此,图像分析输出最好分层:
{
"observations": [
{
"text": "连接器右侧存在明显变色区域",
"region": [612, 188, 804, 376],
"confidence": 0.91
}
],
"hypotheses": [
{
"text": "可能存在热损伤或材料老化",
"supported_by": ["img-obs-001"],
"requires": ["温度测量", "维修手册比对"]
}
]
}
2. 空间定位必须进入证据模型
如果 Agent 只保存“图片中有烧焦痕迹”,后续工程师无法确认模型看的是否是同一位置。应把空间信息当作引用坐标:
对于不同分辨率的图片,建议同时保存原图尺寸:
{
"image_id": "img-001",
"width": 1920,
"height": 1080,
"region": {
"x1": 612,
"y1": 188,
"x2": 804,
"y2": 376
}
}
如果后续生成缩略图,坐标可以按比例换算:
其中 是原图尺寸, 是展示图尺寸。
3. 图像的真实边界
图像适合提供:
- 外观状态;
- 位置关系;
- 标识和读数;
- 结构损伤线索;
- 与文档插图的视觉比对。
图像不适合单独证明:
- 精确温度;
- 材料内部缺陷;
- 时间顺序;
- 因果关系;
- 某个安全阈值是否已经被突破。
一个典型反例是:照片中有红色指示灯。模型回答“设备已经过热”。但红灯也可能表示待机、联网、告警或电源状态。正确做法是将“红灯亮起”作为图像证据,再查询设备手册或调用设备状态工具。
三、音频:语义、说话人和时间轴必须分离
音频 Agent 不只是 ASR,即自动语音识别。一个可用的语音链路通常包括:
1. VAD:判断“有人说话”而不是识别内容
VAD,即 Voice Activity Detection,负责判断音频中哪些时间区间包含语音:
00:00.000 - 00:01.240 静音
00:01.240 - 00:04.880 语音
00:04.880 - 00:05.310 短暂停顿
00:05.310 - 00:08.920 语音
VAD 的错误会直接影响延迟和语义:
- 起点过晚:丢掉首字;
- 终点过早:把一句话切成两段;
- 噪声误触发:浪费 ASR 和推理资源;
- 长时间不切分:用户等待时间增加。
所以 VAD 区间不是最终证据,它只是 ASR 的分段边界。
2. ASR:文本必须携带时间戳和置信度
普通转写:
设备现在有点烫,而且风扇声音不对。
可引用转写:
{
"segment_id": "aud-seg-003",
"speaker": "user",
"start_ms": 5310,
"end_ms": 8920,
"text": "设备现在有点烫,而且风扇声音不对。",
"confidence": 0.94,
"language": "zh"
}
时间戳允许最终回答引用:
用户在 00:05.310–00:08.920 提到设备发热且风扇声音异常。
但这句话仍然只是用户陈述,不等价于测量事实。证据类型必须标为 user_report,而不是 sensor_observation。
3. 流式推理与可撤销中间结果
流式 ASR 常会先输出不稳定文本:
partial-1: 设备现在有点热
partial-2: 设备现在有点烫,而且
final: 设备现在有点烫,而且风扇声音不对。
Agent 不应在 partial 阶段执行不可逆工具动作。例如,不能因为临时识别出“关闭设备”,就立即切断电源。安全动作至少要等待:
- ASR 标记为 final;
- 意图解析完成;
- 工具参数校验通过;
- 必要时取得用户确认。
4. 语音 Agent 的延迟预算
一次语音交互的端到端延迟可以近似为:
其中:
- :采集和缓冲;
- :语音结束判断;
- :识别延迟;
- :模型决策延迟;
- :工具调用延迟;
- :语音合成首包延迟;
- :播放缓冲延迟。
优化时不能只看模型推理时间。如果 VAD 为了避免截断而等待很久,或者工具每次都串行查询,用户感知的延迟仍然很高。
5. 打断是状态转换,不是停止播放
语音 Agent 至少需要维护:
IDLE
-> LISTENING
-> THINKING
-> SPEAKING
-> INTERRUPTED
-> LISTENING
当用户在 SPEAKING 状态开始说话时,系统应:
- VAD 检测到新的语音;
- 立即停止或衰减 TTS 播放;
- 标记当前输出为
interrupted; - 保存已经播放和未播放的文本区间;
- 将新语音作为新的输入事件;
- 决定是否复用旧推理结果。
如果只调用播放器的 stop(),但不更新 Agent 状态,模型可能继续认为自己已经完成回答,导致下一轮上下文错乱。
四、视频:关键问题是时间采样和事件连续性
视频不是“很多张图片”。它额外包含时间关系:
其中 是第 帧, 是该帧时间戳。
1. 视频理解的三层输出
视频 Agent 应将结果分成:
- 帧级观察:某一时刻看到什么;
- 片段级事件:某一时间区间发生了什么;
- 任务级判断:该事件是否满足目标条件。
例如:
{
"frame_observation": {
"time_ms": 12400,
"text": "风扇叶片停止转动",
"frame_id": "frame-372"
},
"event": {
"start_ms": 11800,
"end_ms": 14600,
"text": "风扇逐渐减速并停止"
},
"task_claim": {
"text": "设备在运行期间出现风扇停转",
"supported_by": ["frame-372", "video-event-09"]
}
}
“某一帧看起来停了”不能直接证明“整个设备运行期间风扇都停了”。后者需要时间范围内的连续观察。
2. 采样策略影响结论
设视频总时长为 ,采样间隔为 。若事件持续时间小于 ,均匀采样可能完全漏掉事件。
例如:
- 视频时长:60 秒;
- 每 5 秒采样一帧;
- 故障闪烁持续 1 秒;
- 故障恰好发生在两个采样点之间。
则采样结果可能显示“没有故障”。这不是模型推理错误,而是观测策略造成的信息缺失。
因此,视频 Agent 常采用两阶段策略:
- 低成本均匀采样,定位疑似异常区间;
- 对异常区间提高采样率或提取连续片段;
- 让模型对片段而不是孤立帧进行判断。
3. 视频与音频要共用时间轴
现场视频中的“风扇停转”和音频中的“声音突然消失”只有在时间轴对齐后,才能形成联合证据:
视频:00:11.800 - 00:14.600 风扇减速并停止
音频:00:12.030 - 00:14.510 风扇噪声消失
这两个证据相互支持,但不能重复计数成两个完全独立的事实,因为它们来自同一段视频。证据聚合时应记录 source_id 和派生关系,避免把同一来源的多个观察误当成独立投票。
五、文档:解析、切分和引用位置决定知识质量
文档 Agent 面临的难点不是“把 PDF 转成文本”,而是保留文档结构:
- 页码;
- 标题层级;
- 表格行列;
- 脚注;
- 图片与图注;
- 版本号;
- 生效日期;
- 页眉页脚;
- OCR 不确定区域。
1. 文档证据的结构化表示
{
"chunk_id": "doc-042-sec-3",
"source_id": "manual-v3.pdf",
"source_version": "v3",
"page_start": 42,
"page_end": 42,
"section": "3.4 过热保护",
"text": "当壳体温度高于 80℃ 时,应停止运行并等待冷却。",
"table_coordinates": null,
"content_hash": "sha256:..."
}
content_hash 的作用是防止引用漂移。若文档重新上传后内容发生变化,即使文件名相同,也应视为新的来源版本。
2. 切分不能破坏条件和例外
错误切分:
片段 A:当壳体温度高于 80℃ 时,应停止运行。
片段 B:环境温度低于 5℃ 时除外。
如果检索只召回片段 A,模型可能给出过于绝对的结论。更安全的切分应保留条件、例外和适用范围:
当壳体温度高于 80℃ 时,应停止运行并等待冷却;环境温度低于 5℃ 时,适用另一套低温保护流程。
文档检索的目标不是找到“相似句子”,而是找到足以约束结论的完整证据单元。
3. 文档版本冲突
假设:
manual-v2.pdf:温度阈值为 80℃;manual-v3.pdf:温度阈值改为 75℃;- 工单系统记录设备固件为 v3。
此时 Agent 不应简单地把两个数字平均,也不应选择检索排名更高的片段。它需要执行版本解析:
如果无法判断适用版本,应明确报告冲突:
发现两个手册版本给出不同阈值。当前设备固件对应关系尚未确认,因此不能可靠判断 78℃ 是否触发保护。
六、工具:工具调用是状态变更,不是函数装饰
工具可以分为三类:
- 查询工具:读取订单、设备状态、知识库;
- 计算工具:执行公式、解析文件、运行代码;
- 副作用工具:发送邮件、退款、关机、修改数据库。
工具调用的风险随副作用增加。一个安全的工具描述至少应包含:
{
"name": "get_device_temperature",
"description": "查询设备最近一次温度测量值,不执行任何控制动作。",
"input_schema": {
"type": "object",
"properties": {
"device_id": {
"type": "string",
"description": "设备唯一标识"
}
},
"required": ["device_id"],
"additionalProperties": false
},
"side_effect": "read_only",
"freshness_seconds": 30,
"permission": "device:read"
}
工具说明应接近人机界面设计,而不是只写函数名。Anthropic 特别强调,工具定义和工具规范需要像提示词一样被认真设计;工具格式、参数约束和错误信息会直接影响 Agent 能否正确行动。(anthropic.com)
1. 工具结果必须进入证据链
错误做法:
工具返回:86
模型回答:温度很高,建议停机。
正确做法:
{
"tool_call_id": "call-19",
"tool": "get_device_temperature",
"arguments": {
"device_id": "D-1007"
},
"result": {
"temperature_c": 86,
"measured_at": "2026-09-01T09:24:10+08:00"
},
"evidence": {
"evidence_id": "tool-ev-19",
"source_type": "device_sensor",
"freshness_seconds": 30
}
}
然后由规则或文档证据完成比较:
这里的关键不是模型“觉得 86 很高”,而是把工具结果与适用版本的阈值证据放在同一推理上下文中。
2. 工具错误也属于状态
工具失败不能只返回字符串 "error"。至少要区分:
{
"status": "failed",
"error_code": "DEVICE_TIMEOUT",
"retryable": true,
"attempt": 2,
"safe_to_retry": true,
"user_visible_message": "设备暂时没有响应"
}
Agent 的处理路径应根据错误类型分支:
超时
-> 若幂等且未超过次数:重试
-> 若不可确认是否执行成功:查询状态,不直接重试
-> 若超过预算:转人工或返回不确定性
参数错误
-> 不重试
-> 修正参数或请求用户补充信息
权限错误
-> 不重试
-> 请求授权或改变流程
副作用执行未知
-> 查询操作状态
-> 禁止盲目重复执行
“发送邮件”或“退款”这类工具尤其需要幂等键:
{
"operation_id": "refund-order-1007-v1",
"order_id": "1007",
"amount": 19900,
"currency": "CNY"
}
服务端应保证同一个 operation_id 不会产生两次副作用。
七、证据对齐:从“有引用”到“引用真的支持结论”
1. 主张和证据不是一对一关系
一个结论可能需要多个证据:
设备需要停机。
可能需要:
- 图像:看到烧蚀区域;
- 传感器:当前温度 86℃;
- 文档:当前版本规定 80℃以上停机;
- 工具:设备仍处于运行状态。
可以定义一个主张的支持条件:
缺少任意一项时,结论强度应下降。
2. 支持、反驳和无关证据
证据关系至少分为三类:
{
"claim_id": "claim-07",
"text": "设备应立即停止运行",
"relations": [
{
"evidence_id": "tool-ev-19",
"relation": "supports",
"reason": "温度测量为 86℃"
},
{
"evidence_id": "doc-ev-42",
"relation": "supports",
"reason": "适用手册规定超过 80℃ 应停止运行"
},
{
"evidence_id": "user-ev-03",
"relation": "context",
"reason": "用户报告设备外壳发烫"
}
]
}
用户报告可以作为上下文,但不能与传感器读数拥有相同的事实等级。证据类型、来源可信度、时间新鲜度和版本适用性都应参与判断。
3. 冲突处理不能用平均值解决
假设:
- 音频:用户说“风扇已经停了”;
- 视频:00:12–00:14 风扇停转;
- 实时设备状态:风扇当前转速为 1200 RPM。
这些结果不一定矛盾,因为它们对应不同时间。应先按时间切片:
如果用户问的是“刚才是否停过”,视频证据有效;如果问的是“现在是否停转”,实时工具更相关。
真正的冲突是:
- 同一设备;
- 同一时间范围;
- 同一指标;
- 不同来源给出不一致结果。
此时应输出冲突本身,并说明下一步验证动作,而不是隐藏冲突后给出单一答案。
八、一个完整的多模态 Agent 数据流
flowchart TD
U[用户目标] --> I[输入接入层]
I --> N[模态归一化]
N --> O[观测对象]
O --> P[任务状态与证据图]
P --> D[Agent 决策循环]
D -->|检索| R[文档/知识库]
D -->|查询| T[只读工具]
D -->|控制| A[副作用工具]
D -->|补充观察| V[图像/音频/视频分析]
R --> P
T --> P
V --> P
A --> F[工具执行反馈]
F --> P
P --> C[主张-证据校验]
C -->|证据不足| Q[追问/人工确认]
C -->|证据充分| O1[结构化回答]
O1 --> X[文本或TTS输出]
关键路径不是“模型调用一次”,而是:
- 输入被转换成带时间、空间和来源的观测;
- 观测写入任务状态;
- Agent 选择检索、分析或工具动作;
- 环境反馈再次写入状态;
- 输出主张必须经过证据校验;
- 证据不足时转为追问或人工确认。
OpenAI Agents SDK 当前文档也将运行循环、工具调用、交接、审批、状态和可观测性作为独立能力;如果应用需要完全自定义循环,则可以自行管理模型交互、输出项、工具和分支。(developers.openai.com)
九、可执行的最小证据对齐实现
下面的代码不依赖具体模型供应商,演示“主张必须绑定证据”的最小机制。它可以直接用 Python 运行。
from dataclasses import dataclass, field
from typing import List, Literal
Relation = Literal["supports", "contradicts", "context"]
@dataclass
class Evidence:
evidence_id: str
source_type: str
content: str
confidence: float
freshness_seconds: int | None = None
@dataclass
class Claim:
claim_id: str
text: str
evidence_ids: List[str] = field(default_factory=list)
def validate_claim(
claim: Claim,
evidence_map: dict[str, Evidence],
min_confidence: float = 0.8,
) -> tuple[bool, str]:
if not claim.evidence_ids:
return False, "没有绑定任何证据"
missing = [
evidence_id
for evidence_id in claim.evidence_ids
if evidence_id not in evidence_map
]
if missing:
return False, f"证据不存在: {missing}"
evidences = [evidence_map[eid] for eid in claim.evidence_ids]
weak = [
e.evidence_id
for e in evidences
if e.confidence < min_confidence
]
if weak:
return False, f"证据置信度不足: {weak}"
return True, "证据绑定通过"
evidence = {
"sensor-001": Evidence(
evidence_id="sensor-001",
source_type="device_sensor",
content="设备 D-1007 温度为 86℃",
confidence=0.99,
freshness_seconds=10,
),
"manual-042": Evidence(
evidence_id="manual-042",
source_type="document",
content="当前手册规定壳体温度高于 80℃ 时应停止运行",
confidence=0.98,
),
}
claim = Claim(
claim_id="claim-001",
text="设备 D-1007 应停止运行",
evidence_ids=["sensor-001", "manual-042"],
)
ok, message = validate_claim(claim, evidence)
print(ok, message)
预期输出:
True 证据绑定通过
这段代码只检查“是否存在足够可信的绑定证据”,并没有证明语义蕴含关系。例如,它不能自动判断 86℃ 是否真的高于 80℃,也不能确认手册是否适用于当前设备。因此生产实现还需要:
- 结构化数值比较;
- 文档版本匹配;
- 时间新鲜度校验;
- 冲突检测;
- 主张类型约束;
- 人工审核策略。
可以把主张限制为结构化形式:
{
"claim_type": "threshold_violation",
"metric": "temperature",
"observed_value": 86,
"threshold": 80,
"operator": ">",
"unit": "C",
"evidence_ids": ["sensor-001", "manual-042"]
}
这样,核心判断可以由确定性代码执行,而不是完全交给自然语言模型。
十、从观测到回答的完整算例
输入:
- 图片:连接器右侧有变色区域;
- 视频:00:11.800–00:14.600 风扇逐渐停止;
- 音频:00:05.310–00:08.920 用户说“设备有点烫,风扇声音不对”;
- 文档:当前版本手册规定温度超过 80℃ 应停机;
- 工具:设备 D-1007 当前温度为 86℃,运行状态为
running。
第一步:形成观测
O1 = 图像观察:连接器右侧变色
O2 = 视频观察:风扇在 00:11.800–00:14.600 停止
O3 = 用户陈述:设备发烫、风扇声音异常
O4 = 传感器事实:当前温度 86℃
O5 = 规范事实:超过 80℃ 应停机
O6 = 当前状态:设备仍在运行
第二步:提出假设
H1:设备可能存在散热或风扇故障
H2:设备当前温度超过安全阈值
H3:设备应立即停止运行
其中:
- H1 由 O1、O2、O3 支持,但仍是诊断假设;
- H2 由 O4、O5 经过确定性比较得到;
- H3 还需要 O6,因为“应停止”意味着当前仍处于运行状态。
第三步:选择动作
若系统具备关机工具,不能直接执行。因为这是副作用动作,应先确认:
当前设备运行中,温度 86℃,适用阈值为 80℃。
是否立即停止设备?
如果业务政策规定该条件下自动停机,则可以执行,但必须记录:
{
"action": "stop_device",
"device_id": "D-1007",
"policy_basis": ["manual-042", "safety-policy-07"],
"approval": "automatic_policy",
"idempotency_key": "stop-D-1007-20260901-092410"
}
第四步:生成回答
较好的回答是:
设备存在需要立即处理的过热风险。当前温度为 86℃,而适用手册规定壳体温度高于 80℃ 时应停止运行,因此已满足停机条件。现场视频显示风扇在 00:11.800–00:14.600 期间减速并停止,图片还显示连接器右侧有变色区域,这些现象支持散热或连接器热损伤的诊断假设。用户在 00:05.310–00:08.920 也报告了设备发烫和风扇声音异常,但该部分属于用户陈述,不能替代传感器测量。建议先停止设备,待冷却后检查风扇供电、叶片阻塞和连接器烧蚀情况。
这段回答把三种内容分开:
- 事实:86℃、手册阈值、视频时间段;
- 假设:可能存在散热或连接器热损伤;
- 行动建议:停止设备并检查。
十一、常见错误及其诊断方式
错误一:把转写文本当成事实
失败表现:
用户说设备温度已经超过 80℃,因此设备过热。
诊断方法:
- 查看证据类型是否为
user_report; - 检查是否有传感器或仪表读数;
- 检查转写是否存在数值识别错误;
- 检查该语句是否为引用、猜测或反问。
修复方式是把答案改为:
用户报告设备温度可能超过 80℃,但当前没有独立测量结果确认。
错误二:视频只看关键帧,不看事件区间
失败表现:
视频中风扇停止。
但没有说明何时停止、是否恢复,也没有说明是否存在遮挡。
诊断时应查看:
- 采样间隔;
- 关键帧前后各若干秒;
- 是否发生镜头切换;
- 视频时间戳是否从零开始;
- 音视频是否同步。
错误三:文档引用没有版本
失败表现:
根据手册,阈值是 80℃。
但系统中同时存在多个版本。
诊断时查看:
source_version;- 生效日期;
- 设备型号和固件;
- 检索结果是否跨版本混合;
- 引用是否能定位到页码和章节。
错误四:工具成功不等于业务成功
例如工具返回 HTTP 200,但响应内容是:
{
"accepted": true,
"status": "pending"
}
这只能说明请求已接收,不代表设备已经停机。Agent 应继续查询最终状态,或者向用户明确说明:
停机指令已提交,但设备是否已经停止尚未确认。
错误五:把多个派生证据当成独立投票
图像分析模型从同一张图生成三个相似描述,不代表有三个独立证据。证据聚合应按来源去重:
这不是说同一来源的信息没有价值,而是不能错误地放大置信度。
十二、并发、取消和故障路径
多模态 Agent 通常同时处理多个输入:
- 音频转写持续进行;
- 视频抽帧异步执行;
- 文档 OCR 和检索并行;
- 工具查询需要等待网络;
- 主模型可能在中间结果到达后重新规划。
并发安全的关键是为每个事件分配单调递增的序号:
{
"session_id": "s-1007",
"event_seq": 42,
"event_type": "sensor_result",
"created_at": "2026-09-01T09:24:10+08:00",
"payload": {}
}
状态更新必须检查版本:
否则会出现旧的 ASR partial 覆盖新的 final,或旧工具响应覆盖最新设备状态。
取消传播
当用户打断语音回答时,取消信号应传播到:
TTS 播放器
-> 音频生成任务
-> 主模型流
-> 尚未开始的只读工具
-> 可取消的视频分析任务
但已经提交的副作用操作不能简单取消,必须查询其最终状态。取消是一种控制消息,不是对外部世界的回滚保证。
十三、Workflow 还是 Agent
不是所有多模态流程都应该做成自主 Agent。
如果流程固定为:
上传视频
-> 抽帧
-> ASR
-> 查询手册
-> 生成报告
那么它更适合 workflow。固定路径更容易测试、计费和审计。
如果任务需要根据内容动态决定:
- 是否继续分析视频;
- 是否查询设备状态;
- 是否搜索多个版本的手册;
- 是否请求用户补充照片;
- 是否转人工;
- 是否执行控制动作;
那么才需要 Agent 的动态决策。
Anthropic 建议从最简单的方案开始,因为 Agent 的灵活性通常伴随更高延迟、更高成本和错误累积风险;固定任务优先使用可预测的 workflow,只有当任务步骤难以预先确定时才增加 Agent 自主性。(anthropic.com)
一个实用的划分方式是:
| 场景 | 推荐结构 |
|---|---|
| 固定格式的发票识别 | Workflow |
| 多份文档中的字段核对 | Workflow + 并行处理 |
| 根据证据缺口决定是否继续查证 | Agent |
| 语音客服中的查询、追问和转人工 | Agent |
| 设备控制和安全审批 | Agent + 确定性策略门 |
| 高风险副作用操作 | Agent 规划 + 程序化审批 |
十四、生产系统必须保留什么
一个可审计的多模态 Agent 运行记录至少应包含:
{
"run_id": "run-20260901-001",
"user_goal": "判断设备是否需要停机",
"inputs": [
{"type": "image", "id": "img-001", "sha256": "..."},
{"type": "audio", "id": "aud-001", "sha256": "..."},
{"type": "video", "id": "vid-001", "sha256": "..."},
{"type": "document", "id": "manual-v3.pdf", "version": "v3"}
],
"observations": [],
"claims": [],
"tool_calls": [],
"approvals": [],
"final_answer": {},
"status": "completed"
}
还应能回答以下问题:
- 模型看到了哪一个文件版本;
- 视频结论来自哪些时间区间;
- 音频转写是否为 final;
- 工具调用使用了哪些参数;
- 工具结果产生于什么时候;
- 哪些结论是事实,哪些是推断;
- 哪些证据互相冲突;
- 哪个动作造成了外部副作用;
- 用户是否打断过输出;
- 最终答案是否经过人工确认。
OpenAI 文档将 tracing、状态、审批、运行结果和评估作为 Agent 系统的重要组成部分;这说明可观测性不是上线后的附加功能,而是 Agent 运行时的一部分。(developers.openai.com)
十五、评估不能只评估最终文本
多模态 Agent 的评估至少分成五层:
1. 模态解析正确性
- 图像区域是否正确;
- ASR 是否漏词;
- 时间戳是否偏移;
- 视频事件起止是否合理;
- 文档页码和表格结构是否保留。
2. 状态更新正确性
- 新事件是否覆盖旧事件;
- partial 是否被 final 替换;
- 工具失败是否进入状态;
- 用户打断是否取消输出;
- 过期传感器结果是否被拒绝。
3. 工具选择和参数正确性
- 是否选对工具;
- 是否使用最新设备标识;
- 是否正确处理单位;
- 是否在副作用动作前取得授权;
- 是否避免重复执行。
4. 证据对齐正确性
- 每个重要主张是否有证据;
- 证据是否真的支持主张;
- 引用位置是否可复核;
- 冲突是否被显式报告;
- 不确定性是否与证据质量一致。
5. 任务完成质量
- 是否给出用户真正需要的结论;
- 是否完成必要动作;
- 是否在不能确定时正确追问;
- 是否在风险条件下停止自动化。
一个只检查最终答案“像不像正确答案”的评估,会掩盖中间错误。例如,答案恰好正确,但引用了错误版本的手册;下一次版本更新后系统就会失效。
结语:多模态 Agent 的核心是对齐,而不是模态数量
图像提供空间观察,音频提供语义和声学时间线,视频提供连续事件,文档提供规范和背景,工具提供环境事实与动作能力,证据系统则把这些信息绑定到可复核的来源。
真正可靠的多模态 Agent 需要同时满足:
任何一个条件缺失,系统都可能产生表面流畅、实际不可审计的回答。
因此,设计重点不应是“支持多少种模态”,而应是:
- 每种模态是否保留时间、空间和版本信息;
- 观测、推断、工具结果和用户陈述是否被区分;
- Agent 是否根据环境反馈而不是自身猜测继续行动;
- 工具副作用是否受权限、幂等和审批控制;
- 最终每个关键主张是否能够回指到证据;
- 证据不足或发生冲突时,系统是否愿意明确说“不确定”。
当这些关系被建模为状态、事件、主张和证据,而不是散落在提示词和日志中的字符串时,多模态 Agent 才从“会看、会听、会调用工具”进化为可以被验证、调试和负责的工程系统。
系列导航与关联阅读
- 系列入口:Agent 工程完整路线:从运行循环、记忆与协议到安全、评测和生产交付
- 上一篇:Computer Use Agent:截图、坐标、动作循环、确认和桌面安全
- 下一篇:语音 Agent:VAD、ASR、流式推理、TTS、打断和延迟预算
- 延伸:Agent 知识引用:证据片段、来源映射、冲突和可验证回答
官方资料
本文依据 Agent、模型、协议与框架官方资料重新梳理;正文、示例与生产清单由 WR BLOG 编写。

评论
0 条讨论