Repository navigation
[P1][T37] 增加工具上下文补丁校验与成功提交规则 #140
Copy link
Copy link
Labels
enhancementNew feature or requestNew feature or requestpriority/important-soon高优先级:近期应安排处理的重要问题高优先级:近期应安排处理的重要问题
Description
目标与优先级
缺口在工具提交业务上下文的边界,而非重建状态存储:失败补丁、保留键和串并行差异需明确。
- 优先级:P1;责任仓库:
agentic-ai-java/argi;补充任务:T37。 - 总览:https://github.com/agentic-ai-java/argi/issues/117。
当前证据与判断边界
- 已有 KeyStrategy/ToolStateCollector,parallel按tool原顺序使用KeyStrategy归并;不能说框架没有reducer。
- sequential路径使用putAll合并extraState;除timeout等明确清理路径外,merge没有统一成功状态检查,state snapshot还是浅拷贝。
以上是源码观察;能力补充结论是基于这些路径的推断,不等同生产故障或漏洞已经复现。框架已有ReAct/Hook、摘要、Todo、Schema声明、工具拦截及可选Sandbox,本任务是在其基础上补齐边界。
范围与落地方案
- 提供可选 typed/context patch或校验器,声明可写keys与Schema,复用既有KeyStrategy。
- 工具返回error/被guard拒绝/取消/超时后丢弃该调用补丁;不能修改lease/tenant/policy/engine保留状态。
- 以隔离的read view和patch更新代替直接改共享List/Map;定义sequential/parallel的可见性、冲突和顺序,不静默改旧规则。
- 新严格模式成功patch+tool result作为一个受校验更新单元;durable提交通过 [P1A][T06] 定义持久化 Run/Task 状态与原子提交能力契约 #122/[P1C][T15] 增加工具效果回执、幂等身份与 IN_DOUBT 核对路径 #126,而非新建独立Redis锁。
前置依赖
- 无前置Task,可独立交付基础契约和reference tests。
已有任务与去重边界
- [P0][T03] 在工具执行边界强制校验授权与风险策略 #120 (T03)
- [P1A][T06] 定义持久化 Run/Task 状态与原子提交能力契约 #122 (T06)
- [P1C][T14] 持久化模型调用结果与稳定工具执行计划 #125 (T14)
- [P1C][T15] 增加工具效果回执、幂等身份与 IN_DOUBT 核对路径 #126 (T15)
这些是关联/集成位置,不是额外硬阻塞。仅前置依赖要求先交付;持久化和跨实例能力继续由原任务承担。
验收条件
- callback先写extraState后抛错/返回已映射error时不污染下一轮上下文。
- tool写入框架保留键或错误类型时被拒绝,安全元数据与messages协议不会被业务字段覆盖。
- parallel完成顺序变化不改变定义的归并结果;APPEND/REPLACE/冲突策略有明确测试。
- 浅拷贝shared collection突变在严格模式被隔离或拒绝;旧ToolStateCollector/KeyStrategy API与默认行为回归通过。
非目标
- 不重建已有reducer/CAS,不重复Redis atomic commit;业务失败识别通过T38的显式outcome mapper集成,不猜测任意字符串。
兼容与验证
- Java 17,新增路径opt-in;保留现有公开API、默认行为与历史state/checkpoint格式。不引入MQ或节点级分片。
- Core不导入Redis/Extensions;优先复用已有API、reducer和组件,不直接添加新依赖。
- 先模型无关单测,再按本任务范围运行模块测试/API与格式fixture;跨adapter路径用stub contract tests,真实Docker测试注明环境要求。
- 当前main的兼容文档/CI曾调整,新任务不引用已删除文档或自行恢复CI;遵循实施时实际有效门禁,保留兼容回归目标。
源码依据(固定版本)
分析基线:Core f3bcbef24aa79e1e265a7d0d2011274982ac2978、Extensions 1ba3048f16d48c9f41dab171eed9a91148b45758。只读compare确认相对上次分析没有生产Java变更,主要是release/build/docs更新;本Issue不表示能力已实现。
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestpriority/important-soon高优先级:近期应安排处理的重要问题高优先级:近期应安排处理的重要问题
Activity
XianReallyHot-ZZH commentedon Oct 18, 2026
你好,我想认领 T37 这个任务 @Aias00
初步方案(按片交付,先交基础契约)
非目标遵守 issue 说明:不重建 reducer/CAS,业务失败识别通过 T38 显式 outcome mapper 集成,不猜测任意字符串。
XianReallyHot-ZZH commentedon Oct 24, 2026
Aias00 你好,跟进一下 T37 的进度:
Slice 1(#174)已合并,感谢。接下来计划推进剩余部分(验收 ③④):
注意到 main 在 10-24 完成了模块重构(#260–#263,agent-framework/graph-core 重组为 agent/orchestration/runtime),我会基于新模块结构继续实现,原有 opt-in 语义与兼容约束(不改公开 API、不动 state 格式、零新依赖)保持不变。
两个问题想确认:
XianReallyHot-ZZH commentedon Oct 24, 2026
补充一个实现方向的问题(基于重构后的代码现状):
注意到 #255 已引入 graph-independent 的 ReActAgent(argi-agent-core),并通过 ToolContextPatchProvider 复用了 tool patch 契约;同时架构文档(docs/architecture/target-architecture.md)将 AgentToolNode 所在的 argi-agent-framework 标记为 transitional(移除条件:所有消费者迁移至 neutral Agent contract)。
因此剩余部分(隔离读视图 / patch+result 更新单元 / 并行归并确定性,验收 ③④)的落点想确认您的倾向:
在收到回复前我先按方案 3 起草设计;如有不同意见随时纠正。
feat(agent): wire strict tool-state mode into graph tool node (T37)
feat(agent): wire strict tool-state mode into ReAct agent (T37)
Aias00 commentedon Oct 28, 2026
2026-10-27 更新后复核:严格模式仍有嵌套状态写入绕过
基线 Core
04c5686fe66b8daaa5d60190effa0cc1f40fdfe9。新增 strictToolState 已能拒绝第一层集合修改、丢弃失败补丁;但 StateIsolation 只复制一层,嵌套 Map/List 仍与运行状态共享引用。实现文档也明确写明 one-level-deep,因此这里是隔离范围不足以兑现本 issue 验收的问题,不是声称实现已经承诺任意 Java 对象的深度不可变。代码:https://github.com/agentic-ai-java/argi/blob/04c5686fe66b8daaa5d60190effa0cc1f40fdfe9/argi-agent/argi-agent-core/src/main/java/io/github/agentic/ai/agent/tool/patch/strict/StateIsolation.java#L54。
可控复现
records = List<Map>,其中记录为可变 Map,初始approved=false。独立 ReAct、Graph 串行和 Graph 并行均复现:失败工具执行后原状态为
records=[{approved=true}],未经过补丁准入。此处不是工具直接捕获调用方外部对象自行修改,而是使用框架提供的读取路径。剩余验收
本轮 Core 19 模块 clean install 通过,2578 个测试含 173 个跳过;上述结果来自额外离线假模型/工具探针,尚不涉及持久化或真实后端。
XianReallyHot-ZZH commentedon Oct 28, 2026
你好,我想认领这个后续 slice @Aias00(针对 10-27 复核指出的嵌套状态写入绕过)
初步方案
StateIsolation.readOnlyView从一层防御拷贝升级为递归只读包装:对 List/Map(含嵌套的List<Map>、Map<List>、多层组合)递归包裹 unmodifiable 视图,任意深度的集合写入都被拒绝;失败/超时工具对嵌套元素的修改不再触及运行状态(验收 ①)。List<Map>、Map<List>、多层组合、失败/超时路径,独立 ReAct、Graph 串行、Graph 并行三条路径均断言原状态不变、嵌套写入被拒(验收 ③)。取舍说明(想确认您的偏好):嵌套隔离有两条路线——A. 递归只读包装(拒绝写,上述方案);B. 递归防御深拷贝(隔离写,工具改的是副本、改动自然丢弃)。我倾向 A:更轻、无拷贝成本、深度/环引用问题天然消失,且与"只读视图 + 补丁通道写入"的严格模式语义一致——工具本来就不该写,写入即报错比悄悄改副本更可诊断。若您倾向 B 或混合(如嵌套也拷贝),我按您的意见调整。