Skip to content

fix(graph): add JsonCreator for InterruptionMetadata to support Jackson deserialization#4464

Open
NGshiyu wants to merge 2 commits intoalibaba:mainfrom
NGshiyu:main-jackson
Open

fix(graph): add JsonCreator for InterruptionMetadata to support Jackson deserialization#4464
NGshiyu wants to merge 2 commits intoalibaba:mainfrom
NGshiyu:main-jackson

Conversation

@NGshiyu
Copy link
Copy Markdown
Contributor

@NGshiyu NGshiyu commented Mar 25, 2026

Describe what this PR does / why we need it

When building a graph where a node implements InterruptableAction, if that node is the last one before the end node, the system currently throws an IllegalArgumentException during Jackson deserialization.

This occurs because InterruptionMetadata and its inner class ToolFeedback lack proper Jackson annotations. This PR adds @JsonCreator and @JsonProperty to the relevant constructors to ensure the graph state can be correctly reconstructed from JSON.

java.lang.IllegalArgumentException: Cannot construct instance of `com.alibaba.cloud.ai.graph.action.InterruptionMetadata` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

Does this pull request fix one issue?

NONE

Describe how you did it

  • Added @JsonCreator and @JsonProperty annotations to the constructor of InterruptionMetadata.
  • Added @JsonCreator and @JsonProperty annotations to the ToolFeedback inner class constructor.
  • Ensured collection fields (metadata, toolFeedbacks, etc.) handle null values gracefully during deserialization to prevent NullPointerException.

Describe how to verify it

  1. Create a graph with an InterruptableAction node as the penultimate node (before end).
  2. Trigger the interruption and attempt to serialize/deserialize the graph state.
  3. Verify that the IllegalArgumentException no longer occurs and the state is correctly restored.

@github-actions github-actions bot added the area/graph SAA Grpah module label Mar 25, 2026
@NGshiyu
Copy link
Copy Markdown
Contributor Author

NGshiyu commented Mar 25, 2026

  1. the graph config
StateGraph stateGraph = new StateGraph(keyStrategyFactory)
                    //节点添加
                    .addNode("semantic_understanding", node_async(new SemanticUnderstandingNode(toolCallbackProvider, mcpClientCommonProperties))) // 语义理解节点
                    .addNode("weather_search", new WeatherSearchNode(toolCallbackProvider, mcpClientCommonProperties)) // 天气查询节点
                    ; 

            //定义一个流转的边界路线图
            stateGraph.addEdge(StateGraph.START, "semantic_understanding")
                    .addEdge("semantic_understanding", "weather_search")
                    .addEdge("weather_search", StateGraph.END);
  1. the InterruptableAction Node
public record WeatherSearchNode(org.springframework.ai.tool.ToolCallbackProvider toolCallbackProvider,
                                org.springframework.ai.mcp.client.common.autoconfigure.properties.McpClientCommonProperties mcpClientCommonProperties)
        //implements NodeAction,
implements AsyncNodeAction,
        InterruptableAction {
    private static final Logger logger = LoggerFactory.getLogger(WeatherSearchNode.class);
    private static final String instruction = """
            # Role
            智能天气助手
            
            # Profile
            你擅长调用工具获取实时天气数据,并将信息转化为清晰易读的预报计划。
            
            # Rules
            1. **日期逻辑**:若用户提供日期,查询该日天气;若未提供,默认查询最近 7 天预报。
            2. **信息确认**:提取输入中的城市信息,避免干扰,若缺失城市信息,请先追问。
            3. **输出要求**:数据展示结构化(温度、状况),并根据天气适当给出穿衣或出行建议。
            """;

    @Override
    public CompletableFuture<Map<String, Object>> apply(OverAllState state) {
        // 创建人工介入Hook - 所有工具调用都需要用户确认
        HumanInTheLoopHook humanInTheLoopHook = HumanInTheLoopHook.builder()
                // === 餐品信息查询 ===
                .approvalOn("maps_weather", ToolConfig.builder()
                        .description("根据城市名称或者标准adcode查询指定城市的天气")
                        .build())
                .build();
       //............................................................................
        try {
            Optional<NodeOutput> nodeOutput = agent.invokeAndGetOutput(state.value(TravelGuideGraphConfig.SEMANTIC_ANSWER).get().toString(),
                    config);
            return CompletableFuture.completedFuture(Map.of(TravelGuideGraphConfig.WEATHER_ANSWER, nodeOutput));
            //return Map.of(TravelGuideGraphConfig.WEATHER_ANSWER, nodeOutput);
        } catch (GraphRunnerException e) {
            throw new RuntimeException(e);
        }
    }

@chickenlj chickenlj requested review from chickenlj and Copilot March 27, 2026 03:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Jackson constructor annotations to InterruptionMetadata (and its ToolFeedback) so graph state containing InterruptableAction nodes can be deserialized without IllegalArgumentException.

Changes:

  • Added @JsonCreator / @JsonProperty constructor for InterruptionMetadata.
  • Added @JsonCreator / @JsonProperty constructor for ToolFeedback.
  • Added null-safe initialization for collection fields during deserialization.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…i/graph/action/InterruptionMetadata.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/graph SAA Grpah module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants