chore: import upstream snapshot with attribution
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:25 +08:00
commit db620d33df
5151 changed files with 925932 additions and 0 deletions
@@ -0,0 +1,7 @@
.venv
__pycache__
*.pyc
*.pyo
*.pyd
.Python
.env
@@ -0,0 +1,2 @@
FOUNDRY_PROJECT_ENDPOINT="..."
AZURE_AI_MODEL_DEPLOYMENT_NAME="..."
@@ -0,0 +1,16 @@
FROM python:3.12-slim
WORKDIR /app
COPY . user_agent/
WORKDIR /app/user_agent
RUN if [ -f requirements.txt ]; then \
pip install -r requirements.txt; \
else \
echo "No requirements.txt found"; \
fi
EXPOSE 8088
CMD ["python", "main.py"]
@@ -0,0 +1,43 @@
# What this sample demonstrates
An [Agent Framework](https://github.com/microsoft/agent-framework) workflow demonstrating **multi-agent chaining** and hosted using the **Responses protocol**. It shows how to use the Agent Framework's `WorkflowBuilder` to compose a pipeline of specialized agents — a slogan writer, a legal reviewer, and a formatter — that process a request sequentially. Each agent receives only the output of the previous agent, and only the final formatted result is returned to the caller.
> The workflow will be used as an agent. Read more about Agent Framework workflows in the [Agent Framework documentation](https://learn.microsoft.com/en-us/agent-framework/workflows/) and workflow as an agent in the [Workflow as an Agent documentation](https://learn.microsoft.com/en-us/agent-framework/workflows/as-agents?pivots=programming-language-python).
> This sample requires a more advanced model because the model needs to continue the conversation from an assistant message. Not all models perform well in this scenario. Tested with OpenAI's model `gpt-5.4`.
## How It Works
### Model Integration
The agent creates three specialized `Agent` instances sharing the same `FoundryChatClient`: a **writer** that generates slogans, a **legal reviewer** that ensures compliance, and a **formatter** that styles the output. Each agent is wrapped in an `AgentExecutor` with `context_mode="last_agent"` so it only sees the previous agent's output. The `WorkflowBuilder` wires them into a linear pipeline and limits the output to the formatter's result.
See [main.py](main.py) for the full implementation.
### Agent Hosting
The workflow is exposed as a single agent via `.as_agent()` and hosted using the [Agent Framework](https://github.com/microsoft/agent-framework) with the `ResponsesHostServer`, which provisions a REST API endpoint compatible with the OpenAI Responses protocol.
## Running the Agent Host
Follow the instructions in the [Running the Agent Host Locally](../../README.md#running-the-agent-host-locally) section of the README in the parent directory to run the agent host.
## Interacting with the agent
> Depending on how you run the agent host, you can invoke the agent using `curl` (`Invoke-WebRequest` in PowerShell) or `azd`. Please refer to the [parent README](../../README.md) for more details. Use this README for sample queries you can send to the agent.
Send a POST request to the server with a JSON body containing an `"input"` field to interact with the agent. For example:
```bash
curl -X POST http://localhost:8088/responses -H "Content-Type: application/json" -d '{"input": "Create a slogan for a new electric SUV that is affordable and fun to drive."}'
```
Invoke with `azd`:
```bash
azd ai agent invoke --local "Create a slogan for a new electric SUV that is affordable and fun to drive."
```
## Deploying the Agent to Foundry
To host the agent on Foundry, follow the instructions in the [Deploying the Agent to Foundry](../../README.md#deploying-the-agent-to-foundry) section of the README in the parent directory.
@@ -0,0 +1,23 @@
name: agent-framework-workflows-responses
description: >
An Agent Framework workflow hosted by Foundry.
metadata:
tags:
- Agent Framework
- AI Agent Hosting
- Azure AI AgentServer
- Responses Protocol
- Streaming
template:
name: agent-framework-workflows-responses
kind: hosted
protocols:
- protocol: responses
version: 2.0.0
environment_variables:
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
value: "{{AZURE_AI_MODEL_DEPLOYMENT_NAME}}"
resources:
- kind: model
id: gpt-5.4
name: AZURE_AI_MODEL_DEPLOYMENT_NAME
@@ -0,0 +1,11 @@
kind: hosted
name: agent-framework-workflows-responses
protocols:
- protocol: responses
version: 2.0.0
resources:
cpu: "0.25"
memory: 0.5Gi
environment_variables:
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME}
@@ -0,0 +1,70 @@
# Copyright (c) Microsoft. All rights reserved.
import os
from agent_framework import Agent, AgentExecutor, WorkflowBuilder
from agent_framework.foundry import FoundryChatClient
from agent_framework_foundry_hosting import ResponsesHostServer
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
def main():
client = FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
credential=DefaultAzureCredential(),
)
writer_agent = Agent(
client=client,
instructions=("You are an excellent slogan writer. You create new slogans based on the given topic."),
name="writer",
)
legal_agent = Agent(
client=client,
instructions=(
"You are an excellent legal reviewer. "
"Make necessary corrections to the slogan so that it is legally compliant."
),
name="legal_reviewer",
)
format_agent = Agent(
client=client,
instructions=(
"You are an excellent content formatter. "
"You take the slogan and format it in a cool retro style when printing to a terminal."
),
name="formatter",
)
# Set the context mode to `last_agent` so that each agent only sees the output of the
# previous agent instead of the full conversation history
writer_executor = AgentExecutor(writer_agent, context_mode="last_agent")
legal_executor = AgentExecutor(legal_agent, context_mode="last_agent")
format_executor = AgentExecutor(format_agent, context_mode="last_agent")
workflow_agent = (
WorkflowBuilder(
start_executor=writer_executor,
# Select only the formatted result as Workflow Output.
# Unselected executor payloads are hidden unless selected as Intermediate Output.
output_from=[format_executor],
)
.add_edge(writer_executor, legal_executor)
.add_edge(legal_executor, format_executor)
.build()
.as_agent()
)
server = ResponsesHostServer(workflow_agent)
server.run()
if __name__ == "__main__":
main()
@@ -0,0 +1,2 @@
agent-framework-foundry
agent-framework-foundry-hosting>=1.0.0a260630