@@ -143,6 +143,8 @@ class ChatRequest:
143143 cancel_token : CancelToken = None
144144 # NEW: Add context for rule evaluation
145145 rule_context : Optional [RuleContext ] = None
146+ # Internal conversation id for persistence backends
147+ conversation_id : str = None
146148
147149@dataclass
148150class ResponseStreamData :
@@ -312,6 +314,12 @@ def message_id(self) -> str:
312314
313315 def stream (self , data : ResponseStreamData , finish : bool = False ) -> None :
314316 raise NotImplementedError
317+
318+ def append_tool_calls (self , tool_calls : list [dict ] | None ) -> None :
319+ return None
320+
321+ def append_history_message (self , message : dict ) -> None :
322+ return None
315323
316324 def finish (self ) -> None :
317325 raise NotImplementedError
@@ -636,6 +644,7 @@ async def _tool_call_loop(tool_call_rounds: list):
636644
637645 for choice in tool_response ['choices' ]:
638646 message = choice ['message' ]
647+ response .append_tool_calls (message .get ('tool_calls' ))
639648 # Some models use 'reasoning', some use 'reasoning_content'
640649 raw_reasoning = message .get ('reasoning' ) or message .get ('reasoning_content' ) or ''
641650
@@ -687,6 +696,12 @@ async def _tool_call_loop(tool_call_rounds: list):
687696 args = tool_call ['function' ]['arguments' ]
688697 else :
689698 args = fuzzy_json_loads (tool_call ['function' ]['arguments' ])
699+
700+ # Persist tool execution START (initial record).
701+ if request .conversation_id :
702+ request .host .history_persistence .log_tool_execution (
703+ tool_call ['id' ], request .conversation_id , tool_name , args , ""
704+ )
690705
691706 tool_properties = tool_to_call .schema ["function" ]["parameters" ]["properties" ]
692707 if type (args ) is str :
@@ -713,13 +728,25 @@ async def _tool_call_loop(tool_call_rounds: list):
713728 return
714729
715730 tool_call_response = await tool_to_call .handle_tool_call (request , response , tool_context , args )
731+
732+ # Persist tool execution result.
733+ if request .conversation_id :
734+ request .host .history_persistence .log_tool_execution (
735+ tool_call ['id' ], request .conversation_id , tool_name , args , str (tool_call_response )
736+ )
737+ # Also log the tool message itself
738+ msg_id = str (uuid .uuid4 ())
739+ request .host .history_persistence .add_message (
740+ msg_id , request .conversation_id , "tool" , str (tool_call_response ), tool_call_id = tool_call ['id' ]
741+ )
716742
717743 function_call_result_message = {
718744 "role" : "tool" ,
719745 "content" : str (tool_call_response ),
720746 "tool_call_id" : tool_call ['id' ]
721747 }
722748
749+ response .append_history_message (function_call_result_message )
723750 messages .append (function_call_result_message )
724751
725752 if had_tool_call :
@@ -915,6 +942,9 @@ def register_telemetry_listener(self, listener: TelemetryListener) -> None:
915942 def register_toolset (self , toolset : Toolset ) -> None :
916943 raise NotImplementedError
917944
945+ def register_history_persistence_backend (self , backend ) -> None :
946+ raise NotImplementedError
947+
918948 @property
919949 def nbi_config (self ) -> NBIConfig :
920950 raise NotImplementedError
@@ -971,6 +1001,10 @@ def get_skill_manager(self):
9711001 def websocket_connector (self ) -> ThreadSafeWebSocketConnector :
9721002 raise NotImplementedError
9731003
1004+ @property
1005+ def history_persistence (self ) -> Any :
1006+ return NotImplementedError
1007+
9741008
9751009class NotebookIntelligenceExtension :
9761010 @property
0 commit comments