{"record":{"id":"6ac2e732a7249b29","repo":"microsoft/semantic-kernel","slug":"cannot-reduce-chat-history-since-the-thread-is-no-6ac2e7","errorCode":null,"errorMessage":"Cannot reduce chat history, since the thread is not currently active.","messagePattern":"Cannot reduce chat history, since the thread is not currently active\\.","errorType":"exception","errorClass":"AgentThreadOperationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/open_ai/openai_responses_agent.py","lineNumber":246,"sourceCode":"        \"\"\"Retrieve the current chat history.\"\"\"\n        if self._is_deleted:\n            raise AgentThreadOperationException(\"Cannot retrieve chat history, since the thread has been deleted.\")\n        if self.store_enabled and self.response_id is not None:\n            async for message in ResponsesAgentThreadActions.get_messages(\n                self._client,\n                self.response_id,\n                limit=limit,\n                sort_order=sort_order,\n            ):\n                yield message\n        else:\n            for message in self._chat_history.messages:\n                yield message\n\n    async def reduce(self) -> ChatHistory | None:\n        \"\"\"Reduce the chat history to a smaller size.\"\"\"\n        if self._id is None:\n            raise AgentThreadOperationException(\"Cannot reduce chat history, since the thread is not currently active.\")\n        if not isinstance(self._chat_history, ChatHistoryReducer):\n            return None\n        return await self._chat_history.reduce()\n\n\n# endregion\n\n\n@experimental\n@register_agent_type(\"openai_responses\")\nclass OpenAIResponsesAgent(DeclarativeSpecMixin, Agent):\n    \"\"\"OpenAI Responses Agent class.\n\n    Provides the ability to interact with OpenAI's Responses API.\n\n    NOTE: The Responses Agent does not currently support AgentGroupChat.\n    \"\"\"\n","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/open_ai/openai_responses_agent.py#L228-L264","documentation":"Raised by ResponsesAgentThread.reduce() when self._id is None. reduce() delegates to the underlying ChatHistoryReducer, but only when the thread has a server-side identity (_id). A thread that was never persisted/activated (store disabled, or never created server-side) has no _id, so reduction is refused. Without an active thread the reducer has no authoritative history to compact.","triggerScenarios":"Calling await thread.reduce() on a ResponsesAgentThread that has store_enabled=False (pure local history) or whose _id was never assigned because no message exchange has occurred yet. The reducer path requires an active, identified thread.","commonSituations":"Using a ChatHistoryReducer-based thread in local (non-store) mode and expecting reduce() to work the same as server-backed mode. Also triggered when reduce() is called before the first invoke()/get_response() that would assign a response_id and establish the thread.","solutions":["Ensure the thread is active: run at least one invoke()/get_response() so the thread obtains an id before calling reduce().","Confirm store_enabled=True if you want server-backed reduction; for local-only history manage reduction yourself against thread._chat_history.","Guard reduce() with a check of thread.id before calling it."],"exampleFix":"// before\nthread = ResponsesAgentThread(client=client, enable_store=False)\nawait thread.reduce()  # raises, _id is None\n\n// after\nthread = ResponsesAgentThread(client=client, enable_store=True)\nawait agent.get_response(messages=\"hi\", thread=thread)\nreduced = await thread.reduce()","handlingStrategy":"validation","validationCode":"# Only reduce when the thread has an id (is active)\nif thread.id is not None:\n    reduced = await thread.reduce()\nelse:\n    reduced = None","typeGuard":"async def thread_is_active(thread) -> bool:\n    return thread.id is not None","tryCatchPattern":"from semantic_kernel.exceptions.agent_exceptions import AgentThreadOperationException\ntry:\n    reduced = await thread.reduce()\nexcept AgentThreadOperationException:\n    reduced = None  # thread not active; skip reduction","preventionTips":["Run at least one invoke()/get_response() before reduce() so the thread obtains an id.","Use store_enabled=True when you want server-backed reduction.","Guard reduce() with a thread.id is not None check."],"tags":["agent-thread","history-reduction","responses-agent"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}