Skip to content

Python: [Bug]: Responses-style continuation bypasses history provider isolation #4577

@thomgrand

Description

@thomgrand

Description

What happens

With an agent configured with a history provider that disables loading/storing messages (for example InMemoryHistoryProvider(load_messages=False, store_inputs=False, store_outputs=False)), behavior differs by client:

  • Chat-style client: forgets previous turns (expected)
  • Responses-style client: still remembers previous turns (unexpected)

This also causes usage/token accounting confusion because previous messages are not visible e.g. in OTEL logs, but still influence the model.

Expected behavior

When context providers are configured, they should be the only source of message history unless explicitly overridden by runtime options.

In particular, if a history provider disables load/store, subsequent runs in the same session should not implicitly include prior conversation state.

Found root cause

In agent_framework/_agents.py, Agent._prepare_run_context always forwards session.service_session_id to conversation_id.

For Responses-style clients, that becomes previous_response_id, which reattaches server-side history regardless of history provider policy.

Proposed fix direction

Only forward session.service_session_id implicitly when no history provider is configured (or when explicitly requested), and always honor explicit runtime conversation_id overrides. I have a

Packages

Tested with 1.0.0rc3 and the main branch with hash ded32f3

MWE

See below. The agent is tasked with creating a recipe and recalling the ingredients in a later conversation turn. Since the memory provider discards all messages, this shouldn't be possible. It works however in the responses client in contrast to the chat client.

Code Sample

from agent_framework.openai import OpenAIChatClient, OpenAIResponsesClient
from agent_framework import InMemoryHistoryProvider
import asyncio

async def test_auto_compaction():
    forgetful_provider = InMemoryHistoryProvider(load_messages=False, store_inputs=False, store_context_messages=False, store_outputs=False)
    #agent = OpenAIChatClient().as_agent(context_providers=[forgetful_provider]) # <- This will not remember the history
    agent = OpenAIResponsesClient().as_agent(context_providers=[forgetful_provider]) # <- This will remember the history
    session = agent.create_session()

    print(await agent.run("Hi, just respond with `hi!`", session=session))
    print(await agent.run("Write me lasagna recipe in two paragraphs", session=session))
    print(await agent.run("Please provide an exact bullet list of the ingredients you gave previously. If you don't see it anymore in the conversation, tell me so, don't start making up things.", session=session))
    print(await agent.run("Do you see duplicate messages in the conversation (1:1 copies only)?", session=session))

    return


if __name__ == "__main__":
    from dotenv import load_dotenv
    load_dotenv()

    # Activate if you want to observe the traces on Langfuse
    # from agent_framework.observability import enable_instrumentation
    # from langfuse import get_client
    # langfuse_client = get_client()
    # assert langfuse_client.auth_check(), "Langfuse auth failed"
    # enable_instrumentation(enable_sensitive_data=True)

    asyncio.run(test_auto_compaction())

Error Messages / Stack Traces

# Chat client output:

hi!
For a classic 9x13-inch lasagna (about 6–8 servings) gather: 12 lasagna noodles (or one 12-oz package no-boil noodles), 1 lb (450 g) [...rest of the recipe omitted]  
I don't see any previous ingredient list in this conversation. I won't make one up. If you paste the original text or tell me which recipe or message you mean, I'll provide an exact bullet list.  
No — I don't see any exact 1:1 duplicate messages in this conversation. The system message and the user message are distinct. Would you like me to check a longer chat history or look for near-duplicates (paraphrases)?
# Responses client output:

hi!
For 6–8 servings: 1 lb (450 g) ground beef or a mix of beef and pork, 1 medium onion (finely chopped), 2–3 garlic cloves (minced), 28 oz (800 g) canned crushed tomatoes, [...rest of the recipe omitted]
- 1 lb (450 g) ground beef or a mix of beef and pork
- 1 medium onion (finely chopped)
- 2–3 garlic cloves (minced)
- 28 oz (800 g) canned crushed tomatoes
- 6 oz (170 g) tomato paste
- 1/2 cup (120 ml) red wine (optional)
- 1 tsp sugar
- 1 tsp dried oregano
- 1 tsp dried basil
- salt and pepper to taste
- 2 tbsp olive oil
- 9–12 lasagna noodles (regular or no-boil)
- 15 oz (425 g) ricotta cheese (or cottage cheese)
- 1 large egg
- 1/4 cup grated Parmesan
- 2–3 cups shredded mozzarella plus extra for topping
- Optional béchamel: 3 tbsp butter, 3 tbsp flour, 2 cups milk, pinch of nutmeg
No — I don't see any 1:1 duplicate messages in this conversation.

Package Versions

agent-framework-1.0.0rc3

Python Version

Python 3.12.10

Additional Context

Tested with OpenAI gpt-5-mini

Metadata

Metadata

Labels

bugSomething isn't workingpythonv1.0Features being tracked for the version 1.0 GA

Type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions