Skip to content

Commit 3a0c9ce

Browse files
authored
Merge pull request #38 from Azure-Samples/workflowmagentic
Adding new agent framework examples, remove autogen examples
2 parents 79490ac + fd8557d commit 3a0c9ce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+893
-611
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ This project includes infrastructure as code (IaC) to provision Azure OpenAI dep
197197
198198
## Resources
199199
200-
* [AutoGen Documentation](https://microsoft.github.io/autogen/)
201200
* [LangGraph Documentation](https://langchain-ai.github.io/langgraph/tutorials/introduction/)
202201
* [LlamaIndex Documentation](https://docs.llamaindex.ai/en/latest/)
203202
* [OpenAI Agents Documentation](https://openai.github.io/openai-agents-python/)

examples/agentframework_basic.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@
3535
api_key=os.environ.get("OPENAI_API_KEY"), model_id=os.environ.get("OPENAI_MODEL", "gpt-4o")
3636
)
3737

38-
agent = ChatAgent(
39-
chat_client=client,
40-
instructions="You're an informational agent. Answer questions cheerfully."
41-
)
38+
agent = ChatAgent(chat_client=client, instructions="You're an informational agent. Answer questions cheerfully.")
4239

4340

4441
async def main():
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
"""
2+
Agent Framework MagenticOne Example - Travel Planning with Multiple Agents
3+
"""
4+
import asyncio
5+
import os
6+
7+
from agent_framework import (
8+
ChatAgent,
9+
MagenticAgentDeltaEvent,
10+
MagenticAgentMessageEvent,
11+
MagenticBuilder,
12+
MagenticCallbackEvent,
13+
MagenticCallbackMode,
14+
MagenticOrchestratorMessageEvent,
15+
WorkflowOutputEvent,
16+
)
17+
from agent_framework.azure import AzureOpenAIChatClient
18+
from agent_framework.openai import OpenAIChatClient
19+
from azure.identity import DefaultAzureCredential
20+
from dotenv import load_dotenv
21+
from rich.console import Console
22+
from rich.markdown import Markdown
23+
from rich.panel import Panel
24+
from rich.text import Text
25+
26+
# Setup the client to use either Azure OpenAI or GitHub Models
27+
load_dotenv(override=True)
28+
API_HOST = os.getenv("API_HOST", "github")
29+
30+
if API_HOST == "azure":
31+
client = AzureOpenAIChatClient(
32+
credential=DefaultAzureCredential(),
33+
deployment_name=os.environ.get("AZURE_OPENAI_CHAT_DEPLOYMENT"),
34+
endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"),
35+
api_version=os.environ.get("AZURE_OPENAI_VERSION"),
36+
)
37+
elif API_HOST == "github":
38+
client = OpenAIChatClient(
39+
base_url="https://models.github.ai/inference",
40+
api_key=os.environ["GITHUB_TOKEN"],
41+
model_id=os.getenv("GITHUB_MODEL", "openai/gpt-4o"),
42+
)
43+
elif API_HOST == "ollama":
44+
client = OpenAIChatClient(
45+
base_url=os.environ.get("OLLAMA_ENDPOINT", "http://localhost:11434/v1"),
46+
api_key="none",
47+
model_id=os.environ.get("OLLAMA_MODEL", "llama3.1:latest"),
48+
)
49+
else:
50+
client = OpenAIChatClient(
51+
api_key=os.environ.get("OPENAI_API_KEY"), model_id=os.environ.get("OPENAI_MODEL", "gpt-4o")
52+
)
53+
54+
# Initialize rich console
55+
console = Console()
56+
57+
# Create the agents
58+
local_agent = ChatAgent(
59+
chat_client=client,
60+
instructions=(
61+
"You are a helpful assistant that can suggest authentic and interesting local activities "
62+
"or places to visit for a user and can utilize any context information provided."
63+
),
64+
name="local_agent",
65+
description="A local assistant that can suggest local activities or places to visit.",
66+
)
67+
68+
language_agent = ChatAgent(
69+
chat_client=client,
70+
instructions=(
71+
"You are a helpful assistant that can review travel plans, providing feedback on important/critical "
72+
"tips about how best to address language or communication challenges for the given destination. "
73+
"If the plan already includes language tips, you can mention that the plan is satisfactory, with rationale."
74+
),
75+
name="language_agent",
76+
description="A helpful assistant that can provide language tips for a given destination.",
77+
)
78+
79+
travel_summary_agent = ChatAgent(
80+
chat_client=client,
81+
instructions=(
82+
"You are a helpful assistant that can take in all of the suggestions and advice from the other agents "
83+
"and provide a detailed final travel plan. You must ensure that the final plan is integrated and complete. "
84+
"YOUR FINAL RESPONSE MUST BE THE COMPLETE PLAN. Provide a comprehensive summary when all perspectives "
85+
"from other agents have been integrated."
86+
),
87+
name="travel_summary_agent",
88+
description="A helpful assistant that can summarize the travel plan.",
89+
)
90+
91+
92+
# Event callback for streaming output with rich formatting
93+
async def on_event(event: MagenticCallbackEvent) -> None:
94+
if isinstance(event, MagenticOrchestratorMessageEvent):
95+
emoji = "✅" if event.kind == "task_ledger" else "🦠"
96+
console.print(
97+
Panel(
98+
Markdown(event.message.text),
99+
title=f"{emoji} orchestrator: {event.kind}",
100+
border_style="bold green",
101+
padding=(1, 2),
102+
)
103+
)
104+
elif isinstance(event, MagenticAgentMessageEvent):
105+
console.print(
106+
Panel(
107+
Markdown(event.message.text),
108+
title=f"🤖 {event.agent_id}",
109+
border_style="bold blue",
110+
padding=(1, 2),
111+
)
112+
)
113+
114+
115+
magentic_orchestrator = (
116+
MagenticBuilder()
117+
.participants(
118+
local_agent=local_agent,
119+
language_agent=language_agent,
120+
travel_summary_agent=travel_summary_agent,
121+
)
122+
.on_event(on_event, mode=MagenticCallbackMode.NON_STREAMING)
123+
.with_standard_manager(
124+
chat_client=client,
125+
max_round_count=20,
126+
max_stall_count=3,
127+
max_reset_count=2,
128+
)
129+
.build()
130+
)
131+
132+
133+
async def main():
134+
async for event in magentic_orchestrator.run_stream("Plan a half-day trip to Costa Rica"):
135+
if isinstance(event, WorkflowOutputEvent):
136+
final_result = event.data
137+
console.print(
138+
Panel(
139+
Markdown(final_result.text),
140+
title="🌎 final travel plan",
141+
border_style="bold green",
142+
padding=(1, 2),
143+
)
144+
)
145+
146+
if __name__ == "__main__":
147+
asyncio.run(main())

examples/agentframework_tool.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,7 @@ def get_weather(
6363

6464

6565
agent = ChatAgent(
66-
chat_client=client,
67-
instructions="You're an informational agent. Answer questions cheerfully.",
68-
tools=[get_weather]
66+
chat_client=client, instructions="You're an informational agent. Answer questions cheerfully.", tools=[get_weather]
6967
)
7068

7169

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
from __future__ import annotations
2+
3+
import os
4+
from typing import Any
5+
6+
from agent_framework import (
7+
AgentExecutorResponse,
8+
WorkflowBuilder,
9+
)
10+
from agent_framework.azure import AzureOpenAIChatClient
11+
from agent_framework.openai import OpenAIChatClient
12+
from azure.identity import DefaultAzureCredential
13+
from dotenv import load_dotenv
14+
from pydantic import BaseModel
15+
16+
load_dotenv(override=True)
17+
API_HOST = os.getenv("API_HOST", "github")
18+
19+
if API_HOST == "azure":
20+
client = AzureOpenAIChatClient(
21+
credential=DefaultAzureCredential(),
22+
deployment_name=os.environ.get("AZURE_OPENAI_CHAT_DEPLOYMENT"),
23+
endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"),
24+
api_version=os.environ.get("AZURE_OPENAI_VERSION"),
25+
)
26+
elif API_HOST == "github":
27+
client = OpenAIChatClient(
28+
base_url="https://models.github.ai/inference",
29+
api_key=os.environ["GITHUB_TOKEN"],
30+
model_id=os.getenv("GITHUB_MODEL", "openai/gpt-4o"),
31+
)
32+
elif API_HOST == "ollama":
33+
client = OpenAIChatClient(
34+
base_url=os.environ.get("OLLAMA_ENDPOINT", "http://localhost:11434/v1"),
35+
api_key="none",
36+
model_id=os.environ.get("OLLAMA_MODEL", "llama3.1:latest"),
37+
)
38+
else:
39+
client = OpenAIChatClient(
40+
api_key=os.environ.get("OPENAI_API_KEY"), model_id=os.environ.get("OPENAI_MODEL", "gpt-4o")
41+
)
42+
43+
44+
# Define structured output for review results
45+
class ReviewResult(BaseModel):
46+
"""Review evaluation with scores and feedback."""
47+
48+
score: int # Overall quality score (0-100)
49+
feedback: str # Concise, actionable feedback
50+
clarity: int # Clarity score (0-100)
51+
completeness: int # Completeness score (0-100)
52+
accuracy: int # Accuracy score (0-100)
53+
structure: int # Structure score (0-100)
54+
55+
56+
# Condition function: route to editor if score < 80
57+
def needs_editing(message: Any) -> bool:
58+
"""Check if content needs editing based on review score."""
59+
if not isinstance(message, AgentExecutorResponse):
60+
return False
61+
try:
62+
review = ReviewResult.model_validate_json(message.agent_run_response.text)
63+
return review.score < 80
64+
except Exception:
65+
return False
66+
67+
68+
# Condition function: content is approved (score >= 80)
69+
def is_approved(message: Any) -> bool:
70+
"""Check if content is approved (high quality)."""
71+
if not isinstance(message, AgentExecutorResponse):
72+
return True
73+
try:
74+
review = ReviewResult.model_validate_json(message.agent_run_response.text)
75+
return review.score >= 80
76+
except Exception:
77+
return True
78+
79+
80+
# Create Writer agent - generates content
81+
writer = client.create_agent(
82+
name="Writer",
83+
instructions=(
84+
"You are an excellent content writer. "
85+
"Create clear, engaging content based on the user's request. "
86+
"Focus on clarity, accuracy, and proper structure."
87+
),
88+
)
89+
90+
# Create Reviewer agent - evaluates and provides structured feedback
91+
reviewer = client.create_agent(
92+
name="Reviewer",
93+
instructions=(
94+
"You are an expert content reviewer. "
95+
"Evaluate the writer's content based on:\n"
96+
"1. Clarity - Is it easy to understand?\n"
97+
"2. Completeness - Does it fully address the topic?\n"
98+
"3. Accuracy - Is the information correct?\n"
99+
"4. Structure - Is it well-organized?\n\n"
100+
"Return a JSON object with:\n"
101+
"- score: overall quality (0-100)\n"
102+
"- feedback: concise, actionable feedback\n"
103+
"- clarity, completeness, accuracy, structure: individual scores (0-100)"
104+
),
105+
response_format=ReviewResult,
106+
)
107+
108+
# Create Editor agent - improves content based on feedback
109+
editor = client.create_agent(
110+
name="Editor",
111+
instructions=(
112+
"You are a skilled editor. "
113+
"You will receive content along with review feedback. "
114+
"Improve the content by addressing all the issues mentioned in the feedback. "
115+
"Maintain the original intent while enhancing clarity, completeness, accuracy, and structure."
116+
),
117+
)
118+
119+
# Create Publisher agent - formats content for publication
120+
publisher = client.create_agent(
121+
name="Publisher",
122+
instructions=(
123+
"You are a publishing agent. "
124+
"You receive either approved content or edited content. "
125+
"Format it for publication with proper headings and structure."
126+
),
127+
)
128+
129+
# Create Summarizer agent - creates final publication report
130+
summarizer = client.create_agent(
131+
name="Summarizer",
132+
instructions=(
133+
"You are a summarizer agent. "
134+
"Create a final publication report that includes:\n"
135+
"1. A brief summary of the published content\n"
136+
"2. The workflow path taken (direct approval or edited)\n"
137+
"3. Key highlights and takeaways\n"
138+
"Keep it concise and professional."
139+
),
140+
)
141+
142+
# Build workflow with branching and convergence:
143+
# Writer → Reviewer → [branches]:
144+
# - If score >= 80: → Publisher → Summarizer (direct approval path)
145+
# - If score < 80: → Editor → Publisher → Summarizer (improvement path)
146+
# Both paths converge at Summarizer for final report
147+
workflow = (
148+
WorkflowBuilder(
149+
name="Content Review Workflow",
150+
description="Multi-agent content creation workflow with quality-based routing (Writer → Reviewer → Editor/Publisher)",
151+
)
152+
.set_start_executor(writer)
153+
.add_edge(writer, reviewer)
154+
# Branch 1: High quality (>= 80) goes directly to publisher
155+
.add_edge(reviewer, publisher, condition=is_approved)
156+
# Branch 2: Low quality (< 80) goes to editor first, then publisher
157+
.add_edge(reviewer, editor, condition=needs_editing)
158+
.add_edge(editor, publisher)
159+
# Both paths converge: Publisher → Summarizer
160+
.add_edge(publisher, summarizer)
161+
.build()
162+
)
163+
164+
165+
def main():
166+
from agent_framework.devui import serve
167+
168+
serve(entities=[workflow], port=8093, auto_open=True)
169+
170+
171+
if __name__ == "__main__":
172+
main()

examples/autogen_basic.py

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)