Skip to content

[BUG] AgentTool模式,子agent的skill如果关联了mcp工具,mcp工具无法调用 #4656

Open

Description

@zhongzejia

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

子Agent的skill关联了mcp工具,在AgentLlmNode类的buildChatClientRequestSpec方法中将工具放到了config,config.context().put(RunnableConfig.DYNAMIC_TOOL_CALLBACKS_METADATA_KEY, modelRequest.getDynamicToolCallbacks());
但在AgentToolNode类的resolveFromConfigMetadata方法中获取不到工具,config.context().get(RunnableConfig.DYNAMIC_TOOL_CALLBACKS_METADATA_KEY)取到了空,此类工具最终调用报错:No ToolCallback found for tool name: xxxx

Expected Behavior

No response

Steps To Reproduce

No response

Environment

Spring AI Alibaba version(s):

Debug logs

No response

Anything else?

No response

Activity

  1. i-zoufeng commented on May 26, 2026

    @i-zoufeng
    Contributor

    我尝试复现了一下,写了 4 个最小测试覆盖这条链路(AgentLlmNode.buildChatClientRequestSpec put → AgentToolNode.resolveFromConfigMetadata get),都没能复现:

    子 agent 直接 invoke(控制组):MCP 工具正常调用 ✅
    子 agent 通过 AgentTool.create() 包装、父 agent 调用,skill 用 SkillsAgentHook.groupedTools 注册:✅
    同上,但 skill 用 allowed_tools + ToolCallbackResolver 注册:✅
    父 agent 自身有 skill,先 read_skill → 调子 agent(AgentTool)→ 再调自己的 MCP 工具:✅
    静态看代码,RunnableConfig.Builder 拷贝 context 是按条目复制的,GraphRunnerContext.addCheckpoint 替换 this.config 时也走 builder,所以 put 进去的工具会跟着被复制到下一节点能看到的 config 里。clearContext() 只在跨 agent/subgraph 边界(AgentTool.executeAgent、SubCompiledGraphNodeAction.apply、ReactAgent.AgentToSubCompiledGraphNodeAdapter、GraphRunnerContext.initializeFromResume)发生,子 agent 内部 LlmNode→ToolNode 之间不会清。

    麻烦能否提供一份最小复现?尤其想知道:

    子 agent 是怎么挂到父 agent 的?AgentTool.create() 包装?还是 subAgents(...) / asNode()(走 SubGraph 路径)?
    skill 里的 MCP 工具是怎么注册的?SkillsAgentHook.groupedTools / allowed_tools + ToolCallbackResolver / 还是别的方式?
    是否配了 CheckpointSaver(特别是 Redis/Mongo/Postgres 这种会序列化的,ToolCallback 不可序列化可能是 root cause)?
    是否走流式接口(stream* / streamMessages)?
    用的是哪个具体的 MCP client / ToolCallback 实现?

  2. zhongzejia commented on May 26, 2026

    @zhongzejia
    Author

    1、子agent通过 ReactAgent.builder().tools(子agent列表) 挂到父agent,
    2、子agent中的工具使用渐进式工具披露挂到skill,
    Map<String, List> groupedTools = xxxx;
    SkillsAgentHook hook = SkillsAgentHook.builder()
    .skillRegistry(registry)
    .groupedTools(groupedTools)
    .build();
    3、不涉及CheckpointSaver
    4、走流式接口
    5、使用ToolCallback

    问题应该出在RunalbeConfig,多Agent的RunableConfig,父Agent跟子Agent的RunableConfig不是同一个,动态工具可能挂到父Agent的RunableConfig了

    单agent场景,resolveFromConfigMetadata方法里,config.context().get(RunnableConfig.DYNAMIC_TOOL_CALLBACKS_METADATA_KEY)可以获取到动态工具
    多agent场景,则获取到空

  3. March-77 commented on Jul 24, 2026

    @March-77
    Contributor

    已按补充信息在当前 main 上补齐并验证精确链路:父 ReactAgent 走 stream → AgentTool.create(subAgent) → 子 agent 使用 SkillsAgentHook.groupedTools → read_skill → 动态 ToolCallback。该场景当前可以正常执行,未发现需要修改生产代码的 RunnableConfig 丢失问题。已提交确定性回归测试 PR #4841,防止后续在流式多 Agent 边界上回归。

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions