Skip to content

Commit 09f59b2

Browse files
dmytrostrukCopilot
andauthored
Python: [BREAKING] Renamed AgentRunContext to AgentContext (microsoft#3714)
* Renamed AgentRunContext to AgentContext * Update python/packages/core/AGENTS.md Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent c609b14 commit 09f59b2

18 files changed

+219
-319
lines changed

python/packages/core/AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ agent_framework/
5555
- **`AgentMiddleware`** - Intercepts agent `run()` calls
5656
- **`ChatMiddleware`** - Intercepts chat client `get_response()` calls
5757
- **`FunctionMiddleware`** - Intercepts function/tool invocations
58-
- **`AgentRunContext`** / **`ChatContext`** / **`FunctionInvocationContext`** - Context objects passed through middleware
58+
- **`AgentContext`** / **`ChatContext`** / **`FunctionInvocationContext`** - Context objects passed through middleware
5959

6060
### Threads (`_threads.py`)
6161

@@ -114,10 +114,10 @@ agent = OpenAIChatClient().as_agent(
114114
### Middleware Pipeline
115115

116116
```python
117-
from agent_framework import ChatAgent, AgentMiddleware, AgentRunContext
117+
from agent_framework import ChatAgent, AgentMiddleware, AgentContext
118118

119119
class LoggingMiddleware(AgentMiddleware):
120-
async def invoke(self, context: AgentRunContext, next) -> AgentResponse:
120+
async def process(self, context: AgentContext, next) -> AgentResponse:
121121
print(f"Input: {context.messages}")
122122
response = await next(context)
123123
print(f"Output: {response}")

python/packages/core/agent_framework/_middleware.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
TResponseModelT = TypeVar("TResponseModelT", bound=BaseModel)
4444

4545
__all__ = [
46+
"AgentContext",
4647
"AgentMiddleware",
4748
"AgentMiddlewareLayer",
4849
"AgentMiddlewareTypes",
49-
"AgentRunContext",
5050
"ChatAndFunctionMiddlewareTypes",
5151
"ChatContext",
5252
"ChatMiddleware",
@@ -109,7 +109,7 @@ class MiddlewareType(str, Enum):
109109
CHAT = "chat"
110110

111111

112-
class AgentRunContext:
112+
class AgentContext:
113113
"""Context object for agent middleware invocations.
114114
115115
This context is passed through the agent middleware pipeline and contains all information
@@ -131,11 +131,11 @@ class AgentRunContext:
131131
Examples:
132132
.. code-block:: python
133133
134-
from agent_framework import AgentMiddleware, AgentRunContext
134+
from agent_framework import AgentMiddleware, AgentContext
135135
136136
137137
class LoggingMiddleware(AgentMiddleware):
138-
async def process(self, context: AgentRunContext, next):
138+
async def process(self, context: AgentContext, next):
139139
print(f"Agent: {context.agent.name}")
140140
print(f"Messages: {len(context.messages)}")
141141
print(f"Thread: {context.thread}")
@@ -170,7 +170,7 @@ def __init__(
170170
| None = None,
171171
stream_cleanup_hooks: Sequence[Callable[[], Awaitable[None] | None]] | None = None,
172172
) -> None:
173-
"""Initialize the AgentRunContext.
173+
"""Initialize the AgentContext.
174174
175175
Args:
176176
agent: The agent being invoked.
@@ -356,14 +356,14 @@ class AgentMiddleware(ABC):
356356
Examples:
357357
.. code-block:: python
358358
359-
from agent_framework import AgentMiddleware, AgentRunContext, ChatAgent
359+
from agent_framework import AgentMiddleware, AgentContext, ChatAgent
360360
361361
362362
class RetryMiddleware(AgentMiddleware):
363363
def __init__(self, max_retries: int = 3):
364364
self.max_retries = max_retries
365365
366-
async def process(self, context: AgentRunContext, next):
366+
async def process(self, context: AgentContext, next):
367367
for attempt in range(self.max_retries):
368368
await next(context)
369369
if context.result and not context.result.is_error:
@@ -378,8 +378,8 @@ async def process(self, context: AgentRunContext, next):
378378
@abstractmethod
379379
async def process(
380380
self,
381-
context: AgentRunContext,
382-
next: Callable[[AgentRunContext], Awaitable[None]],
381+
context: AgentContext,
382+
next: Callable[[AgentContext], Awaitable[None]],
383383
) -> None:
384384
"""Process an agent invocation.
385385
@@ -531,7 +531,7 @@ async def process(
531531

532532

533533
# Pure function type definitions for convenience
534-
AgentMiddlewareCallable = Callable[[AgentRunContext, Callable[[AgentRunContext], Awaitable[None]]], Awaitable[None]]
534+
AgentMiddlewareCallable = Callable[[AgentContext, Callable[[AgentContext], Awaitable[None]]], Awaitable[None]]
535535
AgentMiddlewareTypes: TypeAlias = AgentMiddleware | AgentMiddlewareCallable
536536

537537
FunctionMiddlewareCallable = Callable[
@@ -561,7 +561,7 @@ def agent_middleware(func: AgentMiddlewareCallable) -> AgentMiddlewareCallable:
561561
"""Decorator to mark a function as agent middleware.
562562
563563
This decorator explicitly identifies a function as agent middleware,
564-
which processes AgentRunContext objects.
564+
which processes AgentContext objects.
565565
566566
Args:
567567
func: The middleware function to mark as agent middleware.
@@ -572,11 +572,11 @@ def agent_middleware(func: AgentMiddlewareCallable) -> AgentMiddlewareCallable:
572572
Examples:
573573
.. code-block:: python
574574
575-
from agent_framework import agent_middleware, AgentRunContext, ChatAgent
575+
from agent_framework import agent_middleware, AgentContext, ChatAgent
576576
577577
578578
@agent_middleware
579-
async def logging_middleware(context: AgentRunContext, next):
579+
async def logging_middleware(context: AgentContext, next):
580580
print(f"Before: {context.agent.name}")
581581
await next(context)
582582
print(f"After: {context.result}")
@@ -752,9 +752,9 @@ def _register_middleware(self, middleware: AgentMiddlewareTypes) -> None:
752752

753753
async def execute(
754754
self,
755-
context: AgentRunContext,
755+
context: AgentContext,
756756
final_handler: Callable[
757-
[AgentRunContext], Awaitable[AgentResponse] | ResponseStream[AgentResponseUpdate, AgentResponse]
757+
[AgentContext], Awaitable[AgentResponse] | ResponseStream[AgentResponseUpdate, AgentResponse]
758758
],
759759
) -> AgentResponse | ResponseStream[AgentResponseUpdate, AgentResponse] | None:
760760
"""Execute the agent middleware pipeline for streaming or non-streaming.
@@ -772,17 +772,17 @@ async def execute(
772772
context.result = await context.result
773773
return context.result
774774

775-
def create_next_handler(index: int) -> Callable[[AgentRunContext], Awaitable[None]]:
775+
def create_next_handler(index: int) -> Callable[[AgentContext], Awaitable[None]]:
776776
if index >= len(self._middleware):
777777

778-
async def final_wrapper(c: AgentRunContext) -> None:
778+
async def final_wrapper(c: AgentContext) -> None:
779779
c.result = final_handler(c) # type: ignore[assignment]
780780
if inspect.isawaitable(c.result):
781781
c.result = await c.result
782782

783783
return final_wrapper
784784

785-
async def current_handler(c: AgentRunContext) -> None:
785+
async def current_handler(c: AgentContext) -> None:
786786
# MiddlewareTermination bubbles up to execute() to skip post-processing
787787
await self._middleware[index].process(c, create_next_handler(index + 1))
788788

@@ -1161,7 +1161,7 @@ def run(
11611161
if not pipeline.has_middlewares:
11621162
return super().run(messages, stream=stream, thread=thread, options=options, **combined_kwargs) # type: ignore[misc, no-any-return]
11631163

1164-
context = AgentRunContext(
1164+
context = AgentContext(
11651165
agent=self, # type: ignore[arg-type]
11661166
messages=prepare_messages(messages), # type: ignore[arg-type]
11671167
thread=thread,
@@ -1194,7 +1194,7 @@ async def _execute_stream() -> ResponseStream[AgentResponseUpdate, AgentResponse
11941194
return _execute() # type: ignore[return-value]
11951195

11961196
def _middleware_handler(
1197-
self, context: AgentRunContext
1197+
self, context: AgentContext
11981198
) -> Awaitable[AgentResponse] | ResponseStream[AgentResponseUpdate, AgentResponse]:
11991199
return super().run( # type: ignore[misc, no-any-return]
12001200
context.messages,
@@ -1231,7 +1231,7 @@ def _determine_middleware_type(middleware: Any) -> MiddlewareType:
12311231
first_param = params[0]
12321232
if hasattr(first_param.annotation, "__name__"):
12331233
annotation_name = first_param.annotation.__name__
1234-
if annotation_name == "AgentRunContext":
1234+
if annotation_name == "AgentContext":
12351235
param_type = MiddlewareType.AGENT
12361236
elif annotation_name == "FunctionInvocationContext":
12371237
param_type = MiddlewareType.FUNCTION
@@ -1270,7 +1270,7 @@ def _determine_middleware_type(middleware: Any) -> MiddlewareType:
12701270
raise MiddlewareException(
12711271
f"Cannot determine middleware type for function {middleware.__name__}. "
12721272
f"Please either use @agent_middleware/@function_middleware/@chat_middleware decorators "
1273-
f"or specify parameter types (AgentRunContext, FunctionInvocationContext, or ChatContext)."
1273+
f"or specify parameter types (AgentContext, FunctionInvocationContext, or ChatContext)."
12741274
)
12751275

12761276

python/packages/core/agent_framework/_serialization.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,12 +477,12 @@ async def get_current_weather(location: Annotated[str, "The city name"]) -> str:
477477
478478
.. code-block:: python
479479
480-
from agent_framework._middleware import AgentRunContext
480+
from agent_framework._middleware import AgentContext
481481
from agent_framework import BaseAgent
482482
483-
# AgentRunContext has INJECTABLE = {"agent", "result"}
483+
# AgentContext has INJECTABLE = {"agent", "result"}
484484
context_data = {
485-
"type": "agent_run_context",
485+
"type": "agent_context",
486486
"messages": [{"role": "user", "text": "Hello"}],
487487
"stream": False,
488488
"metadata": {"session_id": "abc123"},
@@ -492,14 +492,14 @@ async def get_current_weather(location: Annotated[str, "The city name"]) -> str:
492492
# Inject agent and result during middleware processing
493493
my_agent = BaseAgent(name="test-agent")
494494
dependencies = {
495-
"agent_run_context": {
495+
"agent_context": {
496496
"agent": my_agent,
497497
"result": None, # Will be populated during execution
498498
}
499499
}
500500
501501
# Reconstruct context with agent dependency for middleware chain
502-
context = AgentRunContext.from_dict(context_data, dependencies=dependencies)
502+
context = AgentContext.from_dict(context_data, dependencies=dependencies)
503503
# MiddlewareTypes can now access context.agent and process the execution
504504
505505
This injection system allows the agent framework to maintain clean separation

python/packages/core/tests/core/test_as_tool_kwargs_propagation.py

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import Any
77

88
from agent_framework import ChatAgent, ChatMessage, ChatResponse, Content, agent_middleware
9-
from agent_framework._middleware import AgentRunContext
9+
from agent_framework._middleware import AgentContext
1010

1111
from .conftest import MockChatClient
1212

@@ -19,9 +19,7 @@ async def test_as_tool_forwards_runtime_kwargs(self, chat_client: MockChatClient
1919
captured_kwargs: dict[str, Any] = {}
2020

2121
@agent_middleware
22-
async def capture_middleware(
23-
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
24-
) -> None:
22+
async def capture_middleware(context: AgentContext, next: Callable[[AgentContext], Awaitable[None]]) -> None:
2523
# Capture kwargs passed to the sub-agent
2624
captured_kwargs.update(context.kwargs)
2725
await next(context)
@@ -62,9 +60,7 @@ async def test_as_tool_excludes_arg_name_from_forwarded_kwargs(self, chat_client
6260
captured_kwargs: dict[str, Any] = {}
6361

6462
@agent_middleware
65-
async def capture_middleware(
66-
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
67-
) -> None:
63+
async def capture_middleware(context: AgentContext, next: Callable[[AgentContext], Awaitable[None]]) -> None:
6864
captured_kwargs.update(context.kwargs)
6965
await next(context)
7066

@@ -99,9 +95,7 @@ async def test_as_tool_nested_delegation_propagates_kwargs(self, chat_client: Mo
9995
captured_kwargs_list: list[dict[str, Any]] = []
10096

10197
@agent_middleware
102-
async def capture_middleware(
103-
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
104-
) -> None:
98+
async def capture_middleware(context: AgentContext, next: Callable[[AgentContext], Awaitable[None]]) -> None:
10599
# Capture kwargs at each level
106100
captured_kwargs_list.append(dict(context.kwargs))
107101
await next(context)
@@ -162,9 +156,7 @@ async def test_as_tool_streaming_mode_forwards_kwargs(self, chat_client: MockCha
162156
captured_kwargs: dict[str, Any] = {}
163157

164158
@agent_middleware
165-
async def capture_middleware(
166-
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
167-
) -> None:
159+
async def capture_middleware(context: AgentContext, next: Callable[[AgentContext], Awaitable[None]]) -> None:
168160
captured_kwargs.update(context.kwargs)
169161
await next(context)
170162

@@ -224,9 +216,7 @@ async def test_as_tool_kwargs_with_chat_options(self, chat_client: MockChatClien
224216
captured_kwargs: dict[str, Any] = {}
225217

226218
@agent_middleware
227-
async def capture_middleware(
228-
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
229-
) -> None:
219+
async def capture_middleware(context: AgentContext, next: Callable[[AgentContext], Awaitable[None]]) -> None:
230220
captured_kwargs.update(context.kwargs)
231221
await next(context)
232222

@@ -266,9 +256,7 @@ async def test_as_tool_kwargs_isolated_per_invocation(self, chat_client: MockCha
266256
call_count = 0
267257

268258
@agent_middleware
269-
async def capture_middleware(
270-
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
271-
) -> None:
259+
async def capture_middleware(context: AgentContext, next: Callable[[AgentContext], Awaitable[None]]) -> None:
272260
nonlocal call_count
273261
call_count += 1
274262
if call_count == 1:
@@ -318,9 +306,7 @@ async def test_as_tool_excludes_conversation_id_from_forwarded_kwargs(self, chat
318306
captured_kwargs: dict[str, Any] = {}
319307

320308
@agent_middleware
321-
async def capture_middleware(
322-
context: AgentRunContext, next: Callable[[AgentRunContext], Awaitable[None]]
323-
) -> None:
309+
async def capture_middleware(context: AgentContext, next: Callable[[AgentContext], Awaitable[None]]) -> None:
324310
captured_kwargs.update(context.kwargs)
325311
await next(context)
326312

0 commit comments

Comments
 (0)