From 9b85417a82e2bf64794e69907c9416a1b9ccd47f Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Mon, 9 Mar 2026 15:50:36 +0800 Subject: [PATCH] fix(copilot): serialize tool output to JSON in ToolMessage for history Fixed tool output serialization in tool_node function to ensure ToolMessage.content is always in JSON format, not Python str() representation. This fixes the issue where conversation history showed tool outputs with single quotes (Python format) instead of standard JSON. Changes: - Added json import to gns3_copilot.py - Modified tool_node() to serialize observation to JSON before creating ToolMessage - Ensures both SSE streaming and history storage use consistent JSON format Root cause: ToolMessage was created with raw dict/list objects, which LangChain converted to Python str() representation when saving to history. Co-Authored-By: YueGuobin --- gns3server/agent/gns3_copilot/agent/gns3_copilot.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gns3server/agent/gns3_copilot/agent/gns3_copilot.py b/gns3server/agent/gns3_copilot/agent/gns3_copilot.py index 91fce3b99..98a874c8a 100644 --- a/gns3server/agent/gns3_copilot/agent/gns3_copilot.py +++ b/gns3server/agent/gns3_copilot/agent/gns3_copilot.py @@ -45,6 +45,7 @@ Copilot Modes: """ # Standard library imports +import json import logging import operator from datetime import datetime @@ -384,6 +385,11 @@ def tool_node(state: dict, config: RunnableConfig | None = None): logger.error("Tool %s failed: %s", tool_name, e, exc_info=True) observation = f"Error: {str(e)}" + # Serialize observation to JSON string if it's not already a string + # This ensures ToolMessage.content is always JSON format, not Python str() + if not isinstance(observation, str): + observation = json.dumps(observation, ensure_ascii=False, indent=2) + # Create ToolMessage with metadata including created_at tool_msg = ToolMessage( content=observation,