mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Fix AzureFunctions Integration Tests (#2116)
* Add Identity Auth to samples * Update python/samples/getting_started/azure_functions/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update python/samples/getting_started/azure_functions/01_single_agent/function_app.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update python/samples/getting_started/azure_functions/02_multi_agent/function_app.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update python/samples/getting_started/azure_functions/06_multi_agent_orchestration_conditionals/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
2329bd4841
commit
ebab25b196
@@ -1,7 +1,6 @@
|
||||
# Azure OpenAI Configuration
|
||||
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
|
||||
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME=your-deployment-name
|
||||
AZURE_OPENAI_API_KEY=your-api-key-here
|
||||
FUNCTIONS_WORKER_RUNTIME=python
|
||||
RUN_INTEGRATION_TESTS=true
|
||||
|
||||
|
||||
@@ -64,10 +64,6 @@ def _should_skip_azure_functions_integration_tests() -> tuple[bool, str]:
|
||||
if not deployment_name or deployment_name == "your-deployment-name":
|
||||
return True, "No real AZURE_OPENAI_CHAT_DEPLOYMENT_NAME provided; skipping integration tests."
|
||||
|
||||
api_key = os.getenv("AZURE_OPENAI_API_KEY", "").strip()
|
||||
if not api_key or api_key == "your-api-key-here":
|
||||
return True, "No real AZURE_OPENAI_API_KEY provided; skipping integration tests."
|
||||
|
||||
return False, "Integration tests enabled."
|
||||
|
||||
|
||||
|
||||
@@ -10,34 +10,13 @@ This sample demonstrates how to use the Durable Extension for Agent Framework to
|
||||
- Managing conversation state with session identifiers, so multiple clients can
|
||||
interact with the agent concurrently without sharing context.
|
||||
|
||||
## Environment Setup
|
||||
## Prerequisites
|
||||
|
||||
### 1. Create and activate a virtual environment
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
python -m venv .venv
|
||||
.venv\Scripts\Activate.ps1
|
||||
```
|
||||
|
||||
**Linux/macOS:**
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
### 2. Install dependencies
|
||||
|
||||
- [Azure Functions Core Tools 4.x](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools) – install so you can run `func start` locally.
|
||||
- [Azurite storage emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) – install and start Azurite before launching the app (the sample uses `AzureWebJobsStorage=UseDevelopmentStorage=true`).
|
||||
- Python dependencies – from this folder, run `pip install -r requirements.txt` (or the equivalent in your active virtual environment).
|
||||
- Copy `local.settings.json.template` to `local.settings.json`, then update `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, and `AZURE_OPENAI_API_KEY` so the Azure OpenAI SDK can authenticate; keep `TASKHUB_NAME` set to `default` unless you plan to change the durable task hub name.
|
||||
Follow the common setup steps in `../README.md` to install tooling, configure Azure OpenAI credentials, and install the Python dependencies for this sample.
|
||||
|
||||
## Running the Sample
|
||||
|
||||
With the environment configured and the Functions host running, you can interact
|
||||
with the Joker agent using the provided `demo.http` file or any HTTP client. For
|
||||
example:
|
||||
Send a prompt to the Joker agent:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/agents/Joker/run \
|
||||
@@ -45,11 +24,7 @@ curl -X POST http://localhost:7071/api/agents/Joker/run \
|
||||
-d "Tell me a short joke about cloud computing."
|
||||
```
|
||||
|
||||
The agent responds with a JSON payload that includes the generated joke.
|
||||
|
||||
## Expected Output
|
||||
|
||||
When you send a POST request with plain-text input, the Functions host responds with an HTTP 202 and queues the request for the durable agent entity. A typical response body looks like the following:
|
||||
Expected HTTP 202 payload:
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -10,12 +10,12 @@ from typing import Any
|
||||
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.azurefunctions import AgentFunctionApp
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
# 1. Instantiate the agent with the chosen deployment and instructions.
|
||||
def _create_agent() -> Any:
|
||||
"""Create the Joker agent."""
|
||||
|
||||
return AzureOpenAIChatClient().create_agent(
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).create_agent(
|
||||
name="Joker",
|
||||
instructions="You are good at telling jokes.",
|
||||
)
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
agent-framework-azurefunctions
|
||||
azure-identity
|
||||
packaging
|
||||
|
||||
@@ -9,41 +9,13 @@ This sample demonstrates how to use the Durable Extension for Agent Framework to
|
||||
- Conversation management (via session IDs) for isolated interactions per agent.
|
||||
- Two different methods for registering agents: list-based initialization and incremental addition.
|
||||
|
||||
## Environment Setup
|
||||
## Prerequisites
|
||||
|
||||
### 1. Create and activate a virtual environment
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
python -m venv .venv
|
||||
.venv\Scripts\Activate.ps1
|
||||
```
|
||||
|
||||
**Linux/macOS:**
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
### 2. Install dependencies
|
||||
|
||||
- [Azure Functions Core Tools 4.x](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools) – install so you can run `func start` locally.
|
||||
- [Azurite storage emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) – install and start Azurite before launching the app; the sample expects `AzureWebJobsStorage=UseDevelopmentStorage=true`.
|
||||
- Python dependencies – from this folder, run `pip install -r requirements.txt` (or use the equivalent command in your active virtual environment).
|
||||
|
||||
### 3. Configure local settings
|
||||
|
||||
- Copy `local.settings.json.template` to `local.settings.json`, then set the Azure OpenAI values (`AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, and `AZURE_OPENAI_API_KEY`) so the SDK can authenticate, and keep `TASKHUB_NAME` set to `default` unless you intend to change the durable task hub name.
|
||||
Complete the common environment preparation steps described in `../README.md`, including installing Azure Functions Core Tools, starting Azurite, configuring Azure OpenAI settings, and installing this sample's requirements.
|
||||
|
||||
## Running the Sample
|
||||
|
||||
With the environment setup and function app running, you can test the sample by sending HTTP requests to the different agent endpoints.
|
||||
|
||||
You can use the `demo.http` file to send messages to the agents, or a command line tool like `curl` as shown below:
|
||||
|
||||
### Test the Weather Agent
|
||||
|
||||
Bash (Linux/macOS/WSL):
|
||||
Weather agent request:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/agents/WeatherAgent/run \
|
||||
@@ -51,16 +23,8 @@ curl -X POST http://localhost:7071/api/agents/WeatherAgent/run \
|
||||
-d '{"message": "What is the weather in Seattle?"}'
|
||||
```
|
||||
|
||||
PowerShell:
|
||||
Expected HTTP 202 payload:
|
||||
|
||||
```powershell
|
||||
Invoke-RestMethod -Method Post `
|
||||
-Uri http://localhost:7071/api/agents/WeatherAgent/run `
|
||||
-ContentType application/json `
|
||||
-Body '{"message": "What is the weather in Seattle?"}'
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{
|
||||
"status": "accepted",
|
||||
@@ -71,9 +35,7 @@ Expected response:
|
||||
}
|
||||
```
|
||||
|
||||
### Test the Math Agent
|
||||
|
||||
Bash (Linux/macOS/WSL):
|
||||
Math agent request:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/agents/MathAgent/run \
|
||||
@@ -81,16 +43,8 @@ curl -X POST http://localhost:7071/api/agents/MathAgent/run \
|
||||
-d '{"message": "Calculate a 20% tip on a $50 bill"}'
|
||||
```
|
||||
|
||||
PowerShell:
|
||||
Expected HTTP 202 payload:
|
||||
|
||||
```powershell
|
||||
Invoke-RestMethod -Method Post `
|
||||
-Uri http://localhost:7071/api/agents/MathAgent/run `
|
||||
-ContentType application/json `
|
||||
-Body '{"message": "Calculate a 20% tip on a $50 bill"}'
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{
|
||||
"status": "accepted",
|
||||
@@ -101,21 +55,14 @@ Expected response:
|
||||
}
|
||||
```
|
||||
|
||||
### Check Health
|
||||
|
||||
Bash (Linux/macOS/WSL):
|
||||
Health check (optional):
|
||||
|
||||
```bash
|
||||
curl http://localhost:7071/api/health
|
||||
```
|
||||
|
||||
PowerShell:
|
||||
|
||||
```powershell
|
||||
Invoke-RestMethod -Uri http://localhost:7071/api/health
|
||||
```
|
||||
|
||||
Expected response:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
|
||||
@@ -13,7 +13,7 @@ from typing import Any
|
||||
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.azurefunctions import AgentFunctionApp
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -51,7 +51,7 @@ def calculate_tip(bill_amount: float, tip_percentage: float = 15.0) -> dict[str,
|
||||
|
||||
|
||||
# 1. Create multiple agents, each with its own instruction set and tools.
|
||||
chat_client = AzureOpenAIChatClient()
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
weather_agent = chat_client.create_agent(
|
||||
name="WeatherAgent",
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
agent-framework-azurefunctions
|
||||
packaging
|
||||
azure-identity
|
||||
@@ -17,61 +17,32 @@ an HTTP API that can be polled by a web client or dashboard.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10+
|
||||
- [Azure Functions Core Tools 4.x](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools)
|
||||
- [Azurite storage emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) running locally so the sample can use `AzureWebJobsStorage=UseDevelopmentStorage=true`
|
||||
- Access to an Azure OpenAI deployment with `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, and `AZURE_OPENAI_API_KEY` configured (either in `local.settings.json` or exported in your shell)
|
||||
- Dependencies from `requirements.txt` installed in your environment
|
||||
Complete the shared environment setup steps in `../README.md`, including creating a virtual environment, installing dependencies, and configuring Azure OpenAI credentials and storage settings.
|
||||
|
||||
> **Note:** The sample stores callback events in memory for simplicity. For production scenarios you
|
||||
> should persist events to Application Insights, Azure Storage, Cosmos DB, or another durable store.
|
||||
|
||||
## Running the Sample
|
||||
|
||||
1. Create and activate a virtual environment:
|
||||
Send a prompt to the agent:
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
python -m venv .venv
|
||||
.venv\Scripts\Activate.ps1
|
||||
```
|
||||
|
||||
**Linux/macOS:**
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
2. Install dependencies (from the repository root or this directory):
|
||||
|
||||
```powershell
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. Copy `local.settings.json.template` to `local.settings.json` and update `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, and `AZURE_OPENAI_API_KEY` (or export them as environment variables) for your Azure resources, making sure `TASKHUB_NAME` remains `default` unless you have changed the durable task hub name.
|
||||
|
||||
4. Start the Functions host:
|
||||
|
||||
```powershell
|
||||
func start
|
||||
```
|
||||
|
||||
5. Use the [`demo.http`](./demo.http) file (VS Code REST Client) or any HTTP client to:
|
||||
- Send a message to the agent: `POST /api/agents/CallbackAgent/run`
|
||||
- Query callback telemetry: `GET /api/agents/CallbackAgent/callbacks/{conversationId}`
|
||||
- Clear stored events: `DELETE /api/agents/CallbackAgent/callbacks/{conversationId}`
|
||||
|
||||
Example workflow after the host starts:
|
||||
|
||||
```text
|
||||
POST /api/agents/CallbackAgent/run # send a conversation message
|
||||
GET /api/agents/CallbackAgent/callbacks/test-session # inspect streaming + final events
|
||||
DELETE /api/agents/CallbackAgent/callbacks/test-session # reset telemetry for the session
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/agents/CallbackAgent/run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"message": "Tell me a short joke"}'
|
||||
```
|
||||
|
||||
The GET endpoint returns an array of events captured by the callback, including timestamps,
|
||||
streaming chunk previews, and the final response metadata. This makes it easy to build real-time
|
||||
UI updates or audit logs on top of Durable Agents.
|
||||
Poll callback telemetry (replace `<conversationId>` with the value from the POST response):
|
||||
|
||||
```bash
|
||||
curl http://localhost:7071/api/agents/CallbackAgent/callbacks/<conversationId>
|
||||
```
|
||||
|
||||
Reset stored events:
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:7071/api/agents/CallbackAgent/callbacks/<conversationId>
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from typing import Any, DefaultDict
|
||||
import azure.functions as func
|
||||
from agent_framework import AgentRunResponseUpdate
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from agent_framework.azurefunctions import AgentFunctionApp, AgentCallbackContext, AgentResponseCallbackProtocol
|
||||
|
||||
@@ -105,7 +106,7 @@ class ConversationAuditTrail(AgentResponseCallbackProtocol):
|
||||
|
||||
|
||||
# 2. Create the agent that will emit streaming updates and final responses.
|
||||
callback_agent = AzureOpenAIChatClient().create_agent(
|
||||
callback_agent = AzureOpenAIChatClient(credential=AzureCliCredential()).create_agent(
|
||||
name="CallbackAgent",
|
||||
instructions=(
|
||||
"You are a friendly assistant that narrates actions while responding. "
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
agent-framework-azurefunctions
|
||||
azure-identity
|
||||
packaging
|
||||
azure-identity
|
||||
+13
-19
@@ -9,27 +9,21 @@ preserving the conversation state between runs.
|
||||
- HTTP endpoints for starting the orchestration and polling for status/output
|
||||
|
||||
## Prerequisites
|
||||
- Python 3.10+
|
||||
- [Azure Functions Core Tools 4.x](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools)
|
||||
- [Azurite storage emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) running locally so the sample can use `AzureWebJobsStorage=UseDevelopmentStorage=true`
|
||||
- Environment variables configured:
|
||||
- `AZURE_OPENAI_ENDPOINT`
|
||||
- `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`
|
||||
- `AZURE_OPENAI_API_KEY` (required for key-based auth; ensure Azure CLI is logged in if you prefer token-based auth)
|
||||
- Keep `TASKHUB_NAME` set to `default` unless you intend to change the durable task hub name.
|
||||
- Copy `local.settings.json.template` to `local.settings.json` and populate those keys—including `AZURE_OPENAI_API_KEY`—along with any storage settings before running the Functions host.
|
||||
- Install dependencies with `pip install -r requirements.txt`
|
||||
|
||||
Start with the shared setup instructions in `../README.md` to create a virtual environment, install dependencies, and configure Azure OpenAI and storage settings.
|
||||
|
||||
## Running the Sample
|
||||
1. Start the Functions host: `func start`.
|
||||
2. Kick off the orchestration:
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/singleagent/run
|
||||
```
|
||||
3. Copy the `statusQueryGetUri` from the response and poll until the orchestration completes:
|
||||
```bash
|
||||
curl http://localhost:7071/api/singleagent/status/<instanceId>
|
||||
```
|
||||
Start the orchestration:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/singleagent/run
|
||||
```
|
||||
|
||||
Poll the returned `statusQueryGetUri` until completion:
|
||||
|
||||
```bash
|
||||
curl http://localhost:7071/api/singleagent/status/<instanceId>
|
||||
```
|
||||
|
||||
The orchestration first requests an inspirational sentence from the agent, then refines the initial response while
|
||||
keeping it under 25 words—mirroring the behaviour of the corresponding .NET sample.
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import azure.durable_functions as df
|
||||
import azure.functions as func
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.durable_functions import DurableOrchestrationContext
|
||||
from azure.identity import AzureCliCredential
|
||||
from agent_framework.azurefunctions import AgentFunctionApp, get_agent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -33,7 +34,7 @@ def _create_writer_agent() -> Any:
|
||||
"when given an improved sentence you polish it further."
|
||||
)
|
||||
|
||||
return AzureOpenAIChatClient().create_agent(
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).create_agent(
|
||||
name=WRITER_AGENT_NAME,
|
||||
instructions=instructions,
|
||||
)
|
||||
|
||||
+1
-2
@@ -1,3 +1,2 @@
|
||||
agent-framework-azurefunctions
|
||||
azure-identity
|
||||
packaging
|
||||
azure-identity
|
||||
+16
-22
@@ -8,30 +8,24 @@ This sample starts a Durable Functions orchestration that runs two agents in par
|
||||
- HTTP routes (`/api/multiagent/run` and `/api/multiagent/status/{instanceId}`) mirror the .NET sample for parity.
|
||||
|
||||
## Prerequisites
|
||||
- Python 3.10+
|
||||
- [Azure Functions Core Tools 4.x](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools)
|
||||
- [Azurite storage emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) running locally so the sample can use `AzureWebJobsStorage=UseDevelopmentStorage=true`
|
||||
- Environment variables configured:
|
||||
- `AZURE_OPENAI_ENDPOINT`
|
||||
- `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`
|
||||
- `AZURE_OPENAI_API_KEY` (required for key-based auth; ensure the Azure CLI is logged in if you rely on token-based auth)
|
||||
- Keep `TASKHUB_NAME` set to `default` unless you intend to change the durable task hub name.
|
||||
- Copy `local.settings.json.template` to `local.settings.json` and fill in those Azure OpenAI values—including `AZURE_OPENAI_API_KEY`—along with storage settings before starting the Functions host.
|
||||
- Install dependencies with `pip install -r requirements.txt`
|
||||
|
||||
Use the shared setup instructions in `../README.md` to prepare the environment, install dependencies, and configure Azure OpenAI and storage settings before running this sample.
|
||||
|
||||
## Running the Sample
|
||||
1. Start the Functions host: `func start`.
|
||||
2. Send a prompt to start the orchestration:
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: text/plain" \
|
||||
--data "What is temperature?" \
|
||||
http://localhost:7071/api/multiagent/run
|
||||
```
|
||||
3. Poll the returned `statusQueryGetUri` until the orchestration completes:
|
||||
```bash
|
||||
curl http://localhost:7071/api/multiagent/status/<instanceId>
|
||||
```
|
||||
Start the orchestration:
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: text/plain" \
|
||||
--data "What is temperature?" \
|
||||
http://localhost:7071/api/multiagent/run
|
||||
```
|
||||
|
||||
Poll the returned `statusQueryGetUri` until completion:
|
||||
|
||||
```bash
|
||||
curl http://localhost:7071/api/multiagent/status/<instanceId>
|
||||
```
|
||||
|
||||
The orchestration launches both agents simultaneously so their domain-specific answers can be combined for the caller.
|
||||
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import azure.durable_functions as df
|
||||
import azure.functions as func
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.durable_functions import DurableOrchestrationContext
|
||||
from azure.identity import AzureCliCredential
|
||||
from agent_framework.azurefunctions import AgentFunctionApp, get_agent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -27,7 +28,7 @@ CHEMIST_AGENT_NAME = "ChemistAgent"
|
||||
|
||||
# 2. Instantiate both agents that the orchestration will run concurrently.
|
||||
def _create_agents() -> list[Any]:
|
||||
chat_client = AzureOpenAIChatClient()
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
physicist = chat_client.create_agent(
|
||||
name=PHYSICIST_AGENT_NAME,
|
||||
|
||||
+1
-2
@@ -1,3 +1,2 @@
|
||||
agent-framework-azurefunctions
|
||||
azure-identity
|
||||
packaging
|
||||
azure-identity
|
||||
+16
-11
@@ -4,23 +4,28 @@ This sample evaluates incoming emails with a spam detector agent and,
|
||||
when appropriate, drafts a response using an email assistant agent.
|
||||
|
||||
## Prerequisites
|
||||
- Python 3.10+ environment with dependencies from `requirements.txt` installed.
|
||||
- [Azure Functions Core Tools 4.x](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools) available on the PATH.
|
||||
- [Azurite storage emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) running locally so the sample can use `AzureWebJobsStorage=UseDevelopmentStorage=true`.
|
||||
- Environment variables `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, and `AZURE_OPENAI_API_KEY`.
|
||||
- Keep `TASKHUB_NAME` set to `default` unless you intend to change the durable task hub name.
|
||||
- Copy `local.settings.json.template` to `local.settings.json` and populate those Azure OpenAI settings—including `AZURE_OPENAI_API_KEY`—along with storage values before starting the host.
|
||||
|
||||
Set up the shared prerequisites outlined in `../README.md`, including the virtual environment, dependency installation, and Azure OpenAI and storage configuration.
|
||||
|
||||
## Scenario Overview
|
||||
- Two Azure OpenAI agents share a single deployment: one flags spam, the other drafts replies.
|
||||
- Structured responses (`is_spam` and `reason`, or `response`) determine which orchestration branch runs.
|
||||
- Activity functions handle the side effects of spam handling and email sending.
|
||||
|
||||
## Run the Sample
|
||||
1. Configure the environment variables and install dependencies with `pip install -r requirements.txt`.
|
||||
2. Launch the Functions host from this directory using `func start`.
|
||||
3. Send an email payload to `/api/spamdetection/run` (see `demo.http`).
|
||||
4. Poll the provided `statusQueryGetUri` or call `/api/spamdetection/status/{instanceId}` to monitor results.
|
||||
## Running the Sample
|
||||
Submit an email payload:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/spamdetection/run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"subject": "Sale now on", "body": "Limited time offer"}'
|
||||
```
|
||||
|
||||
Poll the returned `statusQueryGetUri` or call the status route directly:
|
||||
|
||||
```bash
|
||||
curl http://localhost:7071/api/spamdetection/status/<instanceId>
|
||||
```
|
||||
|
||||
## Expected Responses
|
||||
- Spam payloads return `Email marked as spam: <reason>` by invoking the `handle_spam_email` activity.
|
||||
|
||||
+2
-1
@@ -18,6 +18,7 @@ import azure.durable_functions as df
|
||||
import azure.functions as func
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.durable_functions import DurableOrchestrationContext
|
||||
from azure.identity import AzureCliCredential
|
||||
from agent_framework.azurefunctions import AgentFunctionApp, get_agent
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
@@ -43,7 +44,7 @@ class EmailPayload(BaseModel):
|
||||
|
||||
# 2. Instantiate both agents so they can be registered with AgentFunctionApp.
|
||||
def _create_agents() -> list[Any]:
|
||||
chat_client = AzureOpenAIChatClient()
|
||||
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
|
||||
|
||||
spam_agent = chat_client.create_agent(
|
||||
name=SPAM_AGENT_NAME,
|
||||
|
||||
+1
-2
@@ -1,3 +1,2 @@
|
||||
agent-framework-azurefunctions
|
||||
azure-identity
|
||||
packaging
|
||||
azure-identity
|
||||
+24
-12
@@ -5,12 +5,8 @@ A single writer agent iterates on content until a human reviewer approves the
|
||||
output or a maximum number of attempts is reached.
|
||||
|
||||
## Prerequisites
|
||||
- Python 3.10+ environment with the packages from `requirements.txt` installed.
|
||||
- [Azure Functions Core Tools 4.x](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools) available on the PATH.
|
||||
- [Azurite storage emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) running locally so the sample can use `AzureWebJobsStorage=UseDevelopmentStorage=true`.
|
||||
- Environment variables `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, and `AZURE_OPENAI_API_KEY`.
|
||||
- Keep `TASKHUB_NAME` set to `default` unless you intend to change the durable task hub name.
|
||||
- Copy `local.settings.json.template` to `local.settings.json` and configure those keys—including `AZURE_OPENAI_API_KEY`—plus storage settings before starting the Functions host.
|
||||
|
||||
Complete the common setup instructions in `../README.md` to prepare the virtual environment, install dependencies, and configure Azure OpenAI and storage settings.
|
||||
|
||||
## What It Shows
|
||||
- Identical environment variable usage (`AZURE_OPENAI_ENDPOINT`,
|
||||
@@ -20,12 +16,28 @@ output or a maximum number of attempts is reached.
|
||||
- Activity functions that encapsulate the out-of-band operations such as notifying
|
||||
a reviewer and publishing content.
|
||||
|
||||
## Run the Sample
|
||||
1. Configure the environment variables and install dependencies with `pip install -r requirements.txt`.
|
||||
2. Start the Functions host in this directory using `func start`.
|
||||
3. Trigger the orchestration with `demo.http` (or another HTTP client) by POSTing to `/api/hitl/run`.
|
||||
4. Poll the `statusQueryGetUri` or call `/api/hitl/status/{instanceId}` to monitor progress.
|
||||
5. POST an approval or rejection payload to `/api/hitl/approve/{instanceId}` to complete the review loop.
|
||||
## Running the Sample
|
||||
Start the HITL orchestration:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/hitl/run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"topic": "Write a friendly release note"}'
|
||||
```
|
||||
|
||||
Poll the returned `statusQueryGetUri` or call the status route directly:
|
||||
|
||||
```bash
|
||||
curl http://localhost:7071/api/hitl/status/<instanceId>
|
||||
```
|
||||
|
||||
Approve or reject the draft:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:7071/api/hitl/approve/<instanceId> \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"approved": true, "feedback": "Looks good"}'
|
||||
```
|
||||
|
||||
## Expected Responses
|
||||
- `POST /api/hitl/run` returns a 202 Accepted payload with the Durable Functions instance ID.
|
||||
|
||||
+2
-1
@@ -18,6 +18,7 @@ import azure.durable_functions as df
|
||||
import azure.functions as func
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from azure.durable_functions import DurableOrchestrationContext
|
||||
from azure.identity import AzureCliCredential
|
||||
from agent_framework.azurefunctions import AgentFunctionApp, get_agent
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
@@ -52,7 +53,7 @@ def _create_writer_agent() -> Any:
|
||||
"Return your response as JSON with 'title' and 'content' fields."
|
||||
)
|
||||
|
||||
return AzureOpenAIChatClient().create_agent(
|
||||
return AzureOpenAIChatClient(credential=AzureCliCredential()).create_agent(
|
||||
name=WRITER_AGENT_NAME,
|
||||
instructions=instructions,
|
||||
)
|
||||
|
||||
+1
-2
@@ -1,3 +1,2 @@
|
||||
agent-framework-azurefunctions
|
||||
azure-identity
|
||||
packaging
|
||||
azure-identity
|
||||
@@ -1,5 +1,5 @@
|
||||
These are common starting instructions for how to set up your environment for all the samples in this directory.
|
||||
These samples are for illustrating the use of the Durable extensibility to Agent Framework running in Azure Functions.
|
||||
These are common instructions for setting up your environment for every sample in this directory.
|
||||
These samples illustrate the Durable extensibility for Agent Framework running in Azure Functions.
|
||||
|
||||
All of these samples are set up to run in Azure Functions. Azure Functions has a local development tool called [CoreTools](https://learn.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Cpython%2Cv2&pivots=programming-language-python#install-the-azure-functions-core-tools) which we will set up to run these samples locally.
|
||||
|
||||
@@ -11,7 +11,7 @@ All of these samples are set up to run in Azure Functions. Azure Functions has a
|
||||
|
||||
- Install [Azurite storage emulator](https://learn.microsoft.com/en-us/azure/storage/common/storage-install-azurite?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&bc=%2Fazure%2Fstorage%2Fblobs%2Fbreadcrumb%2Ftoc.json&tabs=visual-studio%2Cblob-storage)
|
||||
|
||||
- Create an [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-foundry/models/openai) resource. Note the Azure OpenAI endpoint, deployment name and the Key.
|
||||
- Create an [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-foundry/models/openai) resource. Note the Azure OpenAI endpoint, deployment name, and the key (or ensure you can authenticate with `AzureCliCredential`).
|
||||
|
||||
- Install a tool to execute HTTP calls, for example the [REST Client extension](https://marketplace.visualstudio.com/items?itemName=humao.rest-client)
|
||||
|
||||
@@ -37,11 +37,12 @@ source .venv/bin/activate
|
||||
|
||||
- Inside each sample:
|
||||
|
||||
- Install Python dependencies – from this folder, run `pip install -r requirements.txt` (or the equivalent in your active virtual environment).
|
||||
- Install Python dependencies – from the sample directory, run `pip install -r requirements.txt` (or the equivalent in your active virtual environment).
|
||||
|
||||
- Copy `local.settings.json.template` to `local.settings.json`, then update `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, and `AZURE_OPENAI_API_KEY` so the Azure OpenAI SDK can authenticate; keep `TASKHUB_NAME` set to `default` unless you plan to change the durable task hub name.
|
||||
- Copy `local.settings.json.template` to `local.settings.json`, then update `AZURE_OPENAI_ENDPOINT` and `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME` for Azure OpenAI authentication. The samples use `AzureCliCredential` by default, so ensure you're logged in via `az login`.
|
||||
- Alternatively, you can use API key authentication by setting `AZURE_OPENAI_API_KEY` and updating the code to use `AzureOpenAIChatClient()` without the credential parameter.
|
||||
- Keep `TASKHUB_NAME` set to `default` unless you plan to change the durable task hub name.
|
||||
|
||||
- Run the command `func start` from the root of the sample
|
||||
|
||||
- Run the command `func start` from the root of the sample
|
||||
|
||||
- Follow the specific instructions/requests for each sample
|
||||
- Follow each sample's README for scenario-specific steps, and use its `demo.http` file (or provided curl examples) to trigger the hosted HTTP endpoints.
|
||||
|
||||
Reference in New Issue
Block a user