From 45ae410f05177eb41ef996bd71d0eaa657c5f2ee Mon Sep 17 00:00:00 2001 From: Kim <150593189+KimGLee@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:12:37 +0800 Subject: [PATCH 1/3] fix(agent): do not persist runtime context metadata in session history --- nanobot/agent/loop.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nanobot/agent/loop.py b/nanobot/agent/loop.py index 3e513cb..eb34b31 100644 --- a/nanobot/agent/loop.py +++ b/nanobot/agent/loop.py @@ -467,6 +467,14 @@ class AgentLoop: content = entry["content"] if len(content) > self._TOOL_RESULT_MAX_CHARS: entry["content"] = content[:self._TOOL_RESULT_MAX_CHARS] + "\n... (truncated)" + if ( + entry.get("role") == "user" + and isinstance(entry.get("content"), str) + and entry["content"].startswith(ContextBuilder._RUNTIME_CONTEXT_TAG) + ): + # Runtime metadata is injected per-turn for model context only; do not persist it + # into long-lived session history to avoid semantic drift and repetitive replies. + continue if entry.get("role") == "user" and isinstance(entry.get("content"), list): entry["content"] = [ {"type": "text", "text": "[image]"} if ( From 286e67ddef6cafca737a3edfbe9373a77da0f9ab Mon Sep 17 00:00:00 2001 From: Kim <150593189+KimGLee@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:21:44 +0800 Subject: [PATCH 2/3] style(agent): remove inline comment in runtime-context history filter --- nanobot/agent/loop.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nanobot/agent/loop.py b/nanobot/agent/loop.py index eb34b31..7ae2634 100644 --- a/nanobot/agent/loop.py +++ b/nanobot/agent/loop.py @@ -472,8 +472,6 @@ class AgentLoop: and isinstance(entry.get("content"), str) and entry["content"].startswith(ContextBuilder._RUNTIME_CONTEXT_TAG) ): - # Runtime metadata is injected per-turn for model context only; do not persist it - # into long-lived session history to avoid semantic drift and repetitive replies. continue if entry.get("role") == "user" and isinstance(entry.get("content"), list): entry["content"] = [ From bc558d0592c144b38a0f8b18d8c8270d2addca60 Mon Sep 17 00:00:00 2001 From: Re-bin Date: Fri, 27 Feb 2026 10:07:22 +0000 Subject: [PATCH 3/3] refactor: merge user-role branches in _save_turn --- nanobot/agent/loop.py | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/nanobot/agent/loop.py b/nanobot/agent/loop.py index 69c2916..6fe37e9 100644 --- a/nanobot/agent/loop.py +++ b/nanobot/agent/loop.py @@ -444,24 +444,19 @@ class AgentLoop: from datetime import datetime for m in messages[skip:]: entry = {k: v for k, v in m.items() if k != "reasoning_content"} - if entry.get("role") == "tool" and isinstance(entry.get("content"), str): - content = entry["content"] - if len(content) > self._TOOL_RESULT_MAX_CHARS: - entry["content"] = content[:self._TOOL_RESULT_MAX_CHARS] + "\n... (truncated)" - if ( - entry.get("role") == "user" - and isinstance(entry.get("content"), str) - and entry["content"].startswith(ContextBuilder._RUNTIME_CONTEXT_TAG) - ): - continue - if entry.get("role") == "user" and isinstance(entry.get("content"), list): - entry["content"] = [ - {"type": "text", "text": "[image]"} if ( - c.get("type") == "image_url" - and c.get("image_url", {}).get("url", "").startswith("data:image/") - ) else c - for c in entry["content"] - ] + role, content = entry.get("role"), entry.get("content") + if role == "tool" and isinstance(content, str) and len(content) > self._TOOL_RESULT_MAX_CHARS: + entry["content"] = content[:self._TOOL_RESULT_MAX_CHARS] + "\n... (truncated)" + elif role == "user": + if isinstance(content, str) and content.startswith(ContextBuilder._RUNTIME_CONTEXT_TAG): + continue + if isinstance(content, list): + entry["content"] = [ + {"type": "text", "text": "[image]"} if ( + c.get("type") == "image_url" + and c.get("image_url", {}).get("url", "").startswith("data:image/") + ) else c for c in content + ] entry.setdefault("timestamp", datetime.now().isoformat()) session.messages.append(entry) session.updated_at = datetime.now()