mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Renamed AgentProtocol to SupportsAgentRun (#3717)
* Renamed AgentProtocol to AgentLike * Resolved comments * Renamed AgentLike to SupportsAgentRun * Resolved comments
This commit is contained in:
committed by
GitHub
Unverified
parent
ac17adb595
commit
15256bb616
@@ -25,7 +25,7 @@ agent_framework/
|
||||
|
||||
### Agents (`_agents.py`)
|
||||
|
||||
- **`AgentProtocol`** - Protocol defining the agent interface
|
||||
- **`SupportsAgentRun`** - Protocol defining the agent interface
|
||||
- **`BaseAgent`** - Abstract base class for agents
|
||||
- **`ChatAgent`** - Main agent class wrapping a chat client with tools, instructions, and middleware
|
||||
|
||||
|
||||
@@ -163,14 +163,14 @@ class _RunContext(TypedDict):
|
||||
finalize_kwargs: dict[str, Any]
|
||||
|
||||
|
||||
__all__ = ["AgentProtocol", "BareAgent", "BaseAgent", "ChatAgent", "RawChatAgent"]
|
||||
__all__ = ["BareAgent", "BaseAgent", "ChatAgent", "RawChatAgent", "SupportsAgentRun"]
|
||||
|
||||
|
||||
# region Agent Protocol
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class AgentProtocol(Protocol):
|
||||
class SupportsAgentRun(Protocol):
|
||||
"""A protocol for an agent that can be invoked.
|
||||
|
||||
This protocol defines the interface that all agents must implement,
|
||||
@@ -185,11 +185,11 @@ class AgentProtocol(Protocol):
|
||||
Examples:
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import AgentProtocol
|
||||
from agent_framework import SupportsAgentRun
|
||||
|
||||
|
||||
# Any class implementing the required methods is compatible
|
||||
# No need to inherit from AgentProtocol or use any framework classes
|
||||
# No need to inherit from SupportsAgentRun or use any framework classes
|
||||
class CustomAgent:
|
||||
def __init__(self):
|
||||
self.id = "custom-agent-001"
|
||||
@@ -218,7 +218,7 @@ class AgentProtocol(Protocol):
|
||||
|
||||
# Verify the instance satisfies the protocol
|
||||
instance = CustomAgent()
|
||||
assert isinstance(instance, AgentProtocol)
|
||||
assert isinstance(instance, SupportsAgentRun)
|
||||
"""
|
||||
|
||||
id: str
|
||||
@@ -297,7 +297,7 @@ class BaseAgent(SerializationMixin):
|
||||
|
||||
Note:
|
||||
BaseAgent cannot be instantiated directly as it doesn't implement the
|
||||
``run()`` and other methods required by AgentProtocol.
|
||||
``run()`` and other methods required by SupportsAgentRun.
|
||||
Use a concrete implementation like ChatAgent or create a subclass.
|
||||
|
||||
Examples:
|
||||
@@ -451,7 +451,7 @@ class BaseAgent(SerializationMixin):
|
||||
A FunctionTool that can be used as a tool by other agents.
|
||||
|
||||
Raises:
|
||||
TypeError: If the agent does not implement AgentProtocol.
|
||||
TypeError: If the agent does not implement SupportsAgentRun.
|
||||
ValueError: If the agent tool name cannot be determined.
|
||||
|
||||
Examples:
|
||||
@@ -468,9 +468,9 @@ class BaseAgent(SerializationMixin):
|
||||
# Use the tool with another agent
|
||||
coordinator = ChatAgent(chat_client=client, name="coordinator", tools=research_tool)
|
||||
"""
|
||||
# Verify that self implements AgentProtocol
|
||||
if not isinstance(self, AgentProtocol):
|
||||
raise TypeError(f"Agent {self.__class__.__name__} must implement AgentProtocol to be used as a tool")
|
||||
# Verify that self implements SupportsAgentRun
|
||||
if not isinstance(self, SupportsAgentRun):
|
||||
raise TypeError(f"Agent {self.__class__.__name__} must implement SupportsAgentRun to be used as a tool")
|
||||
|
||||
tool_name = name or _sanitize_agent_name(self.name)
|
||||
if tool_name is None:
|
||||
|
||||
@@ -34,7 +34,7 @@ else:
|
||||
if TYPE_CHECKING:
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ._agents import AgentProtocol
|
||||
from ._agents import SupportsAgentRun
|
||||
from ._clients import ChatClientProtocol
|
||||
from ._threads import AgentThread
|
||||
from ._tools import FunctionTool
|
||||
@@ -64,7 +64,7 @@ __all__ = [
|
||||
"function_middleware",
|
||||
]
|
||||
|
||||
TAgent = TypeVar("TAgent", bound="AgentProtocol")
|
||||
AgentT = TypeVar("AgentT", bound="SupportsAgentRun")
|
||||
TContext = TypeVar("TContext")
|
||||
TUpdate = TypeVar("TUpdate")
|
||||
|
||||
@@ -154,7 +154,7 @@ class AgentContext:
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
agent: AgentProtocol,
|
||||
agent: SupportsAgentRun,
|
||||
messages: list[ChatMessage],
|
||||
thread: AgentThread | None = None,
|
||||
options: Mapping[str, Any] | None = None,
|
||||
|
||||
@@ -9,7 +9,7 @@ from typing_extensions import Never
|
||||
|
||||
from agent_framework import Content
|
||||
|
||||
from .._agents import AgentProtocol
|
||||
from .._agents import SupportsAgentRun
|
||||
from .._threads import AgentThread
|
||||
from .._types import AgentResponse, AgentResponseUpdate, ChatMessage
|
||||
from ._agent_utils import resolve_agent_id
|
||||
@@ -80,7 +80,7 @@ class AgentExecutor(Executor):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
agent: AgentProtocol,
|
||||
agent: SupportsAgentRun,
|
||||
*,
|
||||
agent_thread: AgentThread | None = None,
|
||||
id: str | None = None,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from .._agents import AgentProtocol
|
||||
from .._agents import SupportsAgentRun
|
||||
|
||||
|
||||
def resolve_agent_id(agent: AgentProtocol) -> str:
|
||||
def resolve_agent_id(agent: SupportsAgentRun) -> str:
|
||||
"""Resolve the unique identifier for an agent.
|
||||
|
||||
Prefers the `.name` attribute if set; otherwise falls back to `.id`.
|
||||
|
||||
@@ -6,7 +6,7 @@ from collections.abc import Callable, Sequence
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from .._agents import AgentProtocol
|
||||
from .._agents import SupportsAgentRun
|
||||
from .._threads import AgentThread
|
||||
from ..observability import OtelAttr, capture_exception, create_workflow_span
|
||||
from ._agent_executor import AgentExecutor
|
||||
@@ -171,7 +171,7 @@ class WorkflowBuilder:
|
||||
self._max_iterations: int = max_iterations
|
||||
self._name: str | None = name
|
||||
self._description: str | None = description
|
||||
# Maps underlying AgentProtocol object id -> wrapped Executor so we reuse the same wrapper
|
||||
# Maps underlying SupportsAgentRun object id -> wrapped Executor so we reuse the same wrapper
|
||||
# across set_start_executor / add_edge calls. This avoids multiple AgentExecutor instances
|
||||
# being created for the same agent.
|
||||
self._agent_wrappers: dict[str, Executor] = {}
|
||||
@@ -187,7 +187,7 @@ class WorkflowBuilder:
|
||||
self._executor_registry: dict[str, Callable[[], Executor]] = {}
|
||||
|
||||
# Output executors filter; if set, only outputs from these executors are yielded
|
||||
self._output_executors: list[Executor | AgentProtocol | str] = []
|
||||
self._output_executors: list[Executor | SupportsAgentRun | str] = []
|
||||
|
||||
# Agents auto-wrapped by builder now always stream incremental updates.
|
||||
|
||||
@@ -208,8 +208,8 @@ class WorkflowBuilder:
|
||||
|
||||
return executor.id
|
||||
|
||||
def _maybe_wrap_agent(self, candidate: Executor | AgentProtocol) -> Executor:
|
||||
"""If the provided object implements AgentProtocol, wrap it in an AgentExecutor.
|
||||
def _maybe_wrap_agent(self, candidate: Executor | SupportsAgentRun) -> Executor:
|
||||
"""If the provided object implements SupportsAgentRun, wrap it in an AgentExecutor.
|
||||
|
||||
This allows fluent builder APIs to directly accept agents instead of
|
||||
requiring callers to manually instantiate AgentExecutor.
|
||||
@@ -221,13 +221,13 @@ class WorkflowBuilder:
|
||||
An Executor instance, wrapping the agent if necessary.
|
||||
"""
|
||||
try: # Local import to avoid hard dependency at import time
|
||||
from agent_framework import AgentProtocol # type: ignore
|
||||
from agent_framework import SupportsAgentRun # type: ignore
|
||||
except Exception: # pragma: no cover - defensive
|
||||
AgentProtocol = object # type: ignore
|
||||
SupportsAgentRun = object # type: ignore
|
||||
|
||||
if isinstance(candidate, Executor): # Already an executor
|
||||
return candidate
|
||||
if isinstance(candidate, AgentProtocol): # type: ignore[arg-type]
|
||||
if isinstance(candidate, SupportsAgentRun): # type: ignore[arg-type]
|
||||
# Reuse existing wrapper for the same agent instance if present
|
||||
agent_instance_id = str(id(candidate))
|
||||
existing = self._agent_wrappers.get(agent_instance_id)
|
||||
@@ -244,7 +244,7 @@ class WorkflowBuilder:
|
||||
return wrapper
|
||||
|
||||
raise TypeError(
|
||||
f"WorkflowBuilder expected an Executor or AgentProtocol instance; got {type(candidate).__name__}."
|
||||
f"WorkflowBuilder expected an Executor or SupportsAgentRun instance; got {type(candidate).__name__}."
|
||||
)
|
||||
|
||||
def register_executor(self, factory_func: Callable[[], Executor], name: str | list[str]) -> Self:
|
||||
@@ -321,7 +321,7 @@ class WorkflowBuilder:
|
||||
|
||||
def register_agent(
|
||||
self,
|
||||
factory_func: Callable[[], AgentProtocol],
|
||||
factory_func: Callable[[], SupportsAgentRun],
|
||||
name: str,
|
||||
agent_thread: AgentThread | None = None,
|
||||
) -> Self:
|
||||
@@ -332,7 +332,7 @@ class WorkflowBuilder:
|
||||
enabling deferred initialization and potentially reducing startup time.
|
||||
|
||||
Args:
|
||||
factory_func: A callable that returns an AgentProtocol instance when called.
|
||||
factory_func: A callable that returns an SupportsAgentRun instance when called.
|
||||
name: The name of the registered agent factory. This doesn't have to match
|
||||
the agent's internal name. But it must be unique within the workflow.
|
||||
agent_thread: The thread to use for running the agent. If None, a new thread will be created when
|
||||
@@ -375,8 +375,8 @@ class WorkflowBuilder:
|
||||
|
||||
def add_edge(
|
||||
self,
|
||||
source: Executor | AgentProtocol | str,
|
||||
target: Executor | AgentProtocol | str,
|
||||
source: Executor | SupportsAgentRun | str,
|
||||
target: Executor | SupportsAgentRun | str,
|
||||
condition: EdgeCondition | None = None,
|
||||
) -> Self:
|
||||
"""Add a directed edge between two executors.
|
||||
@@ -441,8 +441,8 @@ class WorkflowBuilder:
|
||||
not isinstance(source, str) and isinstance(target, str)
|
||||
):
|
||||
raise ValueError(
|
||||
"Both source and target must be either registered factory names (str) "
|
||||
"or Executor/AgentProtocol instances."
|
||||
"Both source and target must be either registered factory names (str) or "
|
||||
"Executor/SupportsAgentRun instances."
|
||||
)
|
||||
|
||||
if isinstance(source, str) and isinstance(target, str):
|
||||
@@ -450,7 +450,7 @@ class WorkflowBuilder:
|
||||
self._edge_registry.append(_EdgeRegistration(source=source, target=target, condition=condition))
|
||||
return self
|
||||
|
||||
# Both are Executor/AgentProtocol instances; wrap and add now
|
||||
# Both are Executor/SupportsAgentRun instances; wrap and add now
|
||||
source_exec = self._maybe_wrap_agent(source) # type: ignore[arg-type]
|
||||
target_exec = self._maybe_wrap_agent(target) # type: ignore[arg-type]
|
||||
source_id = self._add_executor(source_exec)
|
||||
@@ -460,8 +460,8 @@ class WorkflowBuilder:
|
||||
|
||||
def add_fan_out_edges(
|
||||
self,
|
||||
source: Executor | AgentProtocol | str,
|
||||
targets: Sequence[Executor | AgentProtocol | str],
|
||||
source: Executor | SupportsAgentRun | str,
|
||||
targets: Sequence[Executor | SupportsAgentRun | str],
|
||||
) -> Self:
|
||||
"""Add multiple edges to the workflow where messages from the source will be sent to all targets.
|
||||
|
||||
@@ -520,8 +520,8 @@ class WorkflowBuilder:
|
||||
not isinstance(source, str) and any(isinstance(t, str) for t in targets)
|
||||
):
|
||||
raise ValueError(
|
||||
"Both source and targets must be either registered factory names (str) "
|
||||
"or Executor/AgentProtocol instances."
|
||||
"Both source and targets must be either registered factory names (str) or "
|
||||
"Executor/SupportsAgentRun instances."
|
||||
)
|
||||
|
||||
if isinstance(source, str) and all(isinstance(t, str) for t in targets):
|
||||
@@ -529,7 +529,7 @@ class WorkflowBuilder:
|
||||
self._edge_registry.append(_FanOutEdgeRegistration(source=source, targets=list(targets))) # type: ignore
|
||||
return self
|
||||
|
||||
# Both are Executor/AgentProtocol instances; wrap and add now
|
||||
# Both are Executor/SupportsAgentRun instances; wrap and add now
|
||||
source_exec = self._maybe_wrap_agent(source) # type: ignore[arg-type]
|
||||
target_execs = [self._maybe_wrap_agent(t) for t in targets] # type: ignore[arg-type]
|
||||
source_id = self._add_executor(source_exec)
|
||||
@@ -540,7 +540,7 @@ class WorkflowBuilder:
|
||||
|
||||
def add_switch_case_edge_group(
|
||||
self,
|
||||
source: Executor | AgentProtocol | str,
|
||||
source: Executor | SupportsAgentRun | str,
|
||||
cases: Sequence[Case | Default],
|
||||
) -> Self:
|
||||
"""Add an edge group that represents a switch-case statement.
|
||||
@@ -620,7 +620,7 @@ class WorkflowBuilder:
|
||||
):
|
||||
raise ValueError(
|
||||
"Both source and case targets must be either registered factory names (str) "
|
||||
"or Executor/AgentProtocol instances."
|
||||
"or Executor/SupportsAgentRun instances."
|
||||
)
|
||||
|
||||
if isinstance(source, str) and all(isinstance(case.target, str) for case in cases):
|
||||
@@ -628,7 +628,7 @@ class WorkflowBuilder:
|
||||
self._edge_registry.append(_SwitchCaseEdgeGroupRegistration(source=source, cases=list(cases))) # type: ignore
|
||||
return self
|
||||
|
||||
# Source is an Executor/AgentProtocol instance; wrap and add now
|
||||
# Source is an Executor/SupportsAgentRun instance; wrap and add now
|
||||
source_exec = self._maybe_wrap_agent(source) # type: ignore[arg-type]
|
||||
source_id = self._add_executor(source_exec)
|
||||
# Convert case data types to internal types that only uses target_id.
|
||||
@@ -647,8 +647,8 @@ class WorkflowBuilder:
|
||||
|
||||
def add_multi_selection_edge_group(
|
||||
self,
|
||||
source: Executor | AgentProtocol | str,
|
||||
targets: Sequence[Executor | AgentProtocol | str],
|
||||
source: Executor | SupportsAgentRun | str,
|
||||
targets: Sequence[Executor | SupportsAgentRun | str],
|
||||
selection_func: Callable[[Any, list[str]], list[str]],
|
||||
) -> Self:
|
||||
"""Add an edge group that represents a multi-selection execution model.
|
||||
@@ -731,8 +731,8 @@ class WorkflowBuilder:
|
||||
not isinstance(source, str) and any(isinstance(t, str) for t in targets)
|
||||
):
|
||||
raise ValueError(
|
||||
"Both source and targets must be either registered factory names (str) "
|
||||
"or Executor/AgentProtocol instances."
|
||||
"Both source and targets must be either registered factory names (str) or "
|
||||
"Executor/SupportsAgentRun instances."
|
||||
)
|
||||
|
||||
if isinstance(source, str) and all(isinstance(t, str) for t in targets):
|
||||
@@ -746,7 +746,7 @@ class WorkflowBuilder:
|
||||
)
|
||||
return self
|
||||
|
||||
# Both are Executor/AgentProtocol instances; wrap and add now
|
||||
# Both are Executor/SupportsAgentRun instances; wrap and add now
|
||||
source_exec = self._maybe_wrap_agent(source) # type: ignore
|
||||
target_execs = [self._maybe_wrap_agent(t) for t in targets] # type: ignore
|
||||
source_id = self._add_executor(source_exec)
|
||||
@@ -757,8 +757,8 @@ class WorkflowBuilder:
|
||||
|
||||
def add_fan_in_edges(
|
||||
self,
|
||||
sources: Sequence[Executor | AgentProtocol | str],
|
||||
target: Executor | AgentProtocol | str,
|
||||
sources: Sequence[Executor | SupportsAgentRun | str],
|
||||
target: Executor | SupportsAgentRun | str,
|
||||
) -> Self:
|
||||
"""Add multiple edges from sources to a single target executor.
|
||||
|
||||
@@ -816,8 +816,8 @@ class WorkflowBuilder:
|
||||
not all(isinstance(s, str) for s in sources) and isinstance(target, str)
|
||||
):
|
||||
raise ValueError(
|
||||
"Both sources and target must be either registered factory names (str) "
|
||||
"or Executor/AgentProtocol instances."
|
||||
"Both sources and target must be either registered factory names (str) or "
|
||||
"Executor/SupportsAgentRun instances."
|
||||
)
|
||||
|
||||
if all(isinstance(s, str) for s in sources) and isinstance(target, str):
|
||||
@@ -825,7 +825,7 @@ class WorkflowBuilder:
|
||||
self._edge_registry.append(_FanInEdgeRegistration(sources=list(sources), target=target)) # type: ignore
|
||||
return self
|
||||
|
||||
# Both are Executor/AgentProtocol instances; wrap and add now
|
||||
# Both are Executor/SupportsAgentRun instances; wrap and add now
|
||||
source_execs = [self._maybe_wrap_agent(s) for s in sources] # type: ignore
|
||||
target_exec = self._maybe_wrap_agent(target) # type: ignore
|
||||
source_ids = [self._add_executor(s) for s in source_execs]
|
||||
@@ -834,7 +834,7 @@ class WorkflowBuilder:
|
||||
|
||||
return self
|
||||
|
||||
def add_chain(self, executors: Sequence[Executor | AgentProtocol | str]) -> Self:
|
||||
def add_chain(self, executors: Sequence[Executor | SupportsAgentRun | str]) -> Self:
|
||||
"""Add a chain of executors to the workflow.
|
||||
|
||||
The output of each executor in the chain will be sent to the next executor in the chain.
|
||||
@@ -895,7 +895,7 @@ class WorkflowBuilder:
|
||||
if not all(isinstance(e, str) for e in executors) and any(isinstance(e, str) for e in executors):
|
||||
raise ValueError(
|
||||
"All executors in the chain must be either registered factory names (str) "
|
||||
"or Executor/AgentProtocol instances."
|
||||
"or Executor/SupportsAgentRun instances."
|
||||
)
|
||||
|
||||
if all(isinstance(e, str) for e in executors):
|
||||
@@ -904,21 +904,21 @@ class WorkflowBuilder:
|
||||
self.add_edge(executors[i], executors[i + 1])
|
||||
return self
|
||||
|
||||
# All are Executor/AgentProtocol instances; wrap and add now
|
||||
# All are Executor/SupportsAgentRun instances; wrap and add now
|
||||
# Wrap each candidate first to ensure stable IDs before adding edges
|
||||
wrapped: list[Executor] = [self._maybe_wrap_agent(e) for e in executors] # type: ignore[arg-type]
|
||||
for i in range(len(wrapped) - 1):
|
||||
self.add_edge(wrapped[i], wrapped[i + 1])
|
||||
return self
|
||||
|
||||
def set_start_executor(self, executor: Executor | AgentProtocol | str) -> Self:
|
||||
def set_start_executor(self, executor: Executor | SupportsAgentRun | str) -> Self:
|
||||
"""Set the starting executor for the workflow.
|
||||
|
||||
The start executor is the entry point for the workflow. When the workflow is executed,
|
||||
the initial message will be sent to this executor.
|
||||
|
||||
Args:
|
||||
executor: The starting executor, which can be an Executor instance, AgentProtocol instance,
|
||||
executor: The starting executor, which can be an Executor instance, SupportsAgentRun instance,
|
||||
or the name of a registered executor factory.
|
||||
|
||||
Returns:
|
||||
@@ -1067,7 +1067,7 @@ class WorkflowBuilder:
|
||||
self._checkpoint_storage = checkpoint_storage
|
||||
return self
|
||||
|
||||
def with_output_from(self, executors: list[Executor | AgentProtocol | str]) -> Self:
|
||||
def with_output_from(self, executors: list[Executor | SupportsAgentRun | str]) -> Self:
|
||||
"""Specify which executors' outputs should be collected as workflow outputs.
|
||||
|
||||
By default, outputs from all executors are collected. This method allows
|
||||
@@ -1231,7 +1231,11 @@ class WorkflowBuilder:
|
||||
if isinstance(factory_name, str)
|
||||
]
|
||||
+ [ex.id for ex in self._output_executors if isinstance(ex, Executor)]
|
||||
+ [resolve_agent_id(agent) for agent in self._output_executors if isinstance(agent, AgentProtocol)]
|
||||
+ [
|
||||
resolve_agent_id(agent)
|
||||
for agent in self._output_executors
|
||||
if isinstance(agent, SupportsAgentRun)
|
||||
]
|
||||
)
|
||||
|
||||
# Perform validation before creating the workflow
|
||||
|
||||
@@ -38,7 +38,7 @@ if TYPE_CHECKING: # pragma: no cover
|
||||
from opentelemetry.util._decorator import _AgnosticContextManager # type: ignore[reportPrivateUsage]
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ._agents import AgentProtocol
|
||||
from ._agents import SupportsAgentRun
|
||||
from ._clients import ChatClientProtocol
|
||||
from ._threads import AgentThread
|
||||
from ._tools import FunctionTool
|
||||
@@ -70,7 +70,7 @@ __all__ = [
|
||||
]
|
||||
|
||||
|
||||
TAgent = TypeVar("TAgent", bound="AgentProtocol")
|
||||
AgentT = TypeVar("AgentT", bound="SupportsAgentRun")
|
||||
TChatClient = TypeVar("TChatClient", bound="ChatClientProtocol[Any]")
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ from pydantic import BaseModel
|
||||
from pytest import fixture
|
||||
|
||||
from agent_framework import (
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
AgentResponseUpdate,
|
||||
AgentThread,
|
||||
@@ -24,6 +23,7 @@ from agent_framework import (
|
||||
Content,
|
||||
FunctionInvocationLayer,
|
||||
ResponseStream,
|
||||
SupportsAgentRun,
|
||||
ToolProtocol,
|
||||
tool,
|
||||
)
|
||||
@@ -273,7 +273,7 @@ class MockAgentThread(AgentThread):
|
||||
|
||||
|
||||
# Mock Agent implementation for testing
|
||||
class MockAgent(AgentProtocol):
|
||||
class MockAgent(SupportsAgentRun):
|
||||
@property
|
||||
def id(self) -> str:
|
||||
return str(uuid4())
|
||||
@@ -329,5 +329,5 @@ def agent_thread() -> AgentThread:
|
||||
|
||||
|
||||
@fixture
|
||||
def agent() -> AgentProtocol:
|
||||
def agent() -> SupportsAgentRun:
|
||||
return MockAgent()
|
||||
|
||||
@@ -10,7 +10,6 @@ import pytest
|
||||
from pytest import raises
|
||||
|
||||
from agent_framework import (
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
AgentResponseUpdate,
|
||||
AgentThread,
|
||||
@@ -24,6 +23,7 @@ from agent_framework import (
|
||||
Context,
|
||||
ContextProvider,
|
||||
HostedCodeInterpreterTool,
|
||||
SupportsAgentRun,
|
||||
ToolProtocol,
|
||||
tool,
|
||||
)
|
||||
@@ -36,17 +36,17 @@ def test_agent_thread_type(agent_thread: AgentThread) -> None:
|
||||
assert isinstance(agent_thread, AgentThread)
|
||||
|
||||
|
||||
def test_agent_type(agent: AgentProtocol) -> None:
|
||||
assert isinstance(agent, AgentProtocol)
|
||||
def test_agent_type(agent: SupportsAgentRun) -> None:
|
||||
assert isinstance(agent, SupportsAgentRun)
|
||||
|
||||
|
||||
async def test_agent_run(agent: AgentProtocol) -> None:
|
||||
async def test_agent_run(agent: SupportsAgentRun) -> None:
|
||||
response = await agent.run("test")
|
||||
assert response.messages[0].role == "assistant"
|
||||
assert response.messages[0].text == "Response"
|
||||
|
||||
|
||||
async def test_agent_run_streaming(agent: AgentProtocol) -> None:
|
||||
async def test_agent_run_streaming(agent: SupportsAgentRun) -> None:
|
||||
async def collect_updates(updates: AsyncIterable[AgentResponseUpdate]) -> list[AgentResponseUpdate]:
|
||||
return [u async for u in updates]
|
||||
|
||||
@@ -57,7 +57,7 @@ async def test_agent_run_streaming(agent: AgentProtocol) -> None:
|
||||
|
||||
def test_chat_client_agent_type(chat_client: ChatClientProtocol) -> None:
|
||||
chat_client_agent = ChatAgent(chat_client=chat_client)
|
||||
assert isinstance(chat_client_agent, AgentProtocol)
|
||||
assert isinstance(chat_client_agent, SupportsAgentRun)
|
||||
|
||||
|
||||
async def test_chat_client_agent_init(chat_client: ChatClientProtocol) -> None:
|
||||
@@ -804,7 +804,7 @@ def test_sanitize_agent_name_replaces_invalid_chars():
|
||||
# endregion
|
||||
|
||||
|
||||
# region Test AgentProtocol.get_new_thread and deserialize_thread
|
||||
# region Test SupportsAgentRun.get_new_thread and deserialize_thread
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -8,7 +8,6 @@ import pytest
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from agent_framework import (
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
AgentResponseUpdate,
|
||||
ChatMessage,
|
||||
@@ -16,6 +15,7 @@ from agent_framework import (
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
ResponseStream,
|
||||
SupportsAgentRun,
|
||||
)
|
||||
from agent_framework._middleware import (
|
||||
AgentContext,
|
||||
@@ -35,7 +35,7 @@ from agent_framework._tools import FunctionTool
|
||||
class TestAgentContext:
|
||||
"""Test cases for AgentContext."""
|
||||
|
||||
def test_init_with_defaults(self, mock_agent: AgentProtocol) -> None:
|
||||
def test_init_with_defaults(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test AgentContext initialization with default values."""
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
@@ -45,7 +45,7 @@ class TestAgentContext:
|
||||
assert context.stream is False
|
||||
assert context.metadata == {}
|
||||
|
||||
def test_init_with_custom_values(self, mock_agent: AgentProtocol) -> None:
|
||||
def test_init_with_custom_values(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test AgentContext initialization with custom values."""
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
metadata = {"key": "value"}
|
||||
@@ -56,7 +56,7 @@ class TestAgentContext:
|
||||
assert context.stream is True
|
||||
assert context.metadata == metadata
|
||||
|
||||
def test_init_with_thread(self, mock_agent: AgentProtocol) -> None:
|
||||
def test_init_with_thread(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test AgentContext initialization with thread parameter."""
|
||||
from agent_framework import AgentThread
|
||||
|
||||
@@ -163,7 +163,7 @@ class TestAgentMiddlewarePipeline:
|
||||
pipeline = AgentMiddlewarePipeline(test_middleware)
|
||||
assert pipeline.has_middlewares
|
||||
|
||||
async def test_execute_no_middleware(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_no_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline execution with no middleware."""
|
||||
pipeline = AgentMiddlewarePipeline()
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
@@ -177,7 +177,7 @@ class TestAgentMiddlewarePipeline:
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
assert result == expected_response
|
||||
|
||||
async def test_execute_with_middleware(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_with_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline execution with middleware."""
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -205,7 +205,7 @@ class TestAgentMiddlewarePipeline:
|
||||
assert result == expected_response
|
||||
assert execution_order == ["test_before", "handler", "test_after"]
|
||||
|
||||
async def test_execute_stream_no_middleware(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_stream_no_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline streaming execution with no middleware."""
|
||||
pipeline = AgentMiddlewarePipeline()
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
@@ -228,7 +228,7 @@ class TestAgentMiddlewarePipeline:
|
||||
assert updates[0].text == "chunk1"
|
||||
assert updates[1].text == "chunk2"
|
||||
|
||||
async def test_execute_stream_with_middleware(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_stream_with_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline streaming execution with middleware."""
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -265,7 +265,7 @@ class TestAgentMiddlewarePipeline:
|
||||
assert updates[1].text == "chunk2"
|
||||
assert execution_order == ["test_before", "test_after", "handler_start", "handler_end"]
|
||||
|
||||
async def test_execute_with_pre_next_termination(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_with_pre_next_termination(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline execution with termination before next()."""
|
||||
middleware = self.PreNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
@@ -283,7 +283,7 @@ class TestAgentMiddlewarePipeline:
|
||||
# Handler should not be called when terminated before next()
|
||||
assert execution_order == []
|
||||
|
||||
async def test_execute_with_post_next_termination(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_with_post_next_termination(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline execution with termination after next()."""
|
||||
middleware = self.PostNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
@@ -301,7 +301,7 @@ class TestAgentMiddlewarePipeline:
|
||||
assert response.messages[0].text == "response"
|
||||
assert execution_order == ["handler"]
|
||||
|
||||
async def test_execute_stream_with_pre_next_termination(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_stream_with_pre_next_termination(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline streaming execution with termination before next()."""
|
||||
middleware = self.PreNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
@@ -329,7 +329,7 @@ class TestAgentMiddlewarePipeline:
|
||||
assert execution_order == []
|
||||
assert not updates
|
||||
|
||||
async def test_execute_stream_with_post_next_termination(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_stream_with_post_next_termination(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline streaming execution with termination after next()."""
|
||||
middleware = self.PostNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
@@ -356,7 +356,7 @@ class TestAgentMiddlewarePipeline:
|
||||
assert updates[1].text == "chunk2"
|
||||
assert execution_order == ["handler_start", "handler_end"]
|
||||
|
||||
async def test_execute_with_thread_in_context(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_with_thread_in_context(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline execution properly passes thread to middleware."""
|
||||
from agent_framework import AgentThread
|
||||
|
||||
@@ -383,7 +383,7 @@ class TestAgentMiddlewarePipeline:
|
||||
assert result == expected_response
|
||||
assert captured_thread is thread
|
||||
|
||||
async def test_execute_with_no_thread_in_context(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_execute_with_no_thread_in_context(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline execution when no thread is provided."""
|
||||
captured_thread = "not_none" # Use string to distinguish from None
|
||||
|
||||
@@ -761,7 +761,7 @@ class TestChatMiddlewarePipeline:
|
||||
class TestClassBasedMiddleware:
|
||||
"""Test cases for class-based middleware implementations."""
|
||||
|
||||
async def test_agent_middleware_execution(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_execution(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test class-based agent middleware execution."""
|
||||
metadata_updates: list[str] = []
|
||||
|
||||
@@ -825,7 +825,7 @@ class TestClassBasedMiddleware:
|
||||
class TestFunctionBasedMiddleware:
|
||||
"""Test cases for function-based middleware implementations."""
|
||||
|
||||
async def test_agent_function_middleware(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_function_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test function-based agent middleware."""
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -879,7 +879,7 @@ class TestFunctionBasedMiddleware:
|
||||
class TestMixedMiddleware:
|
||||
"""Test cases for mixed class and function-based middleware."""
|
||||
|
||||
async def test_mixed_agent_middleware(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_mixed_agent_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test mixed class and function-based agent middleware."""
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -976,7 +976,7 @@ class TestMixedMiddleware:
|
||||
class TestMultipleMiddlewareOrdering:
|
||||
"""Test cases for multiple middleware execution order."""
|
||||
|
||||
async def test_agent_middleware_execution_order(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_execution_order(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that multiple agent middleware execute in registration order."""
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -1110,7 +1110,7 @@ class TestMultipleMiddlewareOrdering:
|
||||
class TestContextContentValidation:
|
||||
"""Test cases for validating middleware context content."""
|
||||
|
||||
async def test_agent_context_validation(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_context_validation(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that agent context contains expected data."""
|
||||
|
||||
class ContextValidationMiddleware(AgentMiddleware):
|
||||
@@ -1231,7 +1231,7 @@ class TestContextContentValidation:
|
||||
class TestStreamingScenarios:
|
||||
"""Test cases for streaming and non-streaming scenarios."""
|
||||
|
||||
async def test_streaming_flag_validation(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_streaming_flag_validation(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that stream flag is correctly set for streaming calls."""
|
||||
streaming_flags: list[bool] = []
|
||||
|
||||
@@ -1271,7 +1271,7 @@ class TestStreamingScenarios:
|
||||
# Verify flags: [non-streaming middleware, non-streaming handler, streaming middleware, streaming handler]
|
||||
assert streaming_flags == [False, False, True, True]
|
||||
|
||||
async def test_streaming_middleware_behavior(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_streaming_middleware_behavior(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test middleware behavior with streaming responses."""
|
||||
chunks_processed: list[str] = []
|
||||
|
||||
@@ -1437,7 +1437,7 @@ class MockFunctionArgs(BaseModel):
|
||||
class TestMiddlewareExecutionControl:
|
||||
"""Test cases for middleware execution control (when next() is called vs not called)."""
|
||||
|
||||
async def test_agent_middleware_no_next_no_execution(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_no_next_no_execution(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that when agent middleware doesn't call next(), no execution happens."""
|
||||
|
||||
class NoNextMiddleware(AgentMiddleware):
|
||||
@@ -1464,7 +1464,7 @@ class TestMiddlewareExecutionControl:
|
||||
assert not handler_called
|
||||
assert context.result is None
|
||||
|
||||
async def test_agent_middleware_no_next_no_streaming_execution(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_no_next_no_streaming_execution(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that when agent middleware doesn't call next(), no streaming execution happens."""
|
||||
|
||||
class NoNextStreamingMiddleware(AgentMiddleware):
|
||||
@@ -1529,7 +1529,7 @@ class TestMiddlewareExecutionControl:
|
||||
assert not handler_called
|
||||
assert context.result is None
|
||||
|
||||
async def test_multiple_middlewares_early_stop(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_multiple_middlewares_early_stop(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that when first middleware doesn't call next(), subsequent middleware are not called."""
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -1664,9 +1664,9 @@ class TestMiddlewareExecutionControl:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_agent() -> AgentProtocol:
|
||||
def mock_agent() -> SupportsAgentRun:
|
||||
"""Mock agent for testing."""
|
||||
agent = MagicMock(spec=AgentProtocol)
|
||||
agent = MagicMock(spec=SupportsAgentRun)
|
||||
agent.name = "test_agent"
|
||||
return agent
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ import pytest
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from agent_framework import (
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Content,
|
||||
ResponseStream,
|
||||
SupportsAgentRun,
|
||||
)
|
||||
from agent_framework._middleware import (
|
||||
AgentContext,
|
||||
@@ -38,7 +38,7 @@ class FunctionTestArgs(BaseModel):
|
||||
class TestResultOverrideMiddleware:
|
||||
"""Test cases for middleware result override functionality."""
|
||||
|
||||
async def test_agent_middleware_response_override_non_streaming(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_response_override_non_streaming(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that agent middleware can override response for non-streaming execution."""
|
||||
override_response = AgentResponse(messages=[ChatMessage(role="assistant", text="overridden response")])
|
||||
|
||||
@@ -69,7 +69,7 @@ class TestResultOverrideMiddleware:
|
||||
# Verify original handler was called since middleware called next()
|
||||
assert handler_called
|
||||
|
||||
async def test_agent_middleware_response_override_streaming(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_response_override_streaming(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that agent middleware can override response for streaming execution."""
|
||||
|
||||
async def override_stream() -> AsyncIterable[AgentResponseUpdate]:
|
||||
@@ -211,7 +211,7 @@ class TestResultOverrideMiddleware:
|
||||
assert normal_updates[0].text == "test streaming response "
|
||||
assert normal_updates[1].text == "another update"
|
||||
|
||||
async def test_agent_middleware_conditional_no_next(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_conditional_no_next(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that when agent middleware conditionally doesn't call next(), no execution happens."""
|
||||
|
||||
class ConditionalNoNextMiddleware(AgentMiddleware):
|
||||
@@ -303,7 +303,7 @@ class TestResultOverrideMiddleware:
|
||||
class TestResultObservability:
|
||||
"""Test cases for middleware result observability functionality."""
|
||||
|
||||
async def test_agent_middleware_response_observability(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_response_observability(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that middleware can observe response after execution."""
|
||||
observed_responses: list[AgentResponse] = []
|
||||
|
||||
@@ -370,7 +370,7 @@ class TestResultObservability:
|
||||
assert observed_results[0] == "executed function result"
|
||||
assert result == observed_results[0]
|
||||
|
||||
async def test_agent_middleware_post_execution_override(self, mock_agent: AgentProtocol) -> None:
|
||||
async def test_agent_middleware_post_execution_override(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that middleware can override response after observing execution."""
|
||||
|
||||
class PostExecutionOverrideMiddleware(AgentMiddleware):
|
||||
@@ -436,9 +436,9 @@ class TestResultObservability:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_agent() -> AgentProtocol:
|
||||
def mock_agent() -> SupportsAgentRun:
|
||||
"""Mock agent for testing."""
|
||||
agent = MagicMock(spec=AgentProtocol)
|
||||
agent = MagicMock(spec=SupportsAgentRun)
|
||||
agent.name = "test_agent"
|
||||
return agent
|
||||
|
||||
|
||||
@@ -1853,13 +1853,13 @@ class TestChatAgentChatMiddleware:
|
||||
|
||||
|
||||
# class TestMiddlewareWithProtocolOnlyAgent:
|
||||
# """Test use_agent_middleware with agents implementing only AgentProtocol."""
|
||||
# """Test use_agent_middleware with agents implementing only SupportsAgentRun."""
|
||||
|
||||
# async def test_middleware_with_protocol_only_agent(self) -> None:
|
||||
# """Verify middleware works without BaseAgent inheritance for both run."""
|
||||
# from collections.abc import AsyncIterable
|
||||
|
||||
# from agent_framework import AgentProtocol, AgentResponse, AgentResponseUpdate
|
||||
# from agent_framework import SupportsAgentRun, AgentResponse, AgentResponseUpdate
|
||||
|
||||
# execution_order: list[str] = []
|
||||
|
||||
@@ -1873,7 +1873,7 @@ class TestChatAgentChatMiddleware:
|
||||
|
||||
# @use_agent_middleware
|
||||
# class ProtocolOnlyAgent:
|
||||
# """Minimal agent implementing only AgentProtocol, not inheriting from BaseAgent."""
|
||||
# """Minimal agent implementing only SupportsAgentRun, not inheriting from BaseAgent."""
|
||||
|
||||
# def __init__(self):
|
||||
# self.id = "protocol-only-agent"
|
||||
@@ -1896,7 +1896,7 @@ class TestChatAgentChatMiddleware:
|
||||
# return None
|
||||
|
||||
# agent = ProtocolOnlyAgent()
|
||||
# assert isinstance(agent, AgentProtocol)
|
||||
# assert isinstance(agent, SupportsAgentRun)
|
||||
|
||||
# # Test run (non-streaming)
|
||||
# response = await agent.run("test message")
|
||||
|
||||
@@ -12,7 +12,6 @@ from opentelemetry.trace import StatusCode
|
||||
|
||||
from agent_framework import (
|
||||
AGENT_FRAMEWORK_USER_AGENT,
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
BaseChatClient,
|
||||
ChatMessage,
|
||||
@@ -20,6 +19,7 @@ from agent_framework import (
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
ResponseStream,
|
||||
SupportsAgentRun,
|
||||
UsageDetails,
|
||||
prepend_agent_framework_to_user_agent,
|
||||
tool,
|
||||
@@ -473,7 +473,7 @@ def mock_chat_agent():
|
||||
|
||||
@pytest.mark.parametrize("enable_sensitive_data", [True, False], indirect=True)
|
||||
async def test_agent_instrumentation_enabled(
|
||||
mock_chat_agent: AgentProtocol, span_exporter: InMemorySpanExporter, enable_sensitive_data
|
||||
mock_chat_agent: SupportsAgentRun, span_exporter: InMemorySpanExporter, enable_sensitive_data
|
||||
):
|
||||
"""Test that when agent diagnostics are enabled, telemetry is applied."""
|
||||
|
||||
@@ -499,7 +499,7 @@ async def test_agent_instrumentation_enabled(
|
||||
|
||||
@pytest.mark.parametrize("enable_sensitive_data", [True, False], indirect=True)
|
||||
async def test_agent_streaming_response_with_diagnostics_enabled(
|
||||
mock_chat_agent: AgentProtocol, span_exporter: InMemorySpanExporter, enable_sensitive_data
|
||||
mock_chat_agent: SupportsAgentRun, span_exporter: InMemorySpanExporter, enable_sensitive_data
|
||||
):
|
||||
"""Test agent streaming telemetry through the agent telemetry mixin."""
|
||||
agent = mock_chat_agent()
|
||||
|
||||
@@ -9,7 +9,6 @@ from typing_extensions import Never
|
||||
|
||||
from agent_framework import (
|
||||
AgentExecutorRequest,
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
AgentResponseUpdate,
|
||||
AgentThread,
|
||||
@@ -18,6 +17,7 @@ from agent_framework import (
|
||||
Content,
|
||||
Executor,
|
||||
ResponseStream,
|
||||
SupportsAgentRun,
|
||||
UsageDetails,
|
||||
WorkflowAgent,
|
||||
WorkflowBuilder,
|
||||
@@ -615,7 +615,7 @@ class TestWorkflowAgent:
|
||||
async def test_agent_executor_output_response_false_filters_streaming_events(self):
|
||||
"""Test that AgentExecutor with output_response=False does not surface streaming events."""
|
||||
|
||||
class MockAgent(AgentProtocol):
|
||||
class MockAgent(SupportsAgentRun):
|
||||
"""Mock agent for testing."""
|
||||
|
||||
def __init__(self, name: str, response_text: str) -> None:
|
||||
@@ -705,7 +705,7 @@ class TestWorkflowAgent:
|
||||
async def test_agent_executor_output_response_no_duplicate_from_workflow_output_event(self):
|
||||
"""Test that AgentExecutor with output_response=True does not duplicate content."""
|
||||
|
||||
class MockAgent(AgentProtocol):
|
||||
class MockAgent(SupportsAgentRun):
|
||||
"""Mock agent for testing."""
|
||||
|
||||
def __init__(self, name: str, response_text: str) -> None:
|
||||
|
||||
@@ -422,7 +422,7 @@ def test_mixing_eager_and_lazy_initialization_error():
|
||||
ValueError,
|
||||
match=(
|
||||
r"Both source and target must be either registered factory names \(str\) "
|
||||
r"or Executor/AgentProtocol instances\."
|
||||
r"or Executor/SupportsAgentRun instances\."
|
||||
),
|
||||
):
|
||||
builder.add_edge(eager_executor, "Lazy")
|
||||
|
||||
Reference in New Issue
Block a user