Visitar URL original
Python: [Bug]: Agent answers using stale history despite fresh_context=True with FileHistoryProvider · Issue #10286 · microsoft/agent-framework · GitHub
Skip to content

Python: [Bug]: Agent answers using stale history despite fresh_context=True with FileHistoryProvider #10286

Open

Description

@master1018

Observed Behavior

With fresh_context=True, the agent still used the previous iteration’s quote when running with FileHistoryProvider. I was using a purchasing agent to calculate the total for two boxes of paper, then recalculate it after the supplier’s CSV price changed from $40 to $25 per box. I enabled fresh context and disabled progress injection so the second iteration would start without the earlier quote. The CSV was confirmed to contain $25 before the second model call, but the model’s input still included the previous $40 tool result.

Expected Behavior

With fresh_context=True and inject_progress=False, the second iteration should receive the original task and the pre-loop conversation, excluding the first iteration’s tool results and answers. For this task, it should read the updated CSV price of $25 per box and return 50 for two boxes.

Steps to Reproduce

  1. Config a LLM model, here I was using deepseek-v4.1-flash
  2. Run the python code I provided.

Minimal Reproduction

import asyncio
import os
from pathlib import Path
from tempfile import TemporaryDirectory
from agent_framework import Agent, FileHistoryProvider, tool
from agent_framework._harness._loop import AgentLoopMiddleware
from agent_framework.openai import OpenAIChatCompletionClient

async def main():
    with TemporaryDirectory(prefix="paper-quotes-") as directory:
        quote_file = Path(directory) / "quote.csv"
        quote_file.write_text("item,price_per_box\npaper,40\n")

        @tool
        def read_quote() -> str:
            """Read the current supplier price per box of paper."""
            return quote_file.read_text()

        def next_quote(**kwargs):
            quote_file.write_text("item,price_per_box\npaper,25\n")
            return "Calculate the total for two boxes."

        agent = Agent(
            client=OpenAIChatCompletionClient(api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com/v1", model="deepseek-flash"),
            instructions="Calculate the purchase total. Reply with only the numeric total, without a currency symbol.",
            tools=[read_quote],
            context_providers=[FileHistoryProvider(Path(directory) / "history")],
            middleware=[AgentLoopMiddleware(
                lambda iteration, **kwargs: iteration < 2,
                next_message=next_quote, fresh_context=True, inject_progress=False,
                return_final_only=True,
            )],
            default_options={"extra_body": {"thinking": {"type": "disabled"}}},
        )
        result = await agent.run("Calculate the total for two boxes.", session=agent.create_session())
        print(result.text)
        assert float(result.text.strip()) == 50, "The fresh pass should read the new $25 quote: 2 x 25 = $50."

asyncio.run(main())

Error Messages and Stack Traces

Traceback (most recent call last):
  File "/tmp/unified-context-audit/microsoft-agent-framework/investigation/fresh-loop-file-history/main.py", line 39, in <module>
    asyncio.run(main())
  File "/tmp/unified-context-audit/microsoft-agent-framework/conda-env/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/tmp/unified-context-audit/microsoft-agent-framework/conda-env/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/unified-context-audit/microsoft-agent-framework/conda-env/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/tmp/unified-context-audit/microsoft-agent-framework/investigation/fresh-loop-file-history/main.py", line 37, in main
    assert float(result.text.strip()) == 50, "The fresh pass should read the new $25 quote: 2 x 25 = $50."
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: The fresh pass should read the new $25 quote: 2 x 25 = $50.

Package Versions

agent-framework-core: 1.25.0, agent-framework-openai: 1.18.1

Python Version

Python 3.11.15

Operating System

Linux

Regression

Unknown

Additional Context

No response

Acknowledgements

  • I searched existing issues and did not find a duplicate.
  • I personally verified this behavior and the reproduction details are authentic.
  • I will wait for explicit maintainer agreement before starting implementation of a non-trivial change.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Nov 12, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    harness[Issues, PRs], Target: harness-level items
    on Nov 12, 2026
  3. github-actions commented on Nov 12, 2026

    @github-actions
    Contributor

    Reproduced offline (no live model) on the current checkout: run.

    A recording fake client with FileHistoryProvider + AgentLoopMiddleware(fresh_context=True, inject_progress=False) received [user:task, assistant:ANSWER-1, user:task, user:again] on iteration 2, so iteration 1's answer leaks. With the default in-memory history the second call correctly receives [user:task, user:again].

    Likely cause from the source: fresh_context snapshots and restores only session.state and service_session_id (_harness/_loop.py). FileHistoryProvider keeps messages in an external append-only file keyed by session id, so the restore does not rewind it.

    Support boundary: direct support. The fresh_context docstring and python/packages/core/AGENTS.md say the local transcript is reset between iterations. Known-good version and fix: unknown. Your tool-call/CSV scenario was not run; the test only checks the model input. Priority and fix design are for maintainers. Routed to the harness owner.

    Generated by Issue Routing for #10286 · copilot · auto · ~53 AIC · ⌖ ~1 AIC · ⊞ 5.2K · ◷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

harness[Issues, PRs], Target: harness-level itemspythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowtriageUsage: [Issues], Target: All issues that still need to be triaged

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions