mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
[BREAKING] Python: Move orchestrations to dedicated package (#3685)
* Move orchestrations to dedicated package * Merge main * Fix markdown links * Fix links
This commit is contained in:
committed by
GitHub
Unverified
parent
10afb86213
commit
0daa7700c6
+1
-1
@@ -233,7 +233,7 @@ if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
For more advanced orchestration patterns including Sequential, GroupChat, Concurrent, Magentic, and Handoff orchestrations, see the [orchestration samples](samples/getting_started/workflows/orchestration).
|
||||
For more advanced orchestration patterns including Sequential, Concurrent, Group Chat, Handoff, and Magentic orchestrations, see the [orchestration samples](samples/getting_started/orchestrations).
|
||||
|
||||
## More Examples & Samples
|
||||
|
||||
|
||||
@@ -213,10 +213,7 @@ if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
**Note**: GroupChat, Sequential, and Concurrent orchestrations are available today. See examples in:
|
||||
- [python/samples/getting_started/workflows/orchestration/](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/workflows/orchestration)
|
||||
- [group_chat_simple_selector.py](https://github.com/microsoft/agent-framework/blob/main/python/samples/getting_started/workflows/orchestration/group_chat_simple_selector.py)
|
||||
- [group_chat_prompt_based_manager.py](https://github.com/microsoft/agent-framework/blob/main/python/samples/getting_started/workflows/orchestration/group_chat_prompt_based_manager.py)
|
||||
**Note**: Sequential, Concurrent, Group Chat, Handoff, and Magentic orchestrations are available. See examples in [orchestration samples](../../samples/getting_started/orchestrations).
|
||||
|
||||
## More Examples & Samples
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ from ._checkpoint import (
|
||||
WorkflowCheckpoint,
|
||||
)
|
||||
from ._checkpoint_summary import WorkflowCheckpointSummary, get_checkpoint_summary
|
||||
from ._concurrent import ConcurrentBuilder
|
||||
from ._const import (
|
||||
DEFAULT_MAX_ITERATIONS,
|
||||
)
|
||||
@@ -66,30 +65,6 @@ from ._executor import (
|
||||
handler,
|
||||
)
|
||||
from ._function_executor import FunctionExecutor, executor
|
||||
from ._group_chat import (
|
||||
AgentBasedGroupChatOrchestrator,
|
||||
GroupChatBuilder,
|
||||
GroupChatState,
|
||||
)
|
||||
from ._handoff import HandoffAgentUserRequest, HandoffBuilder, HandoffSentEvent
|
||||
from ._magentic import (
|
||||
ORCH_MSG_KIND_INSTRUCTION,
|
||||
ORCH_MSG_KIND_NOTICE,
|
||||
ORCH_MSG_KIND_TASK_LEDGER,
|
||||
ORCH_MSG_KIND_USER_TASK,
|
||||
MagenticBuilder,
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticOrchestrator,
|
||||
MagenticOrchestratorEvent,
|
||||
MagenticOrchestratorEventType,
|
||||
MagenticPlanReviewRequest,
|
||||
MagenticPlanReviewResponse,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
MagenticResetSignal,
|
||||
StandardMagenticManager,
|
||||
)
|
||||
from ._orchestration_request_info import AgentRequestInfoResponse
|
||||
from ._orchestration_state import OrchestrationState
|
||||
from ._request_info_mixin import response_handler
|
||||
@@ -99,7 +74,6 @@ from ._runner_context import (
|
||||
Message,
|
||||
RunnerContext,
|
||||
)
|
||||
from ._sequential import SequentialBuilder
|
||||
from ._validation import (
|
||||
EdgeDuplicationError,
|
||||
GraphConnectivityError,
|
||||
@@ -120,11 +94,6 @@ from ._workflow_executor import (
|
||||
|
||||
__all__ = [
|
||||
"DEFAULT_MAX_ITERATIONS",
|
||||
"ORCH_MSG_KIND_INSTRUCTION",
|
||||
"ORCH_MSG_KIND_NOTICE",
|
||||
"ORCH_MSG_KIND_TASK_LEDGER",
|
||||
"ORCH_MSG_KIND_USER_TASK",
|
||||
"AgentBasedGroupChatOrchestrator",
|
||||
"AgentExecutor",
|
||||
"AgentExecutorRequest",
|
||||
"AgentExecutorResponse",
|
||||
@@ -132,7 +101,6 @@ __all__ = [
|
||||
"BaseGroupChatOrchestrator",
|
||||
"Case",
|
||||
"CheckpointStorage",
|
||||
"ConcurrentBuilder",
|
||||
"Default",
|
||||
"Edge",
|
||||
"EdgeCondition",
|
||||
@@ -147,35 +115,17 @@ __all__ = [
|
||||
"FileCheckpointStorage",
|
||||
"FunctionExecutor",
|
||||
"GraphConnectivityError",
|
||||
"GroupChatBuilder",
|
||||
"GroupChatRequestMessage",
|
||||
"GroupChatRequestSentEvent",
|
||||
"GroupChatResponseReceivedEvent",
|
||||
"GroupChatState",
|
||||
"HandoffAgentUserRequest",
|
||||
"HandoffBuilder",
|
||||
"HandoffSentEvent",
|
||||
"InMemoryCheckpointStorage",
|
||||
"InProcRunnerContext",
|
||||
"MagenticBuilder",
|
||||
"MagenticContext",
|
||||
"MagenticManagerBase",
|
||||
"MagenticOrchestrator",
|
||||
"MagenticOrchestratorEvent",
|
||||
"MagenticOrchestratorEventType",
|
||||
"MagenticPlanReviewRequest",
|
||||
"MagenticPlanReviewResponse",
|
||||
"MagenticProgressLedger",
|
||||
"MagenticProgressLedgerItem",
|
||||
"MagenticResetSignal",
|
||||
"Message",
|
||||
"OrchestrationState",
|
||||
"RequestInfoEvent",
|
||||
"Runner",
|
||||
"RunnerContext",
|
||||
"SequentialBuilder",
|
||||
"SingleEdgeGroup",
|
||||
"StandardMagenticManager",
|
||||
"SubWorkflowRequestMessage",
|
||||
"SubWorkflowResponseMessage",
|
||||
"SuperStepCompletedEvent",
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import importlib
|
||||
from typing import Any
|
||||
|
||||
IMPORT_PATH = "agent_framework_orchestrations"
|
||||
PACKAGE_NAME = "agent-framework-orchestrations"
|
||||
_IMPORTS = [
|
||||
"__version__",
|
||||
# Sequential
|
||||
"SequentialBuilder",
|
||||
# Concurrent
|
||||
"ConcurrentBuilder",
|
||||
# Handoff
|
||||
"HandoffAgentExecutor",
|
||||
"HandoffAgentUserRequest",
|
||||
"HandoffBuilder",
|
||||
"HandoffConfiguration",
|
||||
"HandoffSentEvent",
|
||||
# Group Chat
|
||||
"AgentBasedGroupChatOrchestrator",
|
||||
"AgentOrchestrationOutput",
|
||||
"GroupChatBuilder",
|
||||
"GroupChatOrchestrator",
|
||||
"GroupChatSelectionFunction",
|
||||
"GroupChatState",
|
||||
# Magentic
|
||||
"MAGENTIC_MANAGER_NAME",
|
||||
"ORCH_MSG_KIND_INSTRUCTION",
|
||||
"ORCH_MSG_KIND_NOTICE",
|
||||
"ORCH_MSG_KIND_TASK_LEDGER",
|
||||
"ORCH_MSG_KIND_USER_TASK",
|
||||
"MagenticAgentExecutor",
|
||||
"MagenticBuilder",
|
||||
"MagenticContext",
|
||||
"MagenticManagerBase",
|
||||
"MagenticOrchestrator",
|
||||
"MagenticOrchestratorEvent",
|
||||
"MagenticOrchestratorEventType",
|
||||
"MagenticPlanReviewRequest",
|
||||
"MagenticPlanReviewResponse",
|
||||
"MagenticProgressLedger",
|
||||
"MagenticProgressLedgerItem",
|
||||
"MagenticResetSignal",
|
||||
"StandardMagenticManager",
|
||||
]
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
if name in _IMPORTS:
|
||||
try:
|
||||
return getattr(importlib.import_module(IMPORT_PATH), name)
|
||||
except ModuleNotFoundError as exc:
|
||||
raise ModuleNotFoundError(
|
||||
f"The '{PACKAGE_NAME}' package is not installed, please do `pip install {PACKAGE_NAME}`"
|
||||
) from exc
|
||||
raise AttributeError(f"Module {IMPORT_PATH} has no attribute {name}.")
|
||||
|
||||
|
||||
def __dir__() -> list[str]:
|
||||
return _IMPORTS
|
||||
@@ -0,0 +1,141 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
# Type stubs for lazy-loaded orchestrations module
|
||||
# These re-export types from agent_framework_orchestrations
|
||||
|
||||
from agent_framework_orchestrations import (
|
||||
# Magentic
|
||||
MAGENTIC_MANAGER_NAME as MAGENTIC_MANAGER_NAME,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
ORCH_MSG_KIND_INSTRUCTION as ORCH_MSG_KIND_INSTRUCTION,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
ORCH_MSG_KIND_NOTICE as ORCH_MSG_KIND_NOTICE,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
ORCH_MSG_KIND_TASK_LEDGER as ORCH_MSG_KIND_TASK_LEDGER,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
ORCH_MSG_KIND_USER_TASK as ORCH_MSG_KIND_USER_TASK,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
# Group Chat
|
||||
AgentBasedGroupChatOrchestrator as AgentBasedGroupChatOrchestrator,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
AgentOrchestrationOutput as AgentOrchestrationOutput,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
# Concurrent
|
||||
ConcurrentBuilder as ConcurrentBuilder,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
GroupChatBuilder as GroupChatBuilder,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
GroupChatOrchestrator as GroupChatOrchestrator,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
GroupChatSelectionFunction as GroupChatSelectionFunction,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
GroupChatState as GroupChatState,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
# Handoff
|
||||
HandoffAgentExecutor as HandoffAgentExecutor,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
HandoffAgentUserRequest as HandoffAgentUserRequest,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
HandoffBuilder as HandoffBuilder,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
HandoffConfiguration as HandoffConfiguration,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
HandoffSentEvent as HandoffSentEvent,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticAgentExecutor as MagenticAgentExecutor,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticBuilder as MagenticBuilder,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticContext as MagenticContext,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticManagerBase as MagenticManagerBase,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticOrchestrator as MagenticOrchestrator,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticOrchestratorEvent as MagenticOrchestratorEvent,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticOrchestratorEventType as MagenticOrchestratorEventType,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticPlanReviewRequest as MagenticPlanReviewRequest,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticPlanReviewResponse as MagenticPlanReviewResponse,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticProgressLedger as MagenticProgressLedger,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticProgressLedgerItem as MagenticProgressLedgerItem,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
MagenticResetSignal as MagenticResetSignal,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
# Sequential
|
||||
SequentialBuilder as SequentialBuilder,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
StandardMagenticManager as StandardMagenticManager,
|
||||
)
|
||||
from agent_framework_orchestrations import (
|
||||
__version__ as __version__,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"MAGENTIC_MANAGER_NAME",
|
||||
"ORCH_MSG_KIND_INSTRUCTION",
|
||||
"ORCH_MSG_KIND_NOTICE",
|
||||
"ORCH_MSG_KIND_TASK_LEDGER",
|
||||
"ORCH_MSG_KIND_USER_TASK",
|
||||
"AgentBasedGroupChatOrchestrator",
|
||||
"AgentOrchestrationOutput",
|
||||
"ConcurrentBuilder",
|
||||
"GroupChatBuilder",
|
||||
"GroupChatOrchestrator",
|
||||
"GroupChatSelectionFunction",
|
||||
"GroupChatState",
|
||||
"HandoffAgentExecutor",
|
||||
"HandoffAgentUserRequest",
|
||||
"HandoffBuilder",
|
||||
"HandoffConfiguration",
|
||||
"HandoffSentEvent",
|
||||
"MagenticAgentExecutor",
|
||||
"MagenticBuilder",
|
||||
"MagenticContext",
|
||||
"MagenticManagerBase",
|
||||
"MagenticOrchestrator",
|
||||
"MagenticOrchestratorEvent",
|
||||
"MagenticOrchestratorEventType",
|
||||
"MagenticPlanReviewRequest",
|
||||
"MagenticPlanReviewResponse",
|
||||
"MagenticProgressLedger",
|
||||
"MagenticProgressLedgerItem",
|
||||
"MagenticResetSignal",
|
||||
"SequentialBuilder",
|
||||
"StandardMagenticManager",
|
||||
"__version__",
|
||||
]
|
||||
@@ -55,6 +55,7 @@ all = [
|
||||
"agent-framework-lab",
|
||||
"agent-framework-mem0",
|
||||
"agent-framework-ollama",
|
||||
"agent-framework-orchestrations",
|
||||
"agent-framework-purview",
|
||||
"agent-framework-redis",
|
||||
]
|
||||
|
||||
@@ -12,13 +12,13 @@ from agent_framework import (
|
||||
ChatMessage,
|
||||
ChatMessageStore,
|
||||
Content,
|
||||
SequentialBuilder,
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
)
|
||||
from agent_framework._workflows._agent_executor import AgentExecutorResponse
|
||||
from agent_framework._workflows._checkpoint import InMemoryCheckpointStorage
|
||||
from agent_framework.orchestrations import SequentialBuilder
|
||||
|
||||
|
||||
class _CountingAgent(BaseAgent):
|
||||
|
||||
@@ -16,13 +16,13 @@ from agent_framework import (
|
||||
ChatMessage,
|
||||
Content,
|
||||
Executor,
|
||||
SequentialBuilder,
|
||||
WorkflowBuilder,
|
||||
WorkflowContext,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
handler,
|
||||
)
|
||||
from agent_framework.orchestrations import SequentialBuilder
|
||||
|
||||
|
||||
class _SimpleAgent(BaseAgent):
|
||||
|
||||
@@ -11,17 +11,19 @@ from agent_framework import (
|
||||
AgentThread,
|
||||
BaseAgent,
|
||||
ChatMessage,
|
||||
ConcurrentBuilder,
|
||||
Content,
|
||||
GroupChatBuilder,
|
||||
GroupChatState,
|
||||
HandoffBuilder,
|
||||
SequentialBuilder,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
tool,
|
||||
)
|
||||
from agent_framework._workflows._const import WORKFLOW_RUN_KWARGS_KEY
|
||||
from agent_framework.orchestrations import (
|
||||
ConcurrentBuilder,
|
||||
GroupChatBuilder,
|
||||
GroupChatState,
|
||||
HandoffBuilder,
|
||||
SequentialBuilder,
|
||||
)
|
||||
|
||||
# Track kwargs received by tools during test execution
|
||||
_received_kwargs: list[dict[str, Any]] = []
|
||||
@@ -371,14 +373,15 @@ async def test_handoff_kwargs_flow_to_agents() -> None:
|
||||
|
||||
async def test_magentic_kwargs_flow_to_agents() -> None:
|
||||
"""Test that kwargs flow to agents in a magentic workflow via MagenticAgentExecutor."""
|
||||
from agent_framework import MagenticBuilder
|
||||
from agent_framework._workflows._magentic import (
|
||||
from agent_framework_orchestrations._magentic import (
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
)
|
||||
|
||||
from agent_framework.orchestrations import MagenticBuilder
|
||||
|
||||
# Create a mock manager that completes after one round
|
||||
class _MockManager(MagenticManagerBase):
|
||||
def __init__(self) -> None:
|
||||
@@ -422,14 +425,15 @@ async def test_magentic_kwargs_flow_to_agents() -> None:
|
||||
|
||||
async def test_magentic_kwargs_stored_in_state() -> None:
|
||||
"""Test that kwargs are stored in State when using MagenticWorkflow.run_stream()."""
|
||||
from agent_framework import MagenticBuilder
|
||||
from agent_framework._workflows._magentic import (
|
||||
from agent_framework_orchestrations._magentic import (
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
)
|
||||
|
||||
from agent_framework.orchestrations import MagenticBuilder
|
||||
|
||||
class _MockManager(MagenticManagerBase):
|
||||
def __init__(self) -> None:
|
||||
super().__init__(max_stall_count=3, max_reset_count=None, max_round_count=1)
|
||||
|
||||
@@ -27,13 +27,12 @@ from agent_framework import (
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
ConcurrentBuilder,
|
||||
Content,
|
||||
SequentialBuilder,
|
||||
use_chat_middleware,
|
||||
)
|
||||
from agent_framework._clients import TOptions_co
|
||||
from agent_framework._workflows._agent_executor import AgentExecutorResponse
|
||||
from agent_framework.orchestrations import ConcurrentBuilder, SequentialBuilder
|
||||
|
||||
if sys.version_info >= (3, 12):
|
||||
from typing import override # type: ignore # pragma: no cover
|
||||
|
||||
@@ -437,20 +437,20 @@ async def test_workflow_status_event(mapper: MessageMapper, test_request: AgentF
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Magentic Event Tests - Testing REAL AgentRunUpdateEvent with additional_properties
|
||||
# Magentic Event Tests - Testing WorkflowOutputEvent with additional_properties
|
||||
# =============================================================================
|
||||
|
||||
|
||||
async def test_magentic_agent_run_update_event_with_agent_delta_metadata(
|
||||
mapper: MessageMapper, test_request: AgentFrameworkRequest
|
||||
) -> None:
|
||||
"""Test that AgentRunUpdateEvent with magentic_event_type='agent_delta' is handled correctly.
|
||||
"""Test that WorkflowOutputEvent with magentic_event_type='agent_delta' is handled correctly.
|
||||
|
||||
This tests the ACTUAL event format Magentic emits - not a fake MagenticAgentDeltaEvent class.
|
||||
Magentic uses AgentRunUpdateEvent with additional_properties containing magentic_event_type.
|
||||
Magentic uses WorkflowOutputEvent wrapping AgentResponseUpdate with additional_properties.
|
||||
"""
|
||||
from agent_framework._types import AgentResponseUpdate
|
||||
from agent_framework._workflows._events import AgentRunUpdateEvent
|
||||
from agent_framework._workflows._events import WorkflowOutputEvent
|
||||
|
||||
# Create the REAL event format that Magentic emits
|
||||
update = AgentResponseUpdate(
|
||||
@@ -462,11 +462,11 @@ async def test_magentic_agent_run_update_event_with_agent_delta_metadata(
|
||||
"agent_id": "writer_agent",
|
||||
},
|
||||
)
|
||||
event = AgentRunUpdateEvent(executor_id="magentic_executor", data=update)
|
||||
event = WorkflowOutputEvent(executor_id="magentic_executor", data=update)
|
||||
|
||||
events = await mapper.convert_event(event, test_request)
|
||||
|
||||
# Should be treated as a regular AgentRunUpdateEvent with text content
|
||||
# Should be treated as a regular WorkflowOutputEvent with text content
|
||||
# The mapper should emit text delta events
|
||||
assert len(events) >= 1
|
||||
text_events = [e for e in events if getattr(e, "type", "") == "response.output_text.delta"]
|
||||
@@ -475,13 +475,13 @@ async def test_magentic_agent_run_update_event_with_agent_delta_metadata(
|
||||
|
||||
|
||||
async def test_magentic_orchestrator_message_event(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None:
|
||||
"""Test that AgentRunUpdateEvent with magentic_event_type='orchestrator_message' is handled.
|
||||
"""Test that WorkflowOutputEvent with magentic_event_type='orchestrator_message' is handled.
|
||||
|
||||
Magentic emits orchestrator planning/instruction messages using AgentRunUpdateEvent
|
||||
with additional_properties containing magentic_event_type='orchestrator_message'.
|
||||
Magentic emits orchestrator planning/instruction messages using WorkflowOutputEvent
|
||||
wrapping AgentResponseUpdate with additional_properties.
|
||||
"""
|
||||
from agent_framework._types import AgentResponseUpdate
|
||||
from agent_framework._workflows._events import AgentRunUpdateEvent
|
||||
from agent_framework._workflows._events import WorkflowOutputEvent
|
||||
|
||||
# Create orchestrator message event (REAL format from Magentic)
|
||||
update = AgentResponseUpdate(
|
||||
@@ -494,11 +494,11 @@ async def test_magentic_orchestrator_message_event(mapper: MessageMapper, test_r
|
||||
"orchestrator_id": "magentic_orchestrator",
|
||||
},
|
||||
)
|
||||
event = AgentRunUpdateEvent(executor_id="magentic_orchestrator", data=update)
|
||||
event = WorkflowOutputEvent(executor_id="magentic_orchestrator", data=update)
|
||||
|
||||
events = await mapper.convert_event(event, test_request)
|
||||
|
||||
# Currently, mapper treats this as regular AgentRunUpdateEvent (no special handling)
|
||||
# Currently, mapper treats this as regular WorkflowOutputEvent (no special handling)
|
||||
# This test documents the current behavior
|
||||
assert len(events) >= 1
|
||||
text_events = [e for e in events if getattr(e, "type", "") == "response.output_text.delta"]
|
||||
@@ -509,15 +509,15 @@ async def test_magentic_orchestrator_message_event(mapper: MessageMapper, test_r
|
||||
async def test_magentic_events_use_same_event_class_as_other_workflows(
|
||||
mapper: MessageMapper, test_request: AgentFrameworkRequest
|
||||
) -> None:
|
||||
"""Verify Magentic uses the same AgentRunUpdateEvent class as other workflows.
|
||||
"""Verify Magentic uses the same WorkflowOutputEvent class as other workflows.
|
||||
|
||||
This test documents that Magentic does NOT define separate event classes like
|
||||
MagenticAgentDeltaEvent - it reuses AgentRunUpdateEvent with metadata in
|
||||
MagenticAgentDeltaEvent - it reuses WorkflowOutputEvent with metadata in
|
||||
additional_properties. Any mapper code checking for 'MagenticAgentDeltaEvent'
|
||||
class names is dead code.
|
||||
"""
|
||||
from agent_framework._types import AgentResponseUpdate
|
||||
from agent_framework._workflows._events import AgentRunUpdateEvent
|
||||
from agent_framework._workflows._events import WorkflowOutputEvent
|
||||
|
||||
# Create events the way different workflows do it
|
||||
# 1. Regular workflow (no additional_properties)
|
||||
@@ -525,7 +525,7 @@ async def test_magentic_events_use_same_event_class_as_other_workflows(
|
||||
contents=[Content.from_text(text="Regular workflow response")],
|
||||
role="assistant",
|
||||
)
|
||||
regular_event = AgentRunUpdateEvent(executor_id="regular_executor", data=regular_update)
|
||||
regular_event = WorkflowOutputEvent(executor_id="regular_executor", data=regular_update)
|
||||
|
||||
# 2. Magentic workflow (with additional_properties)
|
||||
magentic_update = AgentResponseUpdate(
|
||||
@@ -533,12 +533,12 @@ async def test_magentic_events_use_same_event_class_as_other_workflows(
|
||||
role="assistant",
|
||||
additional_properties={"magentic_event_type": "agent_delta"},
|
||||
)
|
||||
magentic_event = AgentRunUpdateEvent(executor_id="magentic_executor", data=magentic_update)
|
||||
magentic_event = WorkflowOutputEvent(executor_id="magentic_executor", data=magentic_update)
|
||||
|
||||
# Both should be the SAME class
|
||||
assert type(regular_event) is type(magentic_event)
|
||||
assert isinstance(regular_event, AgentRunUpdateEvent)
|
||||
assert isinstance(magentic_event, AgentRunUpdateEvent)
|
||||
assert isinstance(regular_event, WorkflowOutputEvent)
|
||||
assert isinstance(magentic_event, WorkflowOutputEvent)
|
||||
|
||||
# Both should be handled by the same isinstance check in mapper
|
||||
regular_events = await mapper.convert_event(regular_event, test_request)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
@@ -0,0 +1,88 @@
|
||||
# Agent Framework Orchestrations
|
||||
|
||||
Orchestration patterns for Microsoft Agent Framework. This package provides high-level builders for common multi-agent workflow patterns.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install agent-framework-orchestrations
|
||||
```
|
||||
|
||||
## Orchestration Patterns
|
||||
|
||||
### SequentialBuilder
|
||||
|
||||
Chain agents/executors in sequence, passing conversation context along:
|
||||
|
||||
```python
|
||||
from agent_framework_orchestrations import SequentialBuilder
|
||||
|
||||
workflow = SequentialBuilder().participants([agent1, agent2, agent3]).build()
|
||||
```
|
||||
|
||||
### ConcurrentBuilder
|
||||
|
||||
Fan-out to multiple agents in parallel, then aggregate results:
|
||||
|
||||
```python
|
||||
from agent_framework_orchestrations import ConcurrentBuilder
|
||||
|
||||
workflow = ConcurrentBuilder().participants([agent1, agent2, agent3]).build()
|
||||
```
|
||||
|
||||
### HandoffBuilder
|
||||
|
||||
Decentralized agent routing where agents decide handoff targets:
|
||||
|
||||
```python
|
||||
from agent_framework_orchestrations import HandoffBuilder
|
||||
|
||||
workflow = (
|
||||
HandoffBuilder()
|
||||
.participants([triage, billing, support])
|
||||
.with_start_agent(triage)
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
### GroupChatBuilder
|
||||
|
||||
Orchestrator-directed multi-agent conversations:
|
||||
|
||||
```python
|
||||
from agent_framework_orchestrations import GroupChatBuilder
|
||||
|
||||
workflow = (
|
||||
GroupChatBuilder()
|
||||
.with_orchestrator(selection_func=my_selector)
|
||||
.participants([agent1, agent2])
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
### MagenticBuilder
|
||||
|
||||
Sophisticated multi-agent orchestration using the Magentic One pattern:
|
||||
|
||||
```python
|
||||
from agent_framework_orchestrations import MagenticBuilder
|
||||
|
||||
workflow = (
|
||||
MagenticBuilder()
|
||||
.participants([researcher, writer, reviewer])
|
||||
.with_manager(agent=manager_agent)
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
## Usage with agent_framework
|
||||
|
||||
You can also import orchestrations through the main agent_framework package:
|
||||
|
||||
```python
|
||||
from agent_framework.orchestrations import SequentialBuilder, ConcurrentBuilder
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
For more information, see the [Agent Framework documentation](https://aka.ms/agent-framework).
|
||||
@@ -0,0 +1,91 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
"""Orchestration patterns for Microsoft Agent Framework.
|
||||
|
||||
This package provides high-level builders for common multi-agent workflow patterns:
|
||||
- SequentialBuilder: Chain agents in sequence
|
||||
- ConcurrentBuilder: Fan-out to multiple agents in parallel
|
||||
- HandoffBuilder: Decentralized agent routing
|
||||
- GroupChatBuilder: Orchestrator-directed multi-agent conversations
|
||||
- MagenticBuilder: Magentic One pattern for sophisticated multi-agent orchestration
|
||||
"""
|
||||
|
||||
import importlib.metadata
|
||||
|
||||
try:
|
||||
__version__ = importlib.metadata.version(__name__)
|
||||
except importlib.metadata.PackageNotFoundError:
|
||||
__version__ = "0.0.0" # Fallback for development mode
|
||||
|
||||
from ._concurrent import ConcurrentBuilder
|
||||
from ._group_chat import (
|
||||
AgentBasedGroupChatOrchestrator,
|
||||
AgentOrchestrationOutput,
|
||||
GroupChatBuilder,
|
||||
GroupChatOrchestrator,
|
||||
GroupChatSelectionFunction,
|
||||
GroupChatState,
|
||||
)
|
||||
from ._handoff import (
|
||||
HandoffAgentExecutor,
|
||||
HandoffAgentUserRequest,
|
||||
HandoffBuilder,
|
||||
HandoffConfiguration,
|
||||
HandoffSentEvent,
|
||||
)
|
||||
from ._magentic import (
|
||||
MAGENTIC_MANAGER_NAME,
|
||||
ORCH_MSG_KIND_INSTRUCTION,
|
||||
ORCH_MSG_KIND_NOTICE,
|
||||
ORCH_MSG_KIND_TASK_LEDGER,
|
||||
ORCH_MSG_KIND_USER_TASK,
|
||||
MagenticAgentExecutor,
|
||||
MagenticBuilder,
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticOrchestrator,
|
||||
MagenticOrchestratorEvent,
|
||||
MagenticOrchestratorEventType,
|
||||
MagenticPlanReviewRequest,
|
||||
MagenticPlanReviewResponse,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
MagenticResetSignal,
|
||||
StandardMagenticManager,
|
||||
)
|
||||
from ._sequential import SequentialBuilder
|
||||
|
||||
__all__ = [
|
||||
"MAGENTIC_MANAGER_NAME",
|
||||
"ORCH_MSG_KIND_INSTRUCTION",
|
||||
"ORCH_MSG_KIND_NOTICE",
|
||||
"ORCH_MSG_KIND_TASK_LEDGER",
|
||||
"ORCH_MSG_KIND_USER_TASK",
|
||||
"AgentBasedGroupChatOrchestrator",
|
||||
"AgentOrchestrationOutput",
|
||||
"ConcurrentBuilder",
|
||||
"GroupChatBuilder",
|
||||
"GroupChatOrchestrator",
|
||||
"GroupChatSelectionFunction",
|
||||
"GroupChatState",
|
||||
"HandoffAgentExecutor",
|
||||
"HandoffAgentUserRequest",
|
||||
"HandoffBuilder",
|
||||
"HandoffConfiguration",
|
||||
"HandoffSentEvent",
|
||||
"MagenticAgentExecutor",
|
||||
"MagenticBuilder",
|
||||
"MagenticContext",
|
||||
"MagenticManagerBase",
|
||||
"MagenticOrchestrator",
|
||||
"MagenticOrchestratorEvent",
|
||||
"MagenticOrchestratorEventType",
|
||||
"MagenticPlanReviewRequest",
|
||||
"MagenticPlanReviewResponse",
|
||||
"MagenticProgressLedger",
|
||||
"MagenticProgressLedgerItem",
|
||||
"MagenticResetSignal",
|
||||
"SequentialBuilder",
|
||||
"StandardMagenticManager",
|
||||
"__version__",
|
||||
]
|
||||
+12
-14
@@ -6,19 +6,17 @@ import logging
|
||||
from collections.abc import Callable, Sequence
|
||||
from typing import Any
|
||||
|
||||
from typing_extensions import Never
|
||||
|
||||
from agent_framework import AgentProtocol, ChatMessage
|
||||
|
||||
from ._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from ._agent_utils import resolve_agent_id
|
||||
from ._checkpoint import CheckpointStorage
|
||||
from ._executor import Executor, handler
|
||||
from ._message_utils import normalize_messages_input
|
||||
from ._orchestration_request_info import AgentApprovalExecutor
|
||||
from ._workflow import Workflow
|
||||
from ._workflow_builder import WorkflowBuilder
|
||||
from ._workflow_context import WorkflowContext
|
||||
from agent_framework._workflows._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from agent_framework._workflows._agent_utils import resolve_agent_id
|
||||
from agent_framework._workflows._checkpoint import CheckpointStorage
|
||||
from agent_framework._workflows._executor import Executor, handler
|
||||
from agent_framework._workflows._message_utils import normalize_messages_input
|
||||
from agent_framework._workflows._orchestration_request_info import AgentApprovalExecutor
|
||||
from agent_framework._workflows._workflow import Workflow
|
||||
from agent_framework._workflows._workflow_builder import WorkflowBuilder
|
||||
from agent_framework._workflows._workflow_context import WorkflowContext
|
||||
from typing_extensions import Never
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -198,7 +196,7 @@ class ConcurrentBuilder:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import ConcurrentBuilder
|
||||
from agent_framework_orchestrations import ConcurrentBuilder
|
||||
|
||||
# Minimal: use default aggregator (returns list[ChatMessage])
|
||||
workflow = ConcurrentBuilder().participants([agent1, agent2, agent3]).build()
|
||||
@@ -483,7 +481,7 @@ class ConcurrentBuilder:
|
||||
Returns:
|
||||
Self for fluent chaining
|
||||
"""
|
||||
from ._orchestration_request_info import resolve_request_info_filter
|
||||
from agent_framework._workflows._orchestration_request_info import resolve_request_info_filter
|
||||
|
||||
self._request_info_enabled = True
|
||||
self._request_info_filter = resolve_request_info_filter(list(agents) if agents else None)
|
||||
+23
-22
@@ -26,15 +26,12 @@ from collections.abc import Awaitable, Callable, Sequence
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, ClassVar, cast, overload
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Never
|
||||
|
||||
from .._agents import AgentProtocol, ChatAgent
|
||||
from .._threads import AgentThread
|
||||
from .._types import ChatMessage
|
||||
from ._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from ._agent_utils import resolve_agent_id
|
||||
from ._base_group_chat_orchestrator import (
|
||||
from agent_framework import AgentProtocol, ChatAgent
|
||||
from agent_framework._threads import AgentThread
|
||||
from agent_framework._types import ChatMessage
|
||||
from agent_framework._workflows._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from agent_framework._workflows._agent_utils import resolve_agent_id
|
||||
from agent_framework._workflows._base_group_chat_orchestrator import (
|
||||
BaseGroupChatOrchestrator,
|
||||
GroupChatParticipantMessage,
|
||||
GroupChatRequestMessage,
|
||||
@@ -43,13 +40,15 @@ from ._base_group_chat_orchestrator import (
|
||||
ParticipantRegistry,
|
||||
TerminationCondition,
|
||||
)
|
||||
from ._checkpoint import CheckpointStorage
|
||||
from ._conversation_state import decode_chat_messages, encode_chat_messages
|
||||
from ._executor import Executor
|
||||
from ._orchestration_request_info import AgentApprovalExecutor
|
||||
from ._workflow import Workflow
|
||||
from ._workflow_builder import WorkflowBuilder
|
||||
from ._workflow_context import WorkflowContext
|
||||
from agent_framework._workflows._checkpoint import CheckpointStorage
|
||||
from agent_framework._workflows._conversation_state import decode_chat_messages, encode_chat_messages
|
||||
from agent_framework._workflows._executor import Executor
|
||||
from agent_framework._workflows._orchestration_request_info import AgentApprovalExecutor
|
||||
from agent_framework._workflows._workflow import Workflow
|
||||
from agent_framework._workflows._workflow_builder import WorkflowBuilder
|
||||
from agent_framework._workflows._workflow_context import WorkflowContext
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Never
|
||||
|
||||
if sys.version_info >= (3, 12):
|
||||
from typing import override # type: ignore # pragma: no cover
|
||||
@@ -134,7 +133,7 @@ class GroupChatOrchestrator(BaseGroupChatOrchestrator):
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import GroupChatOrchestrator
|
||||
from agent_framework_orchestrations import GroupChatOrchestrator
|
||||
|
||||
|
||||
async def round_robin_selector(state: GroupChatState) -> str:
|
||||
@@ -641,7 +640,7 @@ class GroupChatBuilder:
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import GroupChatBuilder
|
||||
from agent_framework_orchestrations import GroupChatBuilder
|
||||
|
||||
|
||||
orchestrator = CustomGroupChatOrchestrator(...)
|
||||
@@ -726,7 +725,7 @@ class GroupChatBuilder:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import GroupChatBuilder
|
||||
from agent_framework_orchestrations import GroupChatBuilder
|
||||
|
||||
workflow = (
|
||||
GroupChatBuilder()
|
||||
@@ -781,7 +780,8 @@ class GroupChatBuilder:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import ChatMessage, GroupChatBuilder, Role
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework_orchestrations import GroupChatBuilder
|
||||
|
||||
|
||||
def stop_after_two_calls(conversation: list[ChatMessage]) -> bool:
|
||||
@@ -840,7 +840,8 @@ class GroupChatBuilder:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import GroupChatBuilder, MemoryCheckpointStorage
|
||||
from agent_framework import MemoryCheckpointStorage
|
||||
from agent_framework_orchestrations import GroupChatBuilder
|
||||
|
||||
storage = MemoryCheckpointStorage()
|
||||
workflow = (
|
||||
@@ -876,7 +877,7 @@ class GroupChatBuilder:
|
||||
Returns:
|
||||
Self for fluent chaining
|
||||
"""
|
||||
from ._orchestration_request_info import resolve_request_info_filter
|
||||
from agent_framework._workflows._orchestration_request_info import resolve_request_info_filter
|
||||
|
||||
self._request_info_enabled = True
|
||||
self._request_info_filter = resolve_request_info_filter(list(agents) if agents else None)
|
||||
+23
-23
@@ -36,24 +36,23 @@ from collections.abc import Awaitable, Callable, Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, cast
|
||||
|
||||
from agent_framework import AgentProtocol, ChatAgent
|
||||
from agent_framework._middleware import FunctionInvocationContext, FunctionMiddleware
|
||||
from agent_framework._threads import AgentThread
|
||||
from agent_framework._tools import FunctionTool, tool
|
||||
from agent_framework._types import AgentResponse, AgentResponseUpdate, ChatMessage
|
||||
from agent_framework._workflows._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from agent_framework._workflows._agent_utils import resolve_agent_id
|
||||
from agent_framework._workflows._base_group_chat_orchestrator import TerminationCondition
|
||||
from agent_framework._workflows._checkpoint import CheckpointStorage
|
||||
from agent_framework._workflows._events import WorkflowEvent
|
||||
from agent_framework._workflows._orchestrator_helpers import clean_conversation_for_handoff
|
||||
from agent_framework._workflows._request_info_mixin import response_handler
|
||||
from agent_framework._workflows._workflow import Workflow
|
||||
from agent_framework._workflows._workflow_builder import WorkflowBuilder
|
||||
from agent_framework._workflows._workflow_context import WorkflowContext
|
||||
from typing_extensions import Never
|
||||
|
||||
from .._agents import AgentProtocol, ChatAgent
|
||||
from .._middleware import FunctionInvocationContext, FunctionMiddleware
|
||||
from .._threads import AgentThread
|
||||
from .._tools import FunctionTool, tool
|
||||
from .._types import AgentResponse, AgentResponseUpdate, ChatMessage
|
||||
from ._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from ._agent_utils import resolve_agent_id
|
||||
from ._base_group_chat_orchestrator import TerminationCondition
|
||||
from ._checkpoint import CheckpointStorage
|
||||
from ._events import WorkflowEvent
|
||||
from ._orchestrator_helpers import clean_conversation_for_handoff
|
||||
from ._request_info_mixin import response_handler
|
||||
from ._workflow import Workflow
|
||||
from ._workflow_builder import WorkflowBuilder
|
||||
from ._workflow_context import WorkflowContext
|
||||
|
||||
if sys.version_info >= (3, 12):
|
||||
from typing import override # type: ignore # pragma: no cover
|
||||
else:
|
||||
@@ -333,14 +332,14 @@ class HandoffAgentExecutor(AgentExecutor):
|
||||
|
||||
new_tools: list[FunctionTool[Any, Any]] = []
|
||||
for target in targets:
|
||||
tool = self._create_handoff_tool(target.target_id, target.description)
|
||||
if tool.name in existing_names:
|
||||
handoff_tool = self._create_handoff_tool(target.target_id, target.description)
|
||||
if handoff_tool.name in existing_names:
|
||||
raise ValueError(
|
||||
f"Agent '{resolve_agent_id(agent)}' already has a tool named '{tool.name}'. "
|
||||
f"Handoff tool name '{tool.name}' conflicts with existing tool."
|
||||
f"Agent '{resolve_agent_id(agent)}' already has a tool named '{handoff_tool.name}'. "
|
||||
f"Handoff tool name '{handoff_tool.name}' conflicts with existing tool."
|
||||
"Please rename the existing tool or modify the target agent ID to avoid conflicts."
|
||||
)
|
||||
new_tools.append(tool)
|
||||
new_tools.append(handoff_tool)
|
||||
|
||||
if new_tools:
|
||||
default_options["tools"] = existing_tools + new_tools # type: ignore[operator]
|
||||
@@ -654,7 +653,8 @@ class HandoffBuilder:
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import ChatAgent, HandoffBuilder
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework_orchestrations import HandoffBuilder
|
||||
|
||||
|
||||
def create_triage() -> ChatAgent:
|
||||
@@ -710,7 +710,7 @@ class HandoffBuilder:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import HandoffBuilder
|
||||
from agent_framework_orchestrations import HandoffBuilder
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
|
||||
client = OpenAIChatClient()
|
||||
+11
-13
@@ -12,16 +12,13 @@ from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Any, ClassVar, TypeVar, cast, overload
|
||||
|
||||
from typing_extensions import Never
|
||||
|
||||
from agent_framework import (
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
ChatMessage,
|
||||
)
|
||||
|
||||
from ._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from ._base_group_chat_orchestrator import (
|
||||
from agent_framework._workflows._agent_executor import AgentExecutor, AgentExecutorRequest, AgentExecutorResponse
|
||||
from agent_framework._workflows._base_group_chat_orchestrator import (
|
||||
BaseGroupChatOrchestrator,
|
||||
GroupChatParticipantMessage,
|
||||
GroupChatRequestMessage,
|
||||
@@ -29,14 +26,15 @@ from ._base_group_chat_orchestrator import (
|
||||
GroupChatWorkflowContextOutT,
|
||||
ParticipantRegistry,
|
||||
)
|
||||
from ._checkpoint import CheckpointStorage
|
||||
from ._events import ExecutorEvent
|
||||
from ._executor import Executor, handler
|
||||
from ._model_utils import DictConvertible, encode_value
|
||||
from ._request_info_mixin import response_handler
|
||||
from ._workflow import Workflow
|
||||
from ._workflow_builder import WorkflowBuilder
|
||||
from ._workflow_context import WorkflowContext
|
||||
from agent_framework._workflows._checkpoint import CheckpointStorage
|
||||
from agent_framework._workflows._events import ExecutorEvent
|
||||
from agent_framework._workflows._executor import Executor, handler
|
||||
from agent_framework._workflows._model_utils import DictConvertible, encode_value
|
||||
from agent_framework._workflows._request_info_mixin import response_handler
|
||||
from agent_framework._workflows._workflow import Workflow
|
||||
from agent_framework._workflows._workflow_builder import WorkflowBuilder
|
||||
from agent_framework._workflows._workflow_context import WorkflowContext
|
||||
from typing_extensions import Never
|
||||
|
||||
if sys.version_info >= (3, 12):
|
||||
from typing import override # type: ignore # pragma: no cover
|
||||
+11
-12
@@ -42,22 +42,21 @@ from collections.abc import Callable, Sequence
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import AgentProtocol, ChatMessage
|
||||
|
||||
from ._agent_executor import (
|
||||
from agent_framework._workflows._agent_executor import (
|
||||
AgentExecutor,
|
||||
AgentExecutorResponse,
|
||||
)
|
||||
from ._agent_utils import resolve_agent_id
|
||||
from ._checkpoint import CheckpointStorage
|
||||
from ._executor import (
|
||||
from agent_framework._workflows._agent_utils import resolve_agent_id
|
||||
from agent_framework._workflows._checkpoint import CheckpointStorage
|
||||
from agent_framework._workflows._executor import (
|
||||
Executor,
|
||||
handler,
|
||||
)
|
||||
from ._message_utils import normalize_messages_input
|
||||
from ._orchestration_request_info import AgentApprovalExecutor
|
||||
from ._workflow import Workflow
|
||||
from ._workflow_builder import WorkflowBuilder
|
||||
from ._workflow_context import WorkflowContext
|
||||
from agent_framework._workflows._message_utils import normalize_messages_input
|
||||
from agent_framework._workflows._orchestration_request_info import AgentApprovalExecutor
|
||||
from agent_framework._workflows._workflow import Workflow
|
||||
from agent_framework._workflows._workflow_builder import WorkflowBuilder
|
||||
from agent_framework._workflows._workflow_context import WorkflowContext
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -122,7 +121,7 @@ class SequentialBuilder:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from agent_framework import SequentialBuilder
|
||||
from agent_framework_orchestrations import SequentialBuilder
|
||||
|
||||
# With agent instances
|
||||
workflow = SequentialBuilder().participants([agent1, agent2, summarizer_exec]).build()
|
||||
@@ -236,7 +235,7 @@ class SequentialBuilder:
|
||||
Returns:
|
||||
Self for fluent chaining
|
||||
"""
|
||||
from ._orchestration_request_info import resolve_request_info_filter
|
||||
from agent_framework._workflows._orchestration_request_info import resolve_request_info_filter
|
||||
|
||||
self._request_info_enabled = True
|
||||
self._request_info_filter = resolve_request_info_filter(list(agents) if agents else None)
|
||||
@@ -0,0 +1,87 @@
|
||||
[project]
|
||||
name = "agent-framework-orchestrations"
|
||||
description = "Orchestration patterns for Microsoft Agent Framework. Includes SequentialBuilder, ConcurrentBuilder, HandoffBuilder, GroupChatBuilder, and MagenticBuilder."
|
||||
authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
version = "1.0.0b260130"
|
||||
license-files = ["LICENSE"]
|
||||
urls.homepage = "https://aka.ms/agent-framework"
|
||||
urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
|
||||
urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true"
|
||||
urls.issues = "https://github.com/microsoft/agent-framework/issues"
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
"Typing :: Typed",
|
||||
]
|
||||
dependencies = [
|
||||
"agent-framework-core",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
prerelease = "if-necessary-or-explicit"
|
||||
environments = [
|
||||
"sys_platform == 'darwin'",
|
||||
"sys_platform == 'linux'",
|
||||
"sys_platform == 'win32'"
|
||||
]
|
||||
|
||||
[tool.uv-dynamic-versioning]
|
||||
fallback-version = "0.0.0"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = 'tests'
|
||||
addopts = "-ra -q -r fEX"
|
||||
asyncio_mode = "auto"
|
||||
asyncio_default_fixture_loop_scope = "function"
|
||||
filterwarnings = []
|
||||
timeout = 120
|
||||
|
||||
[tool.ruff]
|
||||
extend = "../../pyproject.toml"
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = [
|
||||
"**/__init__.py"
|
||||
]
|
||||
|
||||
[tool.pyright]
|
||||
extends = "../../pyproject.toml"
|
||||
exclude = ['tests']
|
||||
|
||||
[tool.mypy]
|
||||
plugins = ['pydantic.mypy']
|
||||
strict = true
|
||||
python_version = "3.10"
|
||||
ignore_missing_imports = true
|
||||
disallow_untyped_defs = true
|
||||
no_implicit_optional = true
|
||||
check_untyped_defs = true
|
||||
warn_return_any = true
|
||||
show_error_codes = true
|
||||
warn_unused_ignores = false
|
||||
disallow_incomplete_defs = true
|
||||
disallow_untyped_decorators = true
|
||||
|
||||
[tool.bandit]
|
||||
targets = ["agent_framework_orchestrations"]
|
||||
exclude_dirs = ["tests"]
|
||||
|
||||
[tool.poe]
|
||||
executor.type = "uv"
|
||||
include = "../../shared_tasks.toml"
|
||||
[tool.poe.tasks]
|
||||
mypy = "mypy --config-file $POE_ROOT/pyproject.toml agent_framework_orchestrations"
|
||||
test = "pytest --cov=agent_framework_orchestrations --cov-report=term-missing:skip-covered tests"
|
||||
|
||||
[build-system]
|
||||
requires = ["flit-core >= 3.11,<4.0"]
|
||||
build-backend = "flit_core.buildapi"
|
||||
+2
-3
@@ -3,14 +3,11 @@
|
||||
from typing import Any, cast
|
||||
|
||||
import pytest
|
||||
from typing_extensions import Never
|
||||
|
||||
from agent_framework import (
|
||||
AgentExecutorRequest,
|
||||
AgentExecutorResponse,
|
||||
AgentResponse,
|
||||
ChatMessage,
|
||||
ConcurrentBuilder,
|
||||
Executor,
|
||||
WorkflowContext,
|
||||
WorkflowOutputEvent,
|
||||
@@ -19,6 +16,8 @@ from agent_framework import (
|
||||
handler,
|
||||
)
|
||||
from agent_framework._workflows._checkpoint import InMemoryCheckpointStorage
|
||||
from agent_framework.orchestrations import ConcurrentBuilder
|
||||
from typing_extensions import Never
|
||||
|
||||
|
||||
class _FakeAgentExec(Executor):
|
||||
+9
-8
@@ -4,7 +4,6 @@ from collections.abc import AsyncIterable, Callable, Sequence
|
||||
from typing import Any, cast
|
||||
|
||||
import pytest
|
||||
|
||||
from agent_framework import (
|
||||
AgentExecutorResponse,
|
||||
AgentRequestInfoResponse,
|
||||
@@ -18,18 +17,20 @@ from agent_framework import (
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
GroupChatBuilder,
|
||||
GroupChatState,
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
RequestInfoEvent,
|
||||
WorkflowOutputEvent,
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
)
|
||||
from agent_framework._workflows._checkpoint import InMemoryCheckpointStorage
|
||||
from agent_framework.orchestrations import (
|
||||
GroupChatBuilder,
|
||||
GroupChatState,
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
)
|
||||
|
||||
|
||||
class StubAgent(BaseAgent):
|
||||
@@ -1186,7 +1187,7 @@ def test_group_chat_with_orchestrator_factory_returning_base_orchestrator():
|
||||
nonlocal factory_call_count
|
||||
factory_call_count += 1
|
||||
from agent_framework._workflows._base_group_chat_orchestrator import ParticipantRegistry
|
||||
from agent_framework._workflows._group_chat import GroupChatOrchestrator
|
||||
from agent_framework.orchestrations import GroupChatOrchestrator
|
||||
|
||||
# Create a custom orchestrator; when returning BaseGroupChatOrchestrator,
|
||||
# the builder uses it as-is without modifying its participant registry
|
||||
+1
-3
@@ -5,21 +5,19 @@ from typing import Any, cast
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from agent_framework import (
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
HandoffAgentUserRequest,
|
||||
HandoffBuilder,
|
||||
RequestInfoEvent,
|
||||
WorkflowEvent,
|
||||
WorkflowOutputEvent,
|
||||
resolve_agent_id,
|
||||
use_function_invocation,
|
||||
)
|
||||
from agent_framework.orchestrations import HandoffAgentUserRequest, HandoffBuilder
|
||||
|
||||
|
||||
@use_function_invocation
|
||||
+13
-12
@@ -6,7 +6,6 @@ from dataclasses import dataclass
|
||||
from typing import Any, ClassVar, cast
|
||||
|
||||
import pytest
|
||||
|
||||
from agent_framework import (
|
||||
AgentProtocol,
|
||||
AgentResponse,
|
||||
@@ -17,16 +16,7 @@ from agent_framework import (
|
||||
Content,
|
||||
Executor,
|
||||
GroupChatRequestMessage,
|
||||
MagenticBuilder,
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticOrchestrator,
|
||||
MagenticOrchestratorEvent,
|
||||
MagenticPlanReviewRequest,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
RequestInfoEvent,
|
||||
StandardMagenticManager,
|
||||
Workflow,
|
||||
WorkflowCheckpoint,
|
||||
WorkflowCheckpointException,
|
||||
@@ -38,6 +28,17 @@ from agent_framework import (
|
||||
handler,
|
||||
)
|
||||
from agent_framework._workflows._checkpoint import InMemoryCheckpointStorage
|
||||
from agent_framework.orchestrations import (
|
||||
MagenticBuilder,
|
||||
MagenticContext,
|
||||
MagenticManagerBase,
|
||||
MagenticOrchestrator,
|
||||
MagenticOrchestratorEvent,
|
||||
MagenticPlanReviewRequest,
|
||||
MagenticProgressLedger,
|
||||
MagenticProgressLedgerItem,
|
||||
StandardMagenticManager,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 12):
|
||||
from typing import override # type: ignore # pragma: no cover
|
||||
@@ -1246,7 +1247,7 @@ def test_magentic_agent_factory_with_standard_manager_options():
|
||||
custom_final_prompt = "Custom final: {task}"
|
||||
|
||||
# Create a custom task ledger
|
||||
from agent_framework._workflows._magentic import _MagenticTaskLedger # type: ignore
|
||||
from agent_framework_orchestrations._magentic import _MagenticTaskLedger # type: ignore
|
||||
|
||||
custom_task_ledger = _MagenticTaskLedger(
|
||||
facts=ChatMessage("assistant", ["Custom facts"]),
|
||||
@@ -1282,7 +1283,7 @@ def test_magentic_agent_factory_with_standard_manager_options():
|
||||
manager = orchestrator._manager # type: ignore[reportPrivateUsage]
|
||||
|
||||
# Verify the manager is a StandardMagenticManager with the expected options
|
||||
from agent_framework import StandardMagenticManager
|
||||
from agent_framework.orchestrations import StandardMagenticManager
|
||||
|
||||
assert isinstance(manager, StandardMagenticManager)
|
||||
assert manager.task_ledger is custom_task_ledger
|
||||
+1
-2
@@ -4,7 +4,6 @@ from collections.abc import AsyncIterable
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from agent_framework import (
|
||||
AgentExecutorResponse,
|
||||
AgentResponse,
|
||||
@@ -14,7 +13,6 @@ from agent_framework import (
|
||||
ChatMessage,
|
||||
Content,
|
||||
Executor,
|
||||
SequentialBuilder,
|
||||
TypeCompatibilityError,
|
||||
WorkflowContext,
|
||||
WorkflowOutputEvent,
|
||||
@@ -23,6 +21,7 @@ from agent_framework import (
|
||||
handler,
|
||||
)
|
||||
from agent_framework._workflows._checkpoint import InMemoryCheckpointStorage
|
||||
from agent_framework.orchestrations import SequentialBuilder
|
||||
|
||||
|
||||
class _EchoAgent(BaseAgent):
|
||||
@@ -104,6 +104,7 @@ agent-framework-purview = { workspace = true }
|
||||
agent-framework-redis = { workspace = true }
|
||||
agent-framework-github-copilot = { workspace = true }
|
||||
agent-framework-claude = { workspace = true }
|
||||
agent-framework-orchestrations = { workspace = true }
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
@@ -253,6 +254,7 @@ pytest --import-mode=importlib
|
||||
--cov=agent_framework_mem0
|
||||
--cov=agent_framework_purview
|
||||
--cov=agent_framework_redis
|
||||
--cov=agent_framework_orchestrations
|
||||
--cov-config=pyproject.toml
|
||||
--cov-report=term-missing:skip-covered
|
||||
--ignore-glob=packages/lab/**
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# Orchestration Getting Started Samples
|
||||
|
||||
## Installation
|
||||
|
||||
The orchestrations package is included when you install `agent-framework` (which pulls in all optional packages):
|
||||
|
||||
```bash
|
||||
pip install agent-framework
|
||||
```
|
||||
|
||||
Or install the orchestrations package directly:
|
||||
|
||||
```bash
|
||||
pip install agent-framework-orchestrations
|
||||
```
|
||||
|
||||
Orchestration builders are available via the `agent_framework.orchestrations` submodule:
|
||||
|
||||
```python
|
||||
from agent_framework.orchestrations import (
|
||||
SequentialBuilder,
|
||||
ConcurrentBuilder,
|
||||
HandoffBuilder,
|
||||
GroupChatBuilder,
|
||||
MagenticBuilder,
|
||||
)
|
||||
```
|
||||
|
||||
## Samples Overview
|
||||
|
||||
| Sample | File | Concepts |
|
||||
| ------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| Concurrent Orchestration (Default Aggregator) | [concurrent_agents.py](./concurrent_agents.py) | Fan-out to multiple agents; fan-in with default aggregator returning combined ChatMessages |
|
||||
| Concurrent Orchestration (Custom Aggregator) | [concurrent_custom_aggregator.py](./concurrent_custom_aggregator.py) | Override aggregator via callback; summarize results with an LLM |
|
||||
| Concurrent Orchestration (Custom Agent Executors) | [concurrent_custom_agent_executors.py](./concurrent_custom_agent_executors.py) | Child executors own ChatAgents; concurrent fan-out/fan-in via ConcurrentBuilder |
|
||||
| Concurrent Orchestration (Participant Factory) | [concurrent_participant_factory.py](./concurrent_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
| Group Chat with Agent Manager | [group_chat_agent_manager.py](./group_chat_agent_manager.py) | Agent-based manager using `with_orchestrator(agent=)` to select next speaker |
|
||||
| Group Chat Philosophical Debate | [group_chat_philosophical_debate.py](./group_chat_philosophical_debate.py) | Agent manager moderates long-form, multi-round debate across diverse participants |
|
||||
| Group Chat with Simple Function Selector | [group_chat_simple_selector.py](./group_chat_simple_selector.py) | Group chat with a simple function selector for next speaker |
|
||||
| Handoff (Simple) | [handoff_simple.py](./handoff_simple.py) | Single-tier routing: triage agent routes to specialists, control returns to user after each specialist response |
|
||||
| Handoff (Autonomous) | [handoff_autonomous.py](./handoff_autonomous.py) | Autonomous mode: specialists iterate independently until invoking a handoff tool using `.with_autonomous_mode()` |
|
||||
| Handoff (Participant Factory) | [handoff_participant_factory.py](./handoff_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
| Handoff with Code Interpreter | [handoff_with_code_interpreter_file.py](./handoff_with_code_interpreter_file.py) | Retrieve file IDs from code interpreter output in handoff workflow |
|
||||
| Magentic Workflow (Multi-Agent) | [magentic.py](./magentic.py) | Orchestrate multiple agents with Magentic manager and streaming |
|
||||
| Magentic + Human Plan Review | [magentic_human_plan_review.py](./magentic_human_plan_review.py) | Human reviews/updates the plan before execution |
|
||||
| Magentic + Checkpoint Resume | [magentic_checkpoint.py](./magentic_checkpoint.py) | Resume Magentic orchestration from saved checkpoints |
|
||||
| Sequential Orchestration (Agents) | [sequential_agents.py](./sequential_agents.py) | Chain agents sequentially with shared conversation context |
|
||||
| Sequential Orchestration (Custom Executor) | [sequential_custom_executors.py](./sequential_custom_executors.py) | Mix agents with a summarizer that appends a compact summary |
|
||||
| Sequential Orchestration (Participant Factories) | [sequential_participant_factory.py](./sequential_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
|
||||
## Tips
|
||||
|
||||
**Magentic checkpointing tip**: Treat `MagenticBuilder.participants` keys as stable identifiers. When resuming from a checkpoint, the rebuilt workflow must reuse the same participant names; otherwise the checkpoint cannot be applied and the run will fail fast.
|
||||
|
||||
**Handoff workflow tip**: Handoff workflows maintain the full conversation history including any `ChatMessage.additional_properties` emitted by your agents. This ensures routing metadata remains intact across all agent transitions. For specialist-to-specialist handoffs, use `.add_handoff(source, targets)` to configure which agents can route to which others with a fluent, type-safe API.
|
||||
|
||||
**Sequential orchestration note**: Sequential orchestration uses a few small adapter nodes for plumbing:
|
||||
- `input-conversation` normalizes input to `list[ChatMessage]`
|
||||
- `to-conversation:<participant>` converts agent responses into the shared conversation
|
||||
- `complete` publishes the final `WorkflowOutputEvent`
|
||||
|
||||
These may appear in event streams (ExecutorInvoke/Completed). They're analogous to concurrent's dispatcher and aggregator and can be ignored if you only care about agent activity.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- **AzureOpenAIChatClient**: Set Azure OpenAI environment variables as documented [here](https://github.com/microsoft/agent-framework/blob/main/python/samples/getting_started/chat_client/README.md#environment-variables).
|
||||
|
||||
- **OpenAI** (used in some orchestration samples):
|
||||
- [OpenAIChatClient env vars](https://github.com/microsoft/agent-framework/blob/main/python/samples/getting_started/agents/openai_chat_client/README.md)
|
||||
- [OpenAIResponsesClient env vars](https://github.com/microsoft/agent-framework/blob/main/python/samples/getting_started/agents/openai_responses_client/README.md)
|
||||
+2
-1
@@ -3,8 +3,9 @@
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import ChatMessage, ConcurrentBuilder
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import ConcurrentBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+1
-1
@@ -8,12 +8,12 @@ from agent_framework import (
|
||||
AgentExecutorResponse,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
ConcurrentBuilder,
|
||||
Executor,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import ConcurrentBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+2
-1
@@ -3,8 +3,9 @@
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import ChatMessage, ConcurrentBuilder
|
||||
from agent_framework import ChatMessage
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import ConcurrentBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+1
-1
@@ -6,13 +6,13 @@ from typing import Any, Never
|
||||
from agent_framework import (
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
ConcurrentBuilder,
|
||||
Executor,
|
||||
Workflow,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import ConcurrentBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+1
-1
@@ -7,10 +7,10 @@ from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
GroupChatBuilder,
|
||||
WorkflowOutputEvent,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import GroupChatBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+7
-1
@@ -4,8 +4,14 @@ import asyncio
|
||||
import logging
|
||||
from typing import cast
|
||||
|
||||
from agent_framework import AgentResponseUpdate, ChatAgent, ChatMessage, GroupChatBuilder, WorkflowOutputEvent
|
||||
from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
WorkflowOutputEvent,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import GroupChatBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
+1
-2
@@ -7,11 +7,10 @@ from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
GroupChatBuilder,
|
||||
GroupChatState,
|
||||
WorkflowOutputEvent,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import GroupChatBuilder, GroupChatState
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+1
-3
@@ -8,13 +8,12 @@ from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
HandoffBuilder,
|
||||
HandoffSentEvent,
|
||||
HostedWebSearchTool,
|
||||
WorkflowOutputEvent,
|
||||
resolve_agent_id,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import HandoffBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
logging.basicConfig(level=logging.ERROR)
|
||||
@@ -61,7 +60,6 @@ def create_agents(
|
||||
"coordinator. Keep each individual response focused on one aspect."
|
||||
),
|
||||
name="research_agent",
|
||||
tools=[HostedWebSearchTool()],
|
||||
)
|
||||
|
||||
summary_agent = chat_client.as_agent(
|
||||
+1
-3
@@ -8,9 +8,6 @@ from agent_framework import (
|
||||
AgentResponse,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
HandoffAgentUserRequest,
|
||||
HandoffBuilder,
|
||||
HandoffSentEvent,
|
||||
RequestInfoEvent,
|
||||
Workflow,
|
||||
WorkflowEvent,
|
||||
@@ -20,6 +17,7 @@ from agent_framework import (
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import HandoffAgentUserRequest, HandoffBuilder, HandoffSentEvent
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
logging.basicConfig(level=logging.ERROR)
|
||||
+1
-3
@@ -7,9 +7,6 @@ from agent_framework import (
|
||||
AgentResponse,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
HandoffAgentUserRequest,
|
||||
HandoffBuilder,
|
||||
HandoffSentEvent,
|
||||
RequestInfoEvent,
|
||||
WorkflowEvent,
|
||||
WorkflowOutputEvent,
|
||||
@@ -18,6 +15,7 @@ from agent_framework import (
|
||||
tool,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import HandoffAgentUserRequest, HandoffBuilder, HandoffSentEvent
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""Sample: Simple handoff workflow.
|
||||
+1
-2
@@ -34,8 +34,6 @@ from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
HandoffAgentUserRequest,
|
||||
HandoffBuilder,
|
||||
HandoffSentEvent,
|
||||
HostedCodeInterpreterTool,
|
||||
RequestInfoEvent,
|
||||
@@ -44,6 +42,7 @@ from agent_framework import (
|
||||
WorkflowRunState,
|
||||
WorkflowStatusEvent,
|
||||
)
|
||||
from agent_framework.orchestrations import HandoffAgentUserRequest, HandoffBuilder
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
# Toggle between V1 (AzureAIAgentClient) and V2 (AzureAIClient)
|
||||
+1
-3
@@ -11,12 +11,10 @@ from agent_framework import (
|
||||
ChatMessage,
|
||||
GroupChatRequestSentEvent,
|
||||
HostedCodeInterpreterTool,
|
||||
MagenticBuilder,
|
||||
MagenticOrchestratorEvent,
|
||||
MagenticProgressLedger,
|
||||
WorkflowOutputEvent,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient, OpenAIResponsesClient
|
||||
from agent_framework.orchestrations import MagenticBuilder, MagenticOrchestratorEvent, MagenticProgressLedger
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logger = logging.getLogger(__name__)
|
||||
+1
-2
@@ -9,8 +9,6 @@ from agent_framework import (
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
FileCheckpointStorage,
|
||||
MagenticBuilder,
|
||||
MagenticPlanReviewRequest,
|
||||
RequestInfoEvent,
|
||||
WorkflowCheckpoint,
|
||||
WorkflowOutputEvent,
|
||||
@@ -18,6 +16,7 @@ from agent_framework import (
|
||||
WorkflowStatusEvent,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import MagenticBuilder, MagenticPlanReviewRequest
|
||||
from azure.identity._credentials import AzureCliCredential
|
||||
|
||||
"""
|
||||
+1
-3
@@ -9,14 +9,12 @@ from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
MagenticBuilder,
|
||||
MagenticPlanReviewRequest,
|
||||
MagenticPlanReviewResponse,
|
||||
RequestInfoEvent,
|
||||
WorkflowEvent,
|
||||
WorkflowOutputEvent,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from agent_framework.orchestrations import MagenticBuilder, MagenticPlanReviewRequest, MagenticPlanReviewResponse
|
||||
|
||||
"""
|
||||
Sample: Magentic Orchestration with Human Plan Review
|
||||
+2
-1
@@ -3,8 +3,9 @@
|
||||
import asyncio
|
||||
from typing import cast
|
||||
|
||||
from agent_framework import ChatMessage, SequentialBuilder, WorkflowOutputEvent
|
||||
from agent_framework import ChatMessage, WorkflowOutputEvent
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import SequentialBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+1
-1
@@ -7,11 +7,11 @@ from agent_framework import (
|
||||
AgentExecutorResponse,
|
||||
ChatMessage,
|
||||
Executor,
|
||||
SequentialBuilder,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import SequentialBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
+1
-1
@@ -6,12 +6,12 @@ from agent_framework import (
|
||||
ChatAgent,
|
||||
ChatMessage,
|
||||
Executor,
|
||||
SequentialBuilder,
|
||||
Workflow,
|
||||
WorkflowContext,
|
||||
handler,
|
||||
)
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.orchestrations import SequentialBuilder
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
"""
|
||||
@@ -108,31 +108,7 @@ For additional observability samples in Agent Framework, see the [observability
|
||||
|
||||
### orchestration
|
||||
|
||||
| Sample | File | Concepts |
|
||||
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| Concurrent Orchestration (Default Aggregator) | [orchestration/concurrent_agents.py](./orchestration/concurrent_agents.py) | Fan-out to multiple agents; fan-in with default aggregator returning combined ChatMessages |
|
||||
| Concurrent Orchestration (Custom Aggregator) | [orchestration/concurrent_custom_aggregator.py](./orchestration/concurrent_custom_aggregator.py) | Override aggregator via callback; summarize results with an LLM |
|
||||
| Concurrent Orchestration (Custom Agent Executors) | [orchestration/concurrent_custom_agent_executors.py](./orchestration/concurrent_custom_agent_executors.py) | Child executors own ChatAgents; concurrent fan-out/fan-in via ConcurrentBuilder |
|
||||
| Concurrent Orchestration (Participant Factory) | [orchestration/concurrent_participant_factory.py](./orchestration/concurrent_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
| Group Chat with Agent Manager | [orchestration/group_chat_agent_manager.py](./orchestration/group_chat_agent_manager.py) | Agent-based manager using `with_orchestrator(agent=)` to select next speaker |
|
||||
| Group Chat Philosophical Debate | [orchestration/group_chat_philosophical_debate.py](./orchestration/group_chat_philosophical_debate.py) | Agent manager moderates long-form, multi-round debate across diverse participants |
|
||||
| Group Chat with Simple Function Selector | [orchestration/group_chat_simple_selector.py](./orchestration/group_chat_simple_selector.py) | Group chat with a simple function selector for next speaker |
|
||||
| Handoff (Simple) | [orchestration/handoff_simple.py](./orchestration/handoff_simple.py) | Single-tier routing: triage agent routes to specialists, control returns to user after each specialist response |
|
||||
| Handoff (Autonomous) | [orchestration/handoff_autonomous.py](./orchestration/handoff_autonomous.py) | Autonomous mode: specialists iterate independently until invoking a handoff tool using `.with_autonomous_mode()` |
|
||||
| Handoff (Participant Factory) | [orchestration/handoff_participant_factory.py](./orchestration/handoff_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
| Magentic Workflow (Multi-Agent) | [orchestration/magentic.py](./orchestration/magentic.py) | Orchestrate multiple agents with Magentic manager and streaming |
|
||||
| Magentic + Human Plan Review | [orchestration/magentic_human_plan_review.py](./orchestration/magentic_human_plan_review.py) | Human reviews/updates the plan before execution |
|
||||
| Magentic + Checkpoint Resume | [orchestration/magentic_checkpoint.py](./orchestration/magentic_checkpoint.py) | Resume Magentic orchestration from saved checkpoints |
|
||||
| Sequential Orchestration (Agents) | [orchestration/sequential_agents.py](./orchestration/sequential_agents.py) | Chain agents sequentially with shared conversation context |
|
||||
| Sequential Orchestration (Custom Executor) | [orchestration/sequential_custom_executors.py](./orchestration/sequential_custom_executors.py) | Mix agents with a summarizer that appends a compact summary |
|
||||
| Sequential Orchestration (Participant Factories) | [orchestration/sequential_participant_factory.py](./orchestration/sequential_participant_factory.py) | Use participant factories for state isolation between workflow instances |
|
||||
|
||||
**Magentic checkpointing tip**: Treat `MagenticBuilder.participants` keys as stable identifiers. When resuming from a checkpoint, the rebuilt workflow must reuse the same participant names; otherwise the checkpoint cannot be applied and the run will fail fast.
|
||||
|
||||
**Handoff workflow tip**: Handoff workflows maintain the full conversation history including any
|
||||
`ChatMessage.additional_properties` emitted by your agents. This ensures routing metadata remains
|
||||
intact across all agent transitions. For specialist-to-specialist handoffs, use `.add_handoff(source, targets)`
|
||||
to configure which agents can route to which others with a fluent, type-safe API.
|
||||
Orchestration samples (Sequential, Concurrent, Handoff, GroupChat, Magentic) have moved to the dedicated [orchestrations samples directory](../orchestrations/README.md).
|
||||
|
||||
### parallelism
|
||||
|
||||
|
||||
Generated
+465
-458
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user