{ "cells": [ { "cell_type": "markdown", "id": "0f298ce0", "metadata": {}, "source": [ "# ⏩ Sequential Agent Workflows with GitHub Models (Python)\n", "\n", "## 📋 Advanced Sequential Processing Tutorial\n", "\n", "This notebook demonstrates **sequential workflow patterns** using the Microsoft Agent Framework. You'll learn how to build sophisticated multi-step processing pipelines where agents execute in a specific order, passing data and context between stages.\n", "\n", "## 🎯 Learning Objectives\n", "\n", "### 🔄 **Sequential Processing Patterns**\n", "- **Linear Workflow Design**: Create step-by-step processing pipelines\n", "- **Data Flow Management**: Pass information between sequential agents\n", "- **Stage-Gate Processing**: Implement checkpoints and validation stages\n", "- **Progress Tracking**: Monitor workflow execution and intermediate results\n", "\n", "### 🏗️ **Enterprise Pipeline Architecture**\n", "- **Business Process Modeling**: Map real business processes to agent workflows\n", "- **Quality Assurance**: Multi-stage validation and review processes\n", "- **Document Processing**: Sequential document analysis and transformation\n", "- **Content Production**: Editorial workflows with review and approval stages\n", "\n", "### 📊 **Advanced Workflow Features**\n", "- **Context Preservation**: Maintain state across workflow stages\n", "- **Error Propagation**: Handle failures in sequential processing\n", "- **Performance Optimization**: Efficient sequential execution patterns\n", "- **Audit Trails**: Complete tracking of sequential operations\n", "\n", "## ⚙️ Prerequisites & Setup\n", "\n", "### 📦 **Dependencies**\n", "```bash\n", "pip install agent-framework-core -U\n", "```\n", "\n", "### 🔑 **Configuration**\n", "```env\n", "GITHUB_TOKEN=your_github_personal_access_token\n", "GITHUB_ENDPOINT=https://models.inference.ai.azure.com\n", "GITHUB_MODEL_ID=gpt-4o-mini\n", "```\n", "\n", "## 🏢 **Enterprise Sequential Workflow Use Cases**\n", "\n", "### 📝 **Document Processing Pipeline**\n", "```\n", "Raw Document → Content Extraction → Analysis → Validation → Final Output\n", "```\n", "\n", "### 🔍 **Quality Assurance Workflow** \n", "```\n", "Initial Review → Technical Validation → Compliance Check → Final Approval\n", "```\n", "\n", "### 📰 **Content Production Pipeline**\n", "```\n", "Research → Writing → Editing → Review → Publishing\n", "```\n", "\n", "### 💼 **Business Process Automation**\n", "```\n", "Data Collection → Processing → Analysis → Report Generation → Distribution\n", "```\n", "\n", "## 🎨 **Sequential Workflow Design Principles**\n", "\n", "- **🔗 Linear Progression**: Each stage depends on the previous stage's output\n", "- **📋 State Management**: Preserve context and data across all stages\n", "- **🛡️ Error Handling**: Graceful failure management in any stage\n", "- **📊 Progress Monitoring**: Track completion and performance at each stage\n", "- **🔄 Stage Reusability**: Design reusable workflow components\n", "\n", "Let's build sophisticated sequential processing workflows! 🚀" ] }, { "cell_type": "code", "execution_count": 1, "id": "a2276630", "metadata": {}, "outputs": [], "source": [ "####### Linux / MacOS Setup Instructions #######\n", "\n", "####### Linux Instructions #######\n", "# ! sudo apt update \n", "# ! sudo apt install graphviz -y\n", "\n", "####### macOS Instructions #######\n", "# ! brew install graphviz" ] }, { "cell_type": "code", "execution_count": 2, "id": "bef89b29", "metadata": {}, "outputs": [], "source": [ "# ! pip install -r ../../../Installation/requirements.txt -U\n", "# " ] }, { "cell_type": "code", "execution_count": 3, "id": "fec2cf19", "metadata": {}, "outputs": [], "source": [ "from agent_framework.openai import OpenAIChatCompletionClient\n", "from agent_framework import AgentResponse, Message, Content, Role,WorkflowBuilder, WorkflowEvent,WorkflowViz" ] }, { "cell_type": "code", "execution_count": 4, "id": "5d1a0590", "metadata": {}, "outputs": [], "source": [ "\n", "import os\n", "import base64\n", "from typing import cast\n", "from dotenv import load_dotenv" ] }, { "cell_type": "code", "execution_count": 5, "id": "cbbeaf06", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "load_dotenv()" ] }, { "cell_type": "code", "execution_count": 6, "id": "b1ff1a7b", "metadata": {}, "outputs": [], "source": [ "chat_client = OpenAIChatCompletionClient(base_url=os.environ.get(\"GITHUB_ENDPOINT\"), api_key=os.environ.get(\"GITHUB_TOKEN\"), model=os.environ.get(\"GITHUB_MODEL_ID\") )" ] }, { "cell_type": "code", "execution_count": 7, "id": "0d64a0a0", "metadata": {}, "outputs": [], "source": [ "SalesAgentName = \"Sales-Agent\"\n", "SalesAgentInstructions = \"You are my furniture sales consultant, you can find different furniture elements from the pictures and give me a purchase suggestion\"" ] }, { "cell_type": "code", "execution_count": 8, "id": "26b38cbf", "metadata": {}, "outputs": [], "source": [ "PriceAgentName = \"Price-Agent\"\n", "PriceAgentInstructions = \"\"\"You are a furniture pricing specialist and budget consultant. Your responsibilities include:\n", " 1. Analyze furniture items and provide realistic price ranges based on quality, brand, and market standards\n", " 2. Break down pricing by individual furniture pieces\n", " 3. Provide budget-friendly alternatives and premium options\n", " 4. Consider different price tiers (budget, mid-range, premium)\n", " 5. Include estimated total costs for room setups\n", " 6. Suggest where to find the best deals and shopping recommendations\n", " 7. Factor in additional costs like delivery, assembly, and accessories\n", " 8. Provide seasonal pricing insights and best times to buy\n", " Always format your response with clear price breakdowns and explanations for the pricing rationale.\"\"\"" ] }, { "cell_type": "code", "execution_count": 9, "id": "8dad49b7", "metadata": {}, "outputs": [], "source": [ "QuoteAgentName = \"Quote-Agent\"\n", "QuoteAgentInstructions = \"\"\"You are a assistant that create a quote for furniture purchase.\n", " 1. Create a well-structured quote document that includes:\n", " 2. A title page with the document title, date, and client name\n", " 3. An introduction summarizing the purpose of the document\n", " 4. A summary section with total estimated costs and recommendations\n", " 5. Use clear headings, bullet points, and tables for easy readability\n", " 6. All quotes are presented in markdown form\"\"\"" ] }, { "cell_type": "code", "execution_count": 10, "id": "c9a55d69", "metadata": {}, "outputs": [], "source": [ "sales_agent = chat_client.as_agent(\n", " instructions=(\n", " SalesAgentInstructions\n", " ),\n", " name=SalesAgentName,\n", " )\n", "\n", "price_agent = chat_client.as_agent(\n", " instructions=(\n", " PriceAgentInstructions\n", " ),\n", " name=PriceAgentName,\n", " )\n", "\n", "quote_agent = chat_client.as_agent(\n", " instructions=(\n", " QuoteAgentInstructions\n", " ),\n", " name=QuoteAgentName,\n", " )\n" ] }, { "cell_type": "code", "execution_count": 11, "id": "b3ac64f0", "metadata": {}, "outputs": [], "source": [ "workflow = WorkflowBuilder(start_executor=sales_agent).add_edge(sales_agent, price_agent).add_edge(price_agent, quote_agent).build()" ] }, { "cell_type": "code", "execution_count": 12, "id": "12eb6379", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Generating workflow visualization...\n", "Mermaid string: \n", "=======\n", "flowchart TD\n", " Sales_Agent[\"Sales-Agent (Start)\"];\n", " Price_Agent[\"Price-Agent\"];\n", " Quote_Agent[\"Quote-Agent\"];\n", " Sales_Agent --> Price_Agent;\n", " Price_Agent --> Quote_Agent;\n", "=======\n", "DiGraph string: \n", "=======\n", "digraph Workflow {\n", " rankdir=TD;\n", " node [shape=box, style=filled, fillcolor=lightblue];\n", " edge [color=black, arrowhead=vee];\n", "\n", " \"Sales-Agent\" [fillcolor=lightgreen, label=\"Sales-Agent\\n(Start)\"];\n", " \"Price-Agent\" [label=\"Price-Agent\"];\n", " \"Quote-Agent\" [label=\"Quote-Agent\"];\n", " \"Sales-Agent\" -> \"Price-Agent\";\n", " \"Price-Agent\" -> \"Quote-Agent\";\n", "}\n", "=======\n", "SVG file saved to: /var/folders/h1/d_gywhr90l1g98mqlt6wwrkh0000gn/T/tmp3aqgfmhi.svg\n" ] } ], "source": [ "print(\"Generating workflow visualization...\")\n", "viz = WorkflowViz(workflow)\n", "# Print out the mermaid string.\n", "print(\"Mermaid string: \\n=======\")\n", "print(viz.to_mermaid())\n", "print(\"=======\")\n", "# Print out the DiGraph string.\n", "print(\"DiGraph string: \\n=======\")\n", "print(viz.to_digraph())\n", "print(\"=======\")\n", "svg_file = viz.export(format=\"svg\")\n", "print(f\"SVG file saved to: {svg_file}\")" ] }, { "cell_type": "code", "execution_count": 13, "id": "57b86a4e", "metadata": {}, "outputs": [], "source": [ "class DatabaseEvent(WorkflowEvent): ..." ] }, { "cell_type": "code", "execution_count": 14, "id": "466f110e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Attempting to display SVG file at: /var/folders/h1/d_gywhr90l1g98mqlt6wwrkh0000gn/T/tmp3aqgfmhi.svg\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "Workflow\n", "\n", "\n", "\n", "Sales-Agent\n", "\n", "Sales-Agent\n", "(Start)\n", "\n", "\n", "\n", "Price-Agent\n", "\n", "Price-Agent\n", "\n", "\n", "\n", "Sales-Agent->Price-Agent\n", "\n", "\n", "\n", "\n", "\n", "Quote-Agent\n", "\n", "Quote-Agent\n", "\n", "\n", "\n", "Price-Agent->Quote-Agent\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Display the exported workflow SVG inline in the notebook\n", "\n", "from IPython.display import SVG, display, HTML\n", "import os\n", "\n", "print(f\"Attempting to display SVG file at: {svg_file}\")\n", "\n", "if svg_file and os.path.exists(svg_file):\n", " try:\n", " # Preferred: direct SVG rendering\n", " display(SVG(filename=svg_file))\n", " except Exception as e:\n", " print(f\"⚠️ Direct SVG render failed: {e}. Falling back to raw HTML.\")\n", " try:\n", " with open(svg_file, \"r\", encoding=\"utf-8\") as f:\n", " svg_text = f.read()\n", " display(HTML(svg_text))\n", " except Exception as inner:\n", " print(f\"❌ Fallback HTML render also failed: {inner}\")\n", "else:\n", " print(\"❌ SVG file not found. Ensure viz.export(format='svg') ran successfully.\")" ] }, { "cell_type": "code", "execution_count": 15, "id": "e0c32e98", "metadata": {}, "outputs": [], "source": [ "image_path = \"../imgs/home.png\"\n", "with open(image_path, \"rb\") as image_file:\n", " image_b64 = base64.b64encode(image_file.read()).decode()\n", "image_uri = f\"data:image/png;base64,{image_b64}\"\n" ] }, { "cell_type": "code", "execution_count": 16, "id": "417e237d", "metadata": {}, "outputs": [], "source": [ "message = Message(\n", " role=\"user\",\n", " contents=[\n", " Content.from_text(text=\"Please find the relevant furniture according to the image and give the corresponding price for each piece of furniture\"),\n", " Content.from_uri(uri=image_uri, media_type=\"image/png\")\n", " ]\n", ")" ] }, { "cell_type": "code", "execution_count": 17, "id": "bb76bba5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Sales-Agent: That sounds wonderful! Paris is a beautiful city with lots of incredible sights. If you're planning to furnish a new space there or redesign your current one inspired by Parisian style, I can help you select furniture pieces that capture that chic, elegant vibe. Would you like suggestions for classic Parisian-style furniture or something more modern? Also, if you have any pictures of your space or style preferences, feel free to share them!\n", "\n", "Price-Agent: It looks like you mentioned wanting to go to Paris, which sounds exciting! While I specialize in furniture pricing and budgeting, if you're thinking about furnishing a new home or apartment in Paris, I can definitely help you plan a furniture budget tailored to your style and needs there.\n", "\n", "If you're interested, please share details like the room types you want to furnish (living room, bedroom, etc.), your style preference (modern, classic Parisian chic, minimalist), and your budget range. That way, I can provide a detailed breakdown of furniture costs, including budget-friendly and premium options, best places to shop in Paris or online, and tips on timing your purchases for the best deals.\n", "\n", "Would you like to proceed with that?\n", "\n", "Quote-Agent: It sounds like you are interested in visiting Paris. If you are also interested in furnishing a home or accommodation there, I can assist you in creating a detailed furniture purchase quote. Please provide me with the following information to get started:\n", "\n", "- The type of rooms you want to furnish (living room, bedroom, dining room, etc.)\n", "- The style of furniture you prefer (modern, classic, Parisian chic, minimalist, etc.)\n", "- Your budget for the furniture purchase\n", "- Any specific furniture items you want to include\n", "\n", "Once I have these details, I will prepare a comprehensive, well-structured quote document for you.\n", "\n", "Final state: WorkflowRunState.IDLE\n" ] } ], "source": [ "events = await workflow.run(\"I would like to go to Paris.\")\n", "\n", "outputs = events.get_outputs()\n", " # The outputs of the workflow are whatever the agents produce. So the outputs are expected to be a list\n", " # of `AgentResponse` from the agents in the workflow.\n", "outputs = cast(list[AgentResponse], outputs)\n", "for output in outputs:\n", " print(f\"{output.messages[0].author_name}: {output.text}\\n\")\n", "\n", " # Summarize the final run state (e.g., COMPLETED)\n", "print(\"Final state:\", events.get_final_state())" ] } ], "metadata": { "kernelspec": { "display_name": "agentdev", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.10" } }, "nbformat": 4, "nbformat_minor": 5 }