Python: restructure: Python samples into progressive 01-05 layout (#3862)

* restructure: Python samples into progressive 01-05 layout

- 01-get-started/: 6 numbered steps (hello agent → hosting)
- 02-agents/: all agent concept samples (tools, middleware, providers, etc.)
- 03-workflows/: ALL existing workflow samples preserved as-is
- 04-hosting/: azure-functions, durabletask, a2a
- 05-end-to-end/: demos, evaluation, hosted agents
- Old files moved to _to_delete/ for review
- Added AGENTS.md with structure documentation
- autogen-migration/ and semantic-kernel-migration/ preserved at root

* fix: switch to AzureOpenAI Foundry, fix CI failures

- Switch all 01-get-started samples to AzureOpenAIResponsesClient with
  Azure AI Foundry project endpoint (AZURE_AI_PROJECT_ENDPOINT +
  AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME + AzureCliCredential)
- Add _to_delete/ and 05-end-to-end/ to pyrightconfig.samples.json excludes
- Fix test paths in packages/ that referenced old getting_started/ dirs:
  durabletask conftest + streaming test, azurefunctions conftest,
  devui conftest + capture_messages + openai_sdk_integration
- Fix workflow_as_agent_human_in_the_loop.py import (sibling import)
- Update hosting READMEs and tool comment paths
- Replace root README.md with new structure overview
- Update AGENTS.md to document Azure OpenAI Foundry as default provider

* cleanup: remove _to_delete folder, copy resource files to active dirs

All files in _to_delete/ were either:
- Exact duplicates of files in the new structure (240 files)
- Same file with only comment path updates (100 files)
- One import-fix diff (workflow_as_agent_human_in_the_loop.py)
- One superseded minimal_sample.py

Resource files (sample.pdf, countries.json, employees.pdf, weather.json)
copied to 02-agents/sample_assets/ and 02-agents/resources/ since active
samples reference them.

* fix: address PR review comments, centralize resources, remove root duplicates

- Fix type annotation in 04_memory.py (string union -> proper types)
- Fix old sample paths in observability files
- Fix grammar/spelling in observability samples
- Move sample_assets/ and resources/ to shared/ folder
- Remove 8 duplicate observability files from 02-agents root
- Update resource path references in multimodal_input and provider samples

* fix: update broken links from old getting_started paths to new structure

- Update relative paths in READMEs: getting_started/ → 01-get-started/,
  02-agents/, 03-workflows/, 04-hosting/, 05-end-to-end/
- Fix absolute GitHub URLs in package READMEs
- Fix broken link in ollama package README

* fix: convert absolute GitHub URLs to relative paths for link checker

Absolute URLs to python/samples/ on main branch 404 until PR merges.
Converted to relative paths that linkspector can verify locally.

* fix: update link for handoff sample moved to orchestrations/

* fix: update chatkit-integration README path from demos/ to 05-end-to-end/

* fix: update broken links in orchestrations README to match flat directory structure
This commit is contained in:
Eduard van Valkenburg
2026-02-12 18:36:36 +01:00
committed by GitHub
Unverified
parent 69dcfe31ee
commit a2856d3b92
536 changed files with 3816 additions and 1632 deletions
@@ -0,0 +1,7 @@
# Azure OpenAI API Configuration
# Get your credentials from Azure Portal
AZURE_OPENAI_API_KEY=your-azure-openai-api-key-here
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME=gpt-4o
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
AZURE_OPENAI_API_VERSION=2024-10-21
@@ -0,0 +1,7 @@
# Copyright (c) Microsoft. All rights reserved.
"""Sequential Agents Workflow - Writer → Reviewer."""
from .workflow import workflow
__all__ = ["workflow"]
@@ -0,0 +1,170 @@
# Copyright (c) Microsoft. All rights reserved.
"""Agent Workflow - Content Review with Quality Routing.
This sample demonstrates:
- Using agents directly as executors
- Conditional routing based on structured outputs
- Quality-based workflow paths with convergence
Use case: Content creation with automated review.
Writer creates content, Reviewer evaluates quality:
- High quality (score >= 80): → Publisher → Summarizer
- Low quality (score < 80): → Editor → Publisher → Summarizer
Both paths converge at Summarizer for final report.
"""
import os
from typing import Any
from agent_framework import AgentExecutorResponse, WorkflowBuilder
from agent_framework.azure import AzureOpenAIChatClient
from pydantic import BaseModel
# Define structured output for review results
class ReviewResult(BaseModel):
"""Review evaluation with scores and feedback."""
score: int # Overall quality score (0-100)
feedback: str # Concise, actionable feedback
clarity: int # Clarity score (0-100)
completeness: int # Completeness score (0-100)
accuracy: int # Accuracy score (0-100)
structure: int # Structure score (0-100)
# Condition function: route to editor if score < 80
def needs_editing(message: Any) -> bool:
"""Check if content needs editing based on review score."""
if not isinstance(message, AgentExecutorResponse):
return False
try:
review = ReviewResult.model_validate_json(message.agent_response.text)
return review.score < 80
except Exception:
return False
# Condition function: content is approved (score >= 80)
def is_approved(message: Any) -> bool:
"""Check if content is approved (high quality)."""
if not isinstance(message, AgentExecutorResponse):
return True
try:
review = ReviewResult.model_validate_json(message.agent_response.text)
return review.score >= 80
except Exception:
return True
# Create Azure OpenAI chat client
client = AzureOpenAIChatClient(api_key=os.environ.get("AZURE_OPENAI_API_KEY", ""))
# Create Writer agent - generates content
writer = client.as_agent(
name="Writer",
instructions=(
"You are an excellent content writer. "
"Create clear, engaging content based on the user's request. "
"Focus on clarity, accuracy, and proper structure."
),
)
# Create Reviewer agent - evaluates and provides structured feedback
reviewer = client.as_agent(
name="Reviewer",
instructions=(
"You are an expert content reviewer. "
"Evaluate the writer's content based on:\n"
"1. Clarity - Is it easy to understand?\n"
"2. Completeness - Does it fully address the topic?\n"
"3. Accuracy - Is the information correct?\n"
"4. Structure - Is it well-organized?\n\n"
"Return a JSON object with:\n"
"- score: overall quality (0-100)\n"
"- feedback: concise, actionable feedback\n"
"- clarity, completeness, accuracy, structure: individual scores (0-100)"
),
default_options={"response_format": ReviewResult},
)
# Create Editor agent - improves content based on feedback
editor = client.as_agent(
name="Editor",
instructions=(
"You are a skilled editor. "
"You will receive content along with review feedback. "
"Improve the content by addressing all the issues mentioned in the feedback. "
"Maintain the original intent while enhancing clarity, completeness, accuracy, and structure."
),
)
# Create Publisher agent - formats content for publication
publisher = client.as_agent(
name="Publisher",
instructions=(
"You are a publishing agent. "
"You receive either approved content or edited content. "
"Format it for publication with proper headings and structure."
),
)
# Create Summarizer agent - creates final publication report
summarizer = client.as_agent(
name="Summarizer",
instructions=(
"You are a summarizer agent. "
"Create a final publication report that includes:\n"
"1. A brief summary of the published content\n"
"2. The workflow path taken (direct approval or edited)\n"
"3. Key highlights and takeaways\n"
"Keep it concise and professional."
),
)
# Build workflow with branching and convergence:
# Writer → Reviewer → [branches]:
# - If score >= 80: → Publisher → Summarizer (direct approval path)
# - If score < 80: → Editor → Publisher → Summarizer (improvement path)
# Both paths converge at Summarizer for final report
workflow = (
WorkflowBuilder(
name="Content Review Workflow",
description="Multi-agent content creation workflow with quality-based routing (Writer → Reviewer → Editor/Publisher)",
start_executor=writer,
)
.add_edge(writer, reviewer)
# Branch 1: High quality (>= 80) goes directly to publisher
.add_edge(reviewer, publisher, condition=is_approved)
# Branch 2: Low quality (< 80) goes to editor first, then publisher
.add_edge(reviewer, editor, condition=needs_editing)
.add_edge(editor, publisher)
# Both paths converge: Publisher → Summarizer
.add_edge(publisher, summarizer)
.build()
)
def main():
"""Launch the branching workflow in DevUI."""
import logging
from agent_framework.devui import serve
logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger(__name__)
logger.info("Starting Agent Workflow (Content Review with Quality Routing)")
logger.info("Available at: http://localhost:8093")
logger.info("\nThis workflow demonstrates:")
logger.info("- Conditional routing based on structured outputs")
logger.info("- Path 1 (score >= 80): Reviewer → Publisher → Summarizer")
logger.info("- Path 2 (score < 80): Reviewer → Editor → Publisher → Summarizer")
logger.info("- Both paths converge at Summarizer for final report")
serve(entities=[workflow], port=8093, auto_open=True)
if __name__ == "__main__":
main()