Python: [Bug] No API to control Session Memory injection on HITL retry — causes quadratic token growth in multi-turn agent workflows
@eavanvalkenburg is already working on this.
Since Sep 18, 2026.
Assessment
This issue has not been assessed yet.
Description
Description
When a Human-in-the-Loop (HITL) approval cycle triggers an agent re-invocation, the framework automatically injects the full prior conversation via InMemoryHistoryProvider (Session Memory). There is currently no API or hook to control, trim, or replace what goes into that session history before it is appended to the next invocation's context.
This forces developers who need custom retry context construction (e.g. a minimal "Retry Packet") to pass original.full_conversation manually as well — doubling the context. Over multiple HITL cycles the duplication compounds quadratically, leading to severe token bloat and degraded agent reasoning.
Environment
Framework: Microsoft Agent Framework - 1.8.0
Memory Provider: InMemoryHistoryProvider
Pattern: Multi-turn HITL agent with on_user_response retry construction
Trigger: Every AwaitingUserInput → human approval → agent re-invocation
The framework provides no mechanism to:
1.Inspect what Session Memory will inject before constructing a retry payload
2.Suppress or replace the Session Memory injection for a specific invocation
3.Distinguish framework-managed history from developer-managed retry context
Replacing the full conversation in the retry packet with only the user response will cause the next agent invocation to lose the context established by previous invocations.
Code Sample
@response_handler
async def on_user_response(
self,
original: AgentExecutorResponse,
user_response: AgentRequestInfoResponse,
ctx: WorkflowContext,
) -> None:
prior_msgs = list(original.full_conversation or [])
new_msgs = list(user_response.messages or [])
if not new_msgs:
# Empty messages = bare AgentRequestInfoResponse.approve() sent by the
# durable activity. The agent needs to see "Y" in history to know it
# should proceed with the MCP call — mirrors run_pipeline_step behaviour:
# AgentRequestInfoResponse.from_strings(["Y"]) for pre-MCP approve.
new_msgs = [Message(role="user", contents=["Y"])]
_log(f" [awaiting_gate:{self.id}] bare approval — injecting 'Y' so agent proceeds with MCP call")
retry_msgs = prior_msgs + new_msgs
retry = AgentExecutorRequest(messages=retry_msgs, should_respond=True)
_log(f" [awaiting_gate:{self.id}] user responded — retrying upstream agent")
await ctx.send_message(retry, target_id=self._upstream_id)
Error Messages / Stack Traces
Package Versions
agent_framework_core-1.8.0.
Python Version
No response
Additional Context
No response
- Dominant language
- Python
- Stars
- 13.6k
- Forks
- 2.3k
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 342
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/agent-framework
-
python triage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
microsoft/agent-framework#8523 · 1 comment ·
-
.NET compaction documentation
Difficulty 1/5 Under an hour Newbie friendliness 82/100
microsoft/agent-framework#4629 · 1 comment ·
-
harness python reproduced
microsoft/agent-framework#8567 · 2 comments · 1 assignee ·
-
.NET agents reproduced
microsoft/agent-framework#8566 · 1 comment · 1 assignee ·
-
.NET agents python
microsoft/agent-framework#8562 · 1 assignee ·
All issues in microsoft/agent-framework
Similar issues
-
documentation help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
simonw/sqlite-utils#872 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100