Skip to content

Python: Multi-agent orchestration: Magentic #12104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
May 16, 2025
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion python/.cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"logit",
"logprobs",
"lowlevel",
"Magentic",
"mistralai",
"mongocluster",
"nd",
Expand Down Expand Up @@ -77,4 +78,4 @@
"vertexai",
"Weaviate"
]
}
}
29 changes: 15 additions & 14 deletions python/samples/getting_started_with_agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,6 @@ Example|Description

_Note: For details on configuring an Azure AI Agent, please see [here](../getting_started_with_agents/azure_ai_agent/README.md)._

## Multi Agent Orchestration

Example|Description
---|---
[step1_concurrent](../getting_started_with_agents/multi_agent_orchestration/step1_concurrent.py)|How to run multiple agents concurrently and manage their output.
[step1a_concurrent_structure_output](../getting_started_with_agents/multi_agent_orchestration/step1a_concurrent_structure_output.py)|How to run concurrent agents that return structured outputs.
[step2_sequential](../getting_started_with_agents/multi_agent_orchestration/step2_sequential.py)|How to run agents sequentially where each one depends on the previous.
[step2a_sequential_cancellation_token](../getting_started_with_agents/multi_agent_orchestration/step2a_sequential_cancellation_token.py)|How to use cancellation tokens in a sequential agent flow.
[step3_group_chat](../getting_started_with_agents/multi_agent_orchestration/step3_group_chat.py)|How to create a group chat with multiple agents interacting together.
[step3a_group_chat_human_in_the_loop](../getting_started_with_agents/multi_agent_orchestration/step3a_group_chat_human_in_the_loop.py)|How to include a human participant in a group chat with agents.
[step3b_group_chat_with_chat_completion_manager](../getting_started_with_agents/multi_agent_orchestration/step3b_group_chat_with_chat_completion_manager.py)|How to manage a group chat with agents using a chat completion manager.
[step4_handoff](../getting_started_with_agents/multi_agent_orchestration/step4_handoff.py)|How to hand off conversation or tasks from one agent to another.
[step4a_handoff_structured_inputs](../getting_started_with_agents/multi_agent_orchestration/step4a_handoff_structured_inputs.py)|How to perform structured inputs handoffs between agents.


## OpenAI Assistant Agent

Expand All @@ -86,6 +72,21 @@ Example|Description
[step6_responses_agent_vision](../getting_started_with_agents/openai_responses/step6_responses_agent_vision.py)|How to provide an image as input to an OpenAI Responses agent.
[step7_responses_agent_structured_outputs](../getting_started_with_agents/openai_responses/step7_responses_agent_structured_outputs.py)|How to use have an OpenAI Responses agent use structured outputs.

## Multi-Agent Orchestration

Example|Description
---|---
[step1_concurrent](../getting_started_with_agents/multi_agent_orchestration/step1_concurrent.py)|How to run agents in parallel on the same task.
[step1a_concurrent_structure_output](../getting_started_with_agents/multi_agent_orchestration/step1a_concurrent_structure_output.py)|How to run agents in parallel on the same task and return structured output.
[step2_sequential](../getting_started_with_agents/multi_agent_orchestration/step2_sequential.py)|How to run agents in sequence to complete a task.
[step2a_sequential_cancellation_token](../getting_started_with_agents/multi_agent_orchestration/step2a_sequential_cancellation_token.py)|How to cancel an invocation while it is in progress.
[step3_group_chat](../getting_started_with_agents/multi_agent_orchestration/step3_group_chat.py)|How to run agents in a group chat to complete a task.
[step3a_group_chat_human_in_the_loop](../getting_started_with_agents/multi_agent_orchestration/step3a_group_chat_human_in_the_loop.py)|How to run agents in a group chat with human in the loop.
[step3b_group_chat_with_chat_completion_manager](../getting_started_with_agents/multi_agent_orchestration/step3b_group_chat_with_chat_completion_manager.py)|How to run agents in a group chat with a more dynamic manager.
[step4_handoff](../getting_started_with_agents/multi_agent_orchestration/step4_handoff.py)|How to run agents in a handoff orchestration to complete a task.
[step4a_handoff_structure_input](../getting_started_with_agents/multi_agent_orchestration/step4a_handoff_structure_input.py)|How to run agents in a handoff orchestration to complete a task with structured input.
[step5_magentic](../getting_started_with_agents/multi_agent_orchestration/step5_magentic.py)|How to run agents in a Magentic orchestration to complete a task.

## Configuring the Kernel

Similar to the Semantic Kernel Python concept samples, it is necessary to configure the secrets
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Multi-agent orchestration

The Semantic Kernel Agent Framework now supports orchestrating multiple agents to work together to complete a task.

## Background

The following samples are beneficial if you are just getting started with Semantic Kernel.

- [Chat Completion](../../concepts/chat_completion/)
- [Auto Function Calling](../../concepts/auto_function_calling/)
- [Structured Output](../../concepts/structured_output/)
- [Getting Started with Agents](../../getting_started_with_agents/)
- [More advanced agent samples](../../concepts/agents/)

## Prerequisites

The following environment variables are required to run the samples:

- OPENAI_API_KEY
- OPENAI_CHAT_MODEL_ID

However, if you are using other model services, feel free to switch to those in the samples.
Refer to [here](../../concepts/setup/README.md) on how to set up the environment variables for your model service.

## Orchestrations

| **Orchestrations** | **Description** |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Concurrent** | Useful for tasks that will benefit from independent analysis from multiple agents. |
| **Sequential** | Useful for tasks that require a well-defined step-by-step approach. |
| **Handoff** | Useful for tasks that are dynamic in nature and don't have a well-defined step-by-step approach. |
| **GroupChat** | Useful for tasks that will benefit from inputs from multiple agents and a highly configurable conversation flow. |
| **Magentic** | GroupChat like with a planner based manager. Inspired by [Magentic One](https://www.microsoft.com/en-us/research/articles/magentic-one-a-generalist-multi-agent-system-for-solving-complex-tasks/). |

## Samples

| Sample | Description |
|-----------------------------------------------------------------------------|--------------|
| [step1_concurrent](step1_concurrent.py) | Run agents in parallel on the same task. |
| [step1a_concurrent_structure_output](step1a_concurrent_structure_output.py) | Run agents in parallel on the same task and return structured output. |
| [step2_sequential](step2_sequential.py) | Run agents in sequence to complete a task. |
| [step2a_sequential_cancellation_token](step2a_sequential_cancellation_token.py) | Cancel an invocation while it is in progress. |
| [step3_group_chat](step3_group_chat.py) | Run agents in a group chat to complete a task. |
| [step3a_group_chat_human_in_the_loop](step3a_group_chat_human_in_the_loop.py) | Run agents in a group chat with human in the loop. |
| [step3b_group_chat_with_chat_completion_manager](step3b_group_chat_with_chat_completion_manager.py) | Run agents in a group chat with a more dynamic manager. |
| [step4_handoff](step4_handoff.py) | Run agents in a handoff orchestration to complete a task. |
| [step4a_handoff_structure_input](step4a_handoff_structure_input.py) | Run agents in a handoff orchestration to complete a task with structured input. |
| [step5_magentic](step5_magentic.py) | Run agents in a Magentic orchestration to complete a task. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# Copyright (c) Microsoft. All rights reserved.

import asyncio

from semantic_kernel.agents import (
Agent,
ChatCompletionAgent,
MagenticOrchestration,
OpenAIAssistantAgent,
StandardMagenticManager,
)
from semantic_kernel.agents.runtime import InProcessRuntime
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.open_ai_prompt_execution_settings import (
OpenAIChatPromptExecutionSettings,
)
from semantic_kernel.contents import ChatMessageContent

"""
The following sample demonstrates how to create a Magentic orchestration with two agents:
- A Research agent that can perform web searches
- A Coder agent that can run code using the code interpreter

Read more about Magentic here:
https://www.microsoft.com/en-us/research/articles/magentic-one-a-generalist-multi-agent-system-for-solving-complex-tasks/

This sample demonstrates the basic steps of creating and starting a runtime, creating
a Magentic orchestration with two agents and a Magentic manager, invoking the
orchestration, and finally waiting for the results.

The Magentic manager requires a chat completion model that supports structured output.
"""


async def agents() -> list[Agent]:
"""Return a list of agents that will participate in the Magentic orchestration.

Feel free to add or remove agents.
"""
research_agent = ChatCompletionAgent(
name="ResearchAgent",
description="A helpful assistant with access to web search. Ask it to perform web searches.",
instructions=(
"You are a Researcher. You find information without additional computation or quantitative analysis."
),
# This agent requires the gpt-4o-search-preview model to perform web searches.
service=OpenAIChatCompletion(ai_model_id="gpt-4o-search-preview"),
)

# Create an OpenAI Assistant agent with code interpreter capability
client, model = OpenAIAssistantAgent.setup_resources()
code_interpreter_tool, code_interpreter_tool_resources = OpenAIAssistantAgent.configure_code_interpreter_tool()
definition = await client.beta.assistants.create(
model=model,
name="CoderAgent",
description="A helpful assistant with code interpreter capability.",
instructions="You solve questions using code. Please provide detailed analysis and computation process.",
tools=code_interpreter_tool,
tool_resources=code_interpreter_tool_resources,
)
coder_agent = OpenAIAssistantAgent(
client=client,
definition=definition,
)

return [research_agent, coder_agent]


def agent_response_callback(message: ChatMessageContent) -> None:
"""Observer function to print the messages from the agents."""
print(f"**{message.name}**\n{message.content}")


async def main():
"""Main function to run the agents."""
# 1. Create a Magentic orchestration with two agents and a Magentic manager
# Note, the Standard Magentic manager accepts custom prompts for advanced users and scenarios.
magentic_orchestration = MagenticOrchestration(
members=await agents(),
manager=StandardMagenticManager(
chat_completion_service=OpenAIChatCompletion(),
prompt_execution_settings=OpenAIChatPromptExecutionSettings(),
),
agent_response_callback=agent_response_callback,
)

# 2. Create a runtime and start it
runtime = InProcessRuntime()
runtime.start()

# 3. Invoke the orchestration with a task and the runtime
orchestration_result = await magentic_orchestration.invoke(
task=(
"I am preparing a report on the energy efficiency of different machine learning model architectures. "
"Compare the estimated training and inference energy consumption of ResNet-50, BERT-base, and GPT-2 "
"on standard datasets (e.g., ImageNet for ResNet, GLUE for BERT, WebText for GPT-2). "
"Then, estimate the CO2 emissions associated with each, assuming training on an Azure Standard_NC6s_v3 VM "
"for 24 hours. Provide tables for clarity, and recommend the most energy-efficient model "
"per task type (image classification, text classification, and text generation)."
),
runtime=runtime,
)

# 4. Wait for the results
value = await orchestration_result.get()

print(f"\nFinal result:\n{value}")

# 5. Stop the runtime when idle
await runtime.stop_when_idle()

"""
Sample output:
**ResearchAgent**
Estimating the energy consumption and associated CO₂ emissions for training and inference of ResNet-50, BERT-base...

**CoderAgent**
Here is the comparison of energy consumption and CO₂ emissions for each model (ResNet-50, BERT-base, and GPT-2)
over a 24-hour period:

| Model | Training Energy (kWh) | Inference Energy (kWh) | Total Energy (kWh) | CO₂ Emissions (kg) |
|-----------|------------------------|------------------------|---------------------|---------------------|
| ResNet-50 | 21.11 | 0.08232 | 21.19232 | 19.50 |
| BERT-base | 0.048 | 0.23736 | 0.28536 | 0.26 |
| GPT-2 | 42.22 | 0.35604 | 42.57604 | 39.17 |

### Recommendations:
...

**CoderAgent**
Here are the recalibrated results for energy consumption and CO₂ emissions, assuming a more conservative approach
for models like GPT-2:

| Model | Training Energy (kWh) | Inference Energy (kWh) | Total Energy (kWh) | CO₂ Emissions (kg) |
|------------------|------------------------|------------------------|---------------------|---------------------|
| ResNet-50 | 21.11 | 0.08232 | 21.19232 | 19.50 |
| BERT-base | 0.048 | 0.23736 | 0.28536 | 0.26 |
| GPT-2 (Adjusted) | 42.22 | 0.35604 | 42.57604 | 39.17 |

...

**ResearchAgent**
Estimating the energy consumption and associated CO₂ emissions for training and inference of machine learning ...

**ResearchAgent**
Estimating the energy consumption and CO₂ emissions of training and inference for ResNet-50, BERT-base, and ...

**CoderAgent**
Here is the estimated energy use and CO₂ emissions for a full day of operation for each model on an Azure ...

**ResearchAgent**
Recent analyses have highlighted the substantial energy consumption and carbon emissions associated with ...

**CoderAgent**
Here's the refined estimation for the energy use and CO₂ emissions for optimized models on an Azure ...

**CoderAgent**
To provide precise estimates for CO₂ emissions based on Azure's regional data centers' carbon intensity, we need ...

**ResearchAgent**
To refine the CO₂ emission estimates for training and inference of ResNet-50, BERT-base, and GPT-2 on an Azure ...

**CoderAgent**
Here's the refined comparative table for energy consumption and CO₂ emissions for ResNet-50, BERT-base, and GPT-2,
taking into account carbon intensity data for Azure's West Europe and Sweden Central regions:

| Model | Energy (kWh) | CO₂ Emissions West Europe (kg) | CO₂ Emissions Sweden Central (kg) |
|------------|--------------|--------------------------------|-----------------------------------|
| ResNet-50 | 5.76 | 0.639 | 0.086 |
| BERT-base | 9.18 | 1.019 | 0.138 |
| GPT-2 | 12.96 | 1.439 | 0.194 |

**Refined Recommendations:**

...

Final result:
Here is the comprehensive report on energy efficiency and CO₂ emissions for ResNet-50, BERT-base, and GPT-2 models
when trained and inferred on an Azure Standard_NC6s_v3 VM for 24 hours.

### Energy Consumption and CO₂ Emissions:

Based on refined analyses, here are the estimated energy consumption and CO₂ emissions for each model:

| Model | Energy (kWh) | CO₂ Emissions West Europe (kg) | CO₂ Emissions Sweden Central (kg) |
|------------|--------------|--------------------------------|-----------------------------------|
| ResNet-50 | 5.76 | 0.639 | 0.086 |
| BERT-base | 9.18 | 1.019 | 0.138 |
| GPT-2 | 12.96 | 1.439 | 0.194 |

### Recommendations for Energy Efficiency:

...
"""


if __name__ == "__main__":
asyncio.run(main())
9 changes: 9 additions & 0 deletions python/semantic_kernel/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@
"HandoffOrchestration": ".orchestration.handoffs",
"OrchestrationHandoffs": ".orchestration.handoffs",
"GroupChatOrchestration": ".orchestration.group_chat",
"RoundRobinGroupChatManager": ".orchestration.group_chat",
"BooleanResult": ".orchestration.group_chat",
"StringResult": ".orchestration.group_chat",
"MessageResult": ".orchestration.group_chat",
"GroupChatManager": ".orchestration.group_chat",
"MagenticOrchestration": ".orchestration.magentic",
"ProgressLedger": ".orchestration.magentic",
"MagenticManager": ".orchestration.magentic",
"StandardMagenticManager": ".orchestration.magentic",
}


Expand Down
17 changes: 16 additions & 1 deletion python/semantic_kernel/agents/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,16 @@ from .open_ai.open_ai_assistant_agent import AssistantAgentThread, OpenAIAssista
from .open_ai.openai_responses_agent import OpenAIResponsesAgent, ResponsesAgentThread
from .open_ai.run_polling_options import RunPollingOptions
from .orchestration.concurrent import ConcurrentOrchestration
from .orchestration.group_chat import GroupChatManager, GroupChatOrchestration, RoundRobinGroupChatManager
from .orchestration.group_chat import (
BooleanResult,
GroupChatManager,
GroupChatOrchestration,
MessageResult,
RoundRobinGroupChatManager,
StringResult,
)
from .orchestration.handoffs import HandoffOrchestration, OrchestrationHandoffs
from .orchestration.magentic import MagenticManager, MagenticOrchestration, ProgressLedger, StandardMagenticManager
from .orchestration.sequential import SequentialOrchestration

__all__ = [
Expand All @@ -49,6 +57,7 @@ __all__ = [
"AzureResponsesAgent",
"BedrockAgent",
"BedrockAgentThread",
"BooleanResult",
"ChatCompletionAgent",
"ChatHistoryAgentThread",
"ConcurrentOrchestration",
Expand All @@ -60,15 +69,21 @@ __all__ = [
"GroupChatManager",
"GroupChatOrchestration",
"HandoffOrchestration",
"MagenticManager",
"MagenticOrchestration",
"MessageResult",
"ModelConnection",
"ModelSpec",
"OpenAIAssistantAgent",
"OpenAIResponsesAgent",
"OrchestrationHandoffs",
"ProgressLedger",
"ResponsesAgentThread",
"RoundRobinGroupChatManager",
"RunPollingOptions",
"SequentialOrchestration",
"StandardMagenticManager",
"StringResult",
"ToolSpec",
"register_agent_type",
]
Loading
Loading