Skip to content

[P1][T37] 增加工具上下文补丁校验与成功提交规则 #140

Closed

Description

@Aias00

目标与优先级

缺口在工具提交业务上下文的边界,而非重建状态存储:失败补丁、保留键和串并行差异需明确。

当前证据与判断边界

  • 已有 KeyStrategy/ToolStateCollector,parallel按tool原顺序使用KeyStrategy归并;不能说框架没有reducer。
  • sequential路径使用putAll合并extraState;除timeout等明确清理路径外,merge没有统一成功状态检查,state snapshot还是浅拷贝。

以上是源码观察;能力补充结论是基于这些路径的推断,不等同生产故障或漏洞已经复现。框架已有ReAct/Hook、摘要、Todo、Schema声明、工具拦截及可选Sandbox,本任务是在其基础上补齐边界。

范围与落地方案

前置依赖

  • 无前置Task,可独立交付基础契约和reference tests。

已有任务与去重边界

这些是关联/集成位置,不是额外硬阻塞。仅前置依赖要求先交付;持久化和跨实例能力继续由原任务承担。

验收条件

  • 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不表示能力已实现。

Activity

  1. added theissue type on Oct 9, 2026
  2. XianReallyHot-ZZH commented on Oct 18, 2026

    @XianReallyHot-ZZH
    Contributor

    你好,我想认领 T37 这个任务 @Aias00

    初步方案(按片交付,先交基础契约)

    1. 新增可选 typed context patch 契约与校验器:工具声明可写 keys 与 value 校验规则,复用既有 KeyStrategy / ToolStateCollector,不新建 reducer;补丁写框架保留键(lease/tenant/policy/engine 等)或错误类型时拒绝。
    2. 失败补丁丢弃边界:tool 返回 error / 被 guard 拒绝 / 取消 / 超时后,该调用的 extraState 补丁不进入下一轮上下文(验收 ①②)。
    3. 作为后续片跟进:严格模式下以隔离 read view + 受校验 patch 更新单元代替直接突变共享 List/Map(覆盖 sequential putAll 与 parallel 浅拷贝快照两条路径);parallel 完成顺序变化不改变归并结果,APPEND/REPLACE/冲突策略有明确测试(验收 ③④)。
    4. 新路径全部 opt-in,不改现有公开 API、默认行为与历史 state/checkpoint 格式;Core 不引入新依赖;durable 原子提交复用 [P1A][T06] 定义持久化 Run/Task 状态与原子提交能力契约 #122(T06)/[P1C][T15] 增加工具效果回执、幂等身份与 IN_DOUBT 核对路径 #126(T15)契约,不建新锁。

    非目标遵守 issue 说明:不重建 reducer/CAS,业务失败识别通过 T38 显式 outcome mapper 集成,不猜测任意字符串。

  3. XianReallyHot-ZZH commented on Oct 24, 2026

    @XianReallyHot-ZZH
    Contributor

    Aias00 你好,跟进一下 T37 的进度:

    Slice 1(#174)已合并,感谢。接下来计划推进剩余部分(验收 ③④):

    • 严格模式下的隔离读视图:以隔离 read view + 受校验的 patch 更新单元代替直接突变共享 List/Map,覆盖 sequential putAll 与 parallel 浅拷贝快照两条路径;
    • parallel 归并确定性:完成顺序变化不改变归并结果,APPEND/REPLACE/冲突策略的明确测试。

    注意到 main 在 10-24 完成了模块重构(#260–#263,agent-framework/graph-core 重组为 agent/orchestration/runtime),我会基于新模块结构继续实现,原有 opt-in 语义与兼容约束(不改公开 API、不动 state 格式、零新依赖)保持不变。

    两个问题想确认:

    1. 此前的认领是否仍然生效?(feat(agent): add tool context patch validation and failure discard boundary (T37) #174 已合并,我默认理解为按片交付被认可)
    2. docs(architecture): define independent target architecture #260 的新架构文档对 state 隔离/工具归并有新的方向性要求吗?若有,我按新方向调整。
  4. XianReallyHot-ZZH commented on Oct 24, 2026

    @XianReallyHot-ZZH
    Contributor

    补充一个实现方向的问题(基于重构后的代码现状):

    注意到 #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 更新单元 / 并行归并确定性,验收 ③④)的落点想确认您的倾向:

    1. 按 issue 原文,仅落在 AgentToolNode(graph 路径);
    2. 落在 ReActAgent(独立路径);
    3. 核心逻辑落在共享契约层(argi-agent-core,patch 契约现所在地),graph 路径与 ReAct 路径各自薄接入——隔离/单元化/确定性归并本身是引擎无关的纯逻辑,我的初步倾向是 3。

    在收到回复前我先按方案 3 起草设计;如有不同意见随时纠正。

  5. Aias00 commented on Oct 28, 2026

    @Aias00
    ContributorAuthor

    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。

    可控复现

    1. 输入 records = List<Map>,其中记录为可变 Map,初始 approved=false。
    2. 启用 strictToolState(true),并启用只允许补丁写入 safe 的 ToolContextPatchPolicy。
    3. 假工具仅从框架传入的 ToolContext 读取 records,将第一个 Map 的 approved 改为 true,然后返回 ToolResult.error;不提交任何 context patch。
    4. 检查后续运行状态。

    独立 ReAct、Graph 串行和 Graph 并行均复现:失败工具执行后原状态为 records=[{approved=true}],未经过补丁准入。此处不是工具直接捕获调用方外部对象自行修改,而是使用框架提供的读取路径。

    剩余验收

    • 对支持的嵌套业务数据建立真正隔离或拒绝修改的读取表示,不能让失败调用绕过 patch 通道写入。
    • 明确可支持的数据类型和深度/环引用策略,不要求无边界复制任意可变 Java 对象,也不引入 Graph 到中立工具层。
    • 为 List、Map、多层组合及失败/超时路径补行为测试,串并行和独立 ReAct 均验证原状态不变。
    • 保留已实现的第一层集合隔离、补丁校验和默认非严格模式兼容行为。

    本轮 Core 19 模块 clean install 通过,2578 个测试含 173 个跳过;上述结果来自额外离线假模型/工具探针,尚不涉及持久化或真实后端。

  6. XianReallyHot-ZZH commented on Oct 28, 2026

    @XianReallyHot-ZZH
    Contributor

    你好,我想认领这个后续 slice @Aias00(针对 10-27 复核指出的嵌套状态写入绕过)

    初步方案

    1. StateIsolation.readOnlyView 从一层防御拷贝升级为递归只读包装:对 List/Map(含嵌套的 List<Map>、Map<List>、多层组合)递归包裹 unmodifiable 视图,任意深度的集合写入都被拒绝;失败/超时工具对嵌套元素的修改不再触及运行状态(验收 ①)。
    2. 类型边界明确声明:保护范围限于集合容器(List/Map 递归);非集合可变对象(业务 POJO 等)与既有行为一致,不在保护范围——对应"不要求无边界复制任意可变 Java 对象"。递归包装不做深拷贝,包装时以同一容器复用同一包装实例处理环引用,天然无无限递归(验收 ②)。
    3. 顶层既有行为不变:顶层仍防御拷贝(执行中底层结构变化不透出),非严格模式完全不动(验收 ④)。
    4. 行为测试覆盖:List<Map>、Map<List>、多层组合、失败/超时路径,独立 ReAct、Graph 串行、Graph 并行三条路径均断言原状态不变、嵌套写入被拒(验收 ③)。
    5. 不改公开 API、事件、配置与 state/checkpoint 格式,零新依赖;落点仍在 argi-agent-core 的 strict 包,Graph 路径经既有调用点自然受益。

    取舍说明(想确认您的偏好):嵌套隔离有两条路线——A. 递归只读包装(拒绝写,上述方案);B. 递归防御深拷贝(隔离写,工具改的是副本、改动自然丢弃)。我倾向 A:更轻、无拷贝成本、深度/环引用问题天然消失,且与"只读视图 + 补丁通道写入"的严格模式语义一致——工具本来就不该写,写入即报错比悄悄改副本更可诊断。若您倾向 B 或混合(如嵌套也拷贝),我按您的意见调整。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

enhancementNew feature or requestpriority/important-soon高优先级:近期应安排处理的重要问题

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions