microsoft/semantic-kernel · error · AgentThreadOperationException

Cannot reduce chat history, since the thread is not currentl

Error message

Cannot reduce chat history, since the thread is not currently active.

What it means

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.

Source

Thrown at python/semantic_kernel/agents/open_ai/openai_responses_agent.py:246

        """Retrieve the current chat history."""
        if self._is_deleted:
            raise AgentThreadOperationException("Cannot retrieve chat history, since the thread has been deleted.")
        if self.store_enabled and self.response_id is not None:
            async for message in ResponsesAgentThreadActions.get_messages(
                self._client,
                self.response_id,
                limit=limit,
                sort_order=sort_order,
            ):
                yield message
        else:
            for message in self._chat_history.messages:
                yield message

    async def reduce(self) -> ChatHistory | None:
        """Reduce the chat history to a smaller size."""
        if self._id is None:
            raise AgentThreadOperationException("Cannot reduce chat history, since the thread is not currently active.")
        if not isinstance(self._chat_history, ChatHistoryReducer):
            return None
        return await self._chat_history.reduce()


# endregion


@experimental
@register_agent_type("openai_responses")
class OpenAIResponsesAgent(DeclarativeSpecMixin, Agent):
    """OpenAI Responses Agent class.

    Provides the ability to interact with OpenAI's Responses API.

    NOTE: The Responses Agent does not currently support AgentGroupChat.
    """

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Ensure the thread is active: run at least one invoke()/get_response() so the thread obtains an id before calling reduce().
  2. Confirm store_enabled=True if you want server-backed reduction; for local-only history manage reduction yourself against thread._chat_history.
  3. Guard reduce() with a check of thread.id before calling it.

Example fix

// before
thread = ResponsesAgentThread(client=client, enable_store=False)
await thread.reduce()  # raises, _id is None

// after
thread = ResponsesAgentThread(client=client, enable_store=True)
await agent.get_response(messages="hi", thread=thread)
reduced = await thread.reduce()
Defensive patterns

Strategy: validation

Validate before calling

# Only reduce when the thread has an id (is active)
if thread.id is not None:
    reduced = await thread.reduce()
else:
    reduced = None

Type guard

async def thread_is_active(thread) -> bool:
    return thread.id is not None

Try / catch

from semantic_kernel.exceptions.agent_exceptions import AgentThreadOperationException
try:
    reduced = await thread.reduce()
except AgentThreadOperationException:
    reduced = None  # thread not active; skip reduction

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/6ac2e732a7249b29. Report an issue: GitHub.