## 已确认问题 ReAct.finish 调用 StructuredOutputFinalizer 后,只读取 result.status 和 result.data,把结构化数据写入 outputs;没有采用 finalizer 返回的 result.message。一次修复成功后,AgentOutcome 虽为 COMPLETED,最终消息仍是未通过校验的原输出,导致消息与结构化数据互相矛盾。 代码:https://github.com/agentic-ai-java/argi/blob/b34835354b27f1f320ea8438edf2e9d170e69c84/argi-agent/argi-agent-core/src/main/java/io/github/agentic/ai/agent/react/ReActAgent.java#L548;https://github.com/agentic-ai-java/argi/blob/b34835354b27f1f320ea8438edf2e9d170e69c84/argi-agent/argi-agent-core/src/main/java/io/github/agentic/ai/agent/react/ReActAgent.java#L560。 ## 最小复现与结果 1. 假主模型返回终态文本 `not-json`。 2. 配置要求包含字符串 answer 的对象 Schema,并启用 `new StructuredOutputFinalizer(repairClient)`。 3. 假修复客户端返回 `{"answer":"fixed"}`。 4. 调用独立 ReAct,检查最终状态、messages 最后一条和 outputs.structuredOutput。 实测:`status=COMPLETED`、最终消息 `not-json`、structuredOutput 为 `{"answer":"fixed"}`。两个模型均为离线 stub,修复已成功,问题位于结果交付而非 Schema 校验本身。 ## 交付与验收 - [ ] 修复成功时,以实际通过校验的终态消息作为最终交付,明确原始输出在诊断/历史中的保留方式,不能仅替换 data。 - [ ] Finished.outcome.messages、结构化数据与流式消费者能看到一致的最终结果;若需要完整消息更新,复用已有事件契约并明确消息关联。 - [ ] 不重复追加终态,不将原始失败输出误标为已经通过校验;无修复、修复失败和修复后仍不合法保持明确状态。 - [ ] 覆盖原输出合法、成功修复、修复后仍失败、修复客户端失败及流式完成场景,断言最终消息内容与结构化数据一致。 ## 关联与范围 关联 #142、#196、#236。修复请求漏计用量已有 #207,取消/deadline/预算已有 #206;本单仅处理 finalizer 已返回修复消息却未进入独立 ReAct 最终交付的问题,不重复上述记账和控制任务。 ## 验证基线与变更约束 Core `b34835354b27f1f320ea8438edf2e9d170e69c84`;Extensions `cb2635ab2fc338e8aade28a132a15f48b4e655fc`。本轮 Core 19 模块 clean install 通过,2517 个测试中 173 个跳过;此处缺陷由额外的独立 Java 探针确认,说明已有测试尚未覆盖对应行为,不代表真实模型或生产环境验收。 优先修复现有契约的实现,不强制拆模块或重命名,不让独立 Agent/Workflow 反向依赖 Graph/Loop,不向 Core 引入供应商 SDK。若必须改变公开 API、事件、配置或持久格式,说明较小替代方案、消费者影响、收益、迁移成本与目标版本;不得通过删测试、吞错误或弱化取消保证获得通过。 ## 配套缺陷 https://github.com/agentic-ai-java/argi/issues/280
Activity
XianReallyHot-ZZH commentedon Oct 28, 2026
你好,我想认领这个问题。计划先按 issue 中的最小复现确认交付缺陷(假主模型返回
not-json,修复客户端返回{"answer":"fixed"},最终status=COMPLETED而最终消息仍为not-json,与 structuredOutput 互相矛盾),然后在ReActAgent.finish采纳 finalizer 返回的result.message()作为最终交付:修复成功且修复消息与原终态不同时,将修复消息追加为最后一条交付消息(原始输出保留在其前一位供历史/诊断追溯,不误标为已通过校验),并复用现有AgentEvent.Message契约(model-repair)推送给流式消费者,保证Finished.outcome.messages、structuredOutput 与事件流三方一致;无修复发生时零行为变化,不重复追加终态,无修复、修复失败、修复后仍不合法的状态保持不变。AgentResult/AgentEvent/AgentOutcome/StructuredOutputFinalizer公共契约不动,仅改ReActAgent.finish内部实现;graph 侧旧ReactAgent不在本次范围,修复用量归集(#207)与流式消息 ID 一致性(#280)不纳入本单。测试为无模型依赖的行为测试,覆盖原输出合法、修复成功、修复后仍不合法、修复客户端失败、流式完成五个场景,断言最终消息内容与结构化数据一致。完成后提交 PR。fix(agent): deliver repaired structured output message as final ReAct…
konlue commentedon Nov 2, 2026
您好,我想认领 #278。
现状(#333 合并后的 main):
ReActAgent.finish只消费AgentResult的status与data,message被丢弃——repair 成功后structuredOutput是修复后的数据,而最终交付(outcome.messages与流式 Finished)仍是原始无效输出,两者矛盾;workflow 的对话历史(WorkflowAgent的 addAll)也会吸收坏输出。方案(单 PR,范围一个点):
result.message()与 terminal 不同)时,用result.message()替换 messages 列表中的 terminal 消息——替换而非追加,避免双份交付;测试(ScriptedClient + RepairStub 模式,全离线):有效输出直通(不替换)/ repair 成功(末条消息 = 修复文本 + structuredOutput = 解析数据 + 原始输出保留可查)/ repair 后仍失败(AgentExecutionException)/ repair client 失败(同上且 issue 标记 INVALID_JSON)/ 流式完成(Finished 的 messages 末条为 repaired)。
konlue commentedon Nov 2, 2026
撤回上面的认领:刚确认 #294 已经交付了同样的修复(repaired message 进入最终交付 + 原始输出保留在历史),实现与我在认领里提的方案一致。本票无需再做,感谢 @XianReallyHot-ZZH 的交付 🌹 我会转到本卷其他未认领的票上。