Python: ADR: Unifying Context Management with ContextMiddleware (Python)#3609
Merged
eavanvalkenburg merged 19 commits intomicrosoft:mainfrom Feb 10, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new ADR proposing a unified ContextMiddleware abstraction for Python to replace ContextProvider, ChatMessageStore, and AgentThread, using an onion/wrapper middleware pipeline pattern.
Changes:
- Introduces a proposed
ContextMiddleware+SessionContext+ pipeline design for composable context engineering. - Describes a
StorageContextMiddlewareapproach for loading/storing conversation history and optional auditing. - Outlines migration impact and a phased implementation/testing plan.
westey-m
reviewed
Feb 3, 2026
westey-m
reviewed
Feb 3, 2026
westey-m
reviewed
Feb 3, 2026
victordibia
reviewed
Feb 4, 2026
e005fc3 to
761f2bf
Compare
ae59218 to
fed0e4a
Compare
…dback - Add Option 3: ContextHooks with before_run/after_run pattern - Add detailed pros/cons for both wrapper and hooks approaches - Add Open Discussion section on context compaction strategies - Clarify response_messages is read-only (use AgentMiddleware for modifications) - Add SimpleRAG examples showing input-only filtering - Clarify default storage only added when NO middleware configured - Add RAGWithBuffer examples for self-managed history - Rename hook methods to before_run/after_run
- Add class hierarchy clarification for both options - Merge detailed design sections (side-by-side comparison) - Move detailed design before decision outcome - Move compaction discussion after decision - Add .NET implementation comparison (feature equivalence) - Update .NET method names to match actual implementation - Rename hook methods to before_run/after_run - Fix storage context table for injected context
- Note that class and method names are open for discussion - Add alternative method naming options table - Include invoking/invoked as option matching current Python and .NET
…filtering - Remove smart mode for load_messages (now explicit bool, default True) - Add attribution marker in additional_properties for message filtering - Update validation to warn on multiple or zero storage loaders - Add note about ChatReducer naming from .NET - Note that attribution should not be propagated to storage
- Option A: Instances in Session (current proposal) - Option B: Instances in Agent, State in Session - B1: Simple dict state with optional return - B2: SessionState object with mutable wrapper - Updated examples to use Hooks pattern (before_run/after_run) - Added open discussion on hook factories in Option B model
Decision outcomes: - Option 3 (Hooks pattern) with ContextPlugin class name - Methods: before_run/after_run - Option B1: Instances in Agent, State in Session (simple dict) - Whole state dict passed to plugins (mutable, no return needed) - Added trust note: plugins reason over messages, so they're trusted by default Status changed from proposed to accepted.
Signature now: before_run(agent, session, context, state)
Simpler design: agent stores Sequence[ContextPlugin] and calls before_run/after_run directly in the run method.
2bc78ee to
1372be3
Compare
…ports - Add to_dict()/from_dict() on AgentSession with 'type' discriminator - Present serialization as Option A (direct) vs Option B (through agent) - Rewrite ownership section as 2x2 matrix (orthogonal decision) - Move Instance Ownership Options before Decision Outcome - Fix get_session to use service_session_id, split from create_session - Add decorator-based provider convenience API (@before_run/@after_run) - Add _ prefix naming strategy for all PR1 types (core + external) - Constructor compatibility table for existing providers - Add load_messages=False skip logic to all agent run loops - Clarify abstract vs non-abstract in execution pattern samples - Update auto-provision: trigger on conversation_id or store=True - Document root package exports (ContextProvider, HistoryProvider, etc.) - Rename section heading to 'Key Design Considerations'
victordibia
approved these changes
Feb 9, 2026
dmytrostruk
approved these changes
Feb 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This ADR proposes unifying \ContextProvider, \ChatMessageStore, and \AgentThread\ into a single \ContextMiddleware\ concept for the Python SDK.
Problem
Currently, developers doing 'Context Engineering' must understand multiple abstractions:
Proposed Solution
A unified \ContextMiddleware\ using the onion/wrapper pattern (like existing \AgentMiddleware):
\\python
class RAGMiddleware(ContextMiddleware):
async def process(self, context: SessionContext, next) -> None:
# Pre-processing: add context
docs = await self.retrieve_documents(context.input_messages[-1].text)
context.add_messages(self.source_id, [ChatMessage.system(f'Context: {docs}')])
agent = ChatAgent(
chat_client=client,
context_middleware=[
InMemoryStorageMiddleware('memory'),
RAGMiddleware('rag'),
]
)
\\
Key Decisions
Migration Impact
See the full ADR in \docs/decisions/00XX-python-context-middleware.md\ for detailed design, code examples, and implementation workplan.
Related Issues
This ADR addresses the following issues: