Skip to content

Python: Add AgentExecutorResponse.with_text() to preserve conversation history through custom executors#5255

Open
kartikmadan11 wants to merge 1 commit intomicrosoft:mainfrom
kartikmadan11:fix/5246-executor-clears-conversation-history
Open

Python: Add AgentExecutorResponse.with_text() to preserve conversation history through custom executors#5255
kartikmadan11 wants to merge 1 commit intomicrosoft:mainfrom
kartikmadan11:fix/5246-executor-clears-conversation-history

Conversation

@kartikmadan11
Copy link
Copy Markdown

Motivation and Context

When a custom @executor sits between two AgentExecutor nodes in a workflow chain, it receives an AgentExecutorResponse (which carries the full conversation) but typically sends a plain str downstream. This causes the next AgentExecutor.from_str handler to start fresh with only that string, losing all prior conversation turns.

The issue reporter demonstrated this with a simple upper-case executor placed between four agents — the final agent could only see its own immediate input instead of the full history from all previous agents.

Fixes #5246

Description

The root cause is that custom executors have no convenient way to transform the agent's output text while keeping the AgentExecutorResponse wrapper intact. Sending a plain str routes to from_str, which discards the conversation chain.

This adds a with_text(text) method to AgentExecutorResponse that creates a new response with replaced text, preserving the prior conversation in full_conversation. This way the response type stays AgentExecutorResponse and routes to from_response instead, which properly feeds the full history into the next agent's cache.

Three regression tests are included:

  • End-to-end workflow test mirroring the issue's reproduction (agent1 → agent2 → upper_case → agent3 → capture)
  • Immutability check (original response is not mutated)
  • Multi-message agent turn stripping (tool call chains are handled correctly)

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

@kartikmadan11
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copy link
Copy Markdown
Contributor

@moonbox3 moonbox3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. The helper itself looks correct and I'm supportive of merging it. One thing I'd like to see added before we do that, though:

The underlying issue in #5246 looks fundamentally like a discoverability problem. The typed-dispatch routing between from_str / from_response / from_message is working as designed (see _agent_executor.py:156-188), but a user writing a custom executor with output=str has no way to know they're silently dropping full_conversation. Adding with_text() gives them an escape hatch, but only if they already know it exists - the original reporter's code would have looked identical without this PR, and they'd hit the same wall.

Could we also:

  1. Add a docstring note on AgentExecutor.from_str (and on the @executor decorator / tutorial docs for custom executors between agents) that explicitly calls out: "if the upstream executor received an AgentExecutorResponse, emitting a plain str will reset the conversation. Use AgentExecutorResponse.with_text(...) to preserve it."
  2. Consider a logger.warning in from_str when the cache is empty and the incoming text looks like it came from an agent turn - or at minimum when the sending executor's declared input type is AgentExecutorResponse. (Optional; docs alone may be enough.)

Without the docs change the helper is hard to find, and users will keep filing this same bug.

@moonbox3
Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework/_workflows
   _agent_executor.py1981691%165, 189, 230, 256–257, 337–339, 341, 351–352, 399, 471–472, 544, 550
TOTAL27551319988% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
5573 20 💤 0 ❌ 0 🔥 1m 25s ⏱️

…y through custom executors

Fixes microsoft#5246

When a custom @executor transforms agent output and sends a plain str,
the downstream AgentExecutor.from_str handler loses the full conversation
context. This adds a with_text() helper that creates a new
AgentExecutorResponse with replaced text while preserving the prior
conversation chain, so AgentExecutor.from_response is invoked instead.

- Add with_text(text) method to AgentExecutorResponse dataclass
- Add 3 regression tests in test_full_conversation.py
@kartikmadan11 kartikmadan11 force-pushed the fix/5246-executor-clears-conversation-history branch from 4b1de95 to df06ee7 Compare April 15, 2026 11:57
@kartikmadan11
Copy link
Copy Markdown
Author

kartikmadan11 commented Apr 15, 2026

Thanks for the review! Updated with:

  • Warning: docstrings on both from_str and @executor
  • logger.warning in from_str

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Executor clears up previous agents messages from workflow context

2 participants