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,25 @@
FROM python:3.12-slim
# Bring in the `uv` binary from a pinned Astral image. Update this tag intentionally;
# `latest` would make rebuilds non-deterministic.
COPY --from=ghcr.io/astral-sh/uv:0.11.6 /uv /uvx /usr/local/bin/
ENV UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=1 \
UV_PROJECT_ENVIRONMENT=/app/.venv \
PATH="/app/.venv/bin:${PATH}"
WORKDIR /app
# Sync dependencies first to maximize Docker layer caching.
COPY pyproject.toml ./
RUN uv sync --no-install-project --no-cache
# Now copy the rest of the agent and finalize the environment.
COPY . ./
RUN uv sync --no-cache
EXPOSE 8088
CMD ["uv", "run", "--no-sync", "python", "main.py"]
@@ -0,0 +1,116 @@
# What this sample demonstrates
An [Agent Framework](https://github.com/microsoft/agent-framework) agent with a
**Monty-backed CodeAct context provider** hosted using the **Responses protocol**.
The model receives one tool (`execute_code`) and runs Python inside a
[Monty](https://github.com/pydantic/monty) interpreter; the registered host
tools (`compute`, `fetch_data`) are only reachable from inside the sandbox via
typed `await compute(...)` calls or the generic `call_tool(...)` fallback.
> [!NOTE]
> `agent-framework-monty` is an **alpha** package, so the `pyproject.toml`
> sets `[tool.uv] prerelease = "allow"` to let `uv sync` pick up the
> `1.0.0a*` release from PyPI.
## How It Works
### Model Integration
The agent uses `FoundryChatClient` to create a Responses client from the project
endpoint and the model deployment. The agent supports both streaming (SSE
events) and non-streaming (JSON) response modes.
See [main.py](main.py) for the full implementation.
### CodeAct context provider
`MontyCodeActProvider` is added to the agent via `context_providers=[...]`. On
every run it injects:
- An `execute_code` tool that runs Python in the Monty interpreter.
- Dynamic CodeAct instructions describing the available host tools and DSL.
The host tools (`compute`, `fetch_data`) are **not** exposed as direct agent
tools — the model can only call them from inside `execute_code`, either as
typed async functions (`await compute(operation="multiply", a=6, b=7)`) or via
the generic `call_tool("compute", operation="multiply", a=6, b=7)` fallback.
Code is type-checked against the host tool signatures using
[ty](https://docs.astral.sh/ty/) before any tool runs.
OS-level access (filesystem, network, subprocess) is blocked inside the
sandbox; the registered host tools retain full Python access.
### Observability
Agent Framework's [native OpenTelemetry instrumentation](https://learn.microsoft.com/en-us/agent-framework/agents/observability?pivots=programming-language-python) is enabled by setting these env vars in `agent.yaml` / `agent.manifest.yaml`:
- `ENABLE_INSTRUMENTATION=true` — turns on the framework's span/metric/log emitters.
- `ENABLE_SENSITIVE_DATA=true` — includes prompts, tool inputs, tool outputs, and completions in telemetry. **Dev/test only.**
`main.py` wires Azure Monitor at startup:
1. Reads `APPLICATIONINSIGHTS_CONNECTION_STRING` (Foundry hosting injects this automatically for the project's attached Application Insights resource; set it yourself when running locally).
2. Calls `azure.monitor.opentelemetry.configure_azure_monitor(connection_string=...)` to register Azure Monitor exporters with the global OTel tracer/meter/logger providers.
3. Calls `agent_framework.observability.enable_instrumentation()` so Agent Framework emits its `invoke_agent`, `chat`, `execute_tool`, and `execute_code` spans on those providers.
Trace linking happens automatically: the Foundry hosting layer's incoming `Responses` request becomes the **parent span**, and every framework / tool span (including the `execute_code` invocation that runs Monty) becomes a child via OpenTelemetry context propagation since both layers share the same global tracer provider. In Application Insights you can click any operation and see the full tree from inbound HTTP all the way down to individual `compute(...)` / `fetch_data(...)` calls inside the Monty sandbox.
## Running the Agent Host
This sample uses `pyproject.toml` + `uv sync` rather than the parent
README's `requirements.txt` flow. To run locally:
1. Install dependencies into a local virtual environment:
```bash
uv sync
```
2. Set the environment variables described in the
[parent README](../../README.md#running-the-agent-host-locally) (Foundry
project endpoint, model deployment, optional Application Insights), then
start the host:
```bash
uv run python main.py
```
Refer to the parent README for the shared `azd` / Docker / invocation /
deployment guidance.
## 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. Try queries that benefit from combining Python with multiple tool calls:
```bash
curl -X POST http://localhost:8088/responses \
-H "Content-Type: application/json" \
-d '{"input": "Fetch all users, find the admins, then multiply the count by 7. Use a single execute_code call."}'
```
```bash
curl -X POST http://localhost:8088/responses \
-H "Content-Type: application/json" \
-d '{"input": "Compute the total price for one of every product in the products table. Use execute_code."}'
```
The model should respond with one `execute_code` call whose code looks like:
```python
users = await fetch_data(table="users")
admins = [u for u in users if u["role"] == "admin"]
result = await compute(operation="multiply", a=len(admins), b=7)
print(result)
```
## 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,28 @@
name: agent-framework-agent-monty-codeact-responses
description: >
An Agent Framework agent with a Monty-backed CodeAct context provider hosted by Foundry.
metadata:
tags:
- Agent Framework
- AI Agent Hosting
- Azure AI AgentServer
- Responses Protocol
- CodeAct
- Monty
template:
name: agent-framework-agent-monty-codeact-responses
kind: hosted
protocols:
- protocol: responses
version: 2.0.0
environment_variables:
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
value: "{{AZURE_AI_MODEL_DEPLOYMENT_NAME}}"
- name: ENABLE_INSTRUMENTATION
value: "true"
- name: ENABLE_SENSITIVE_DATA
value: "true"
resources:
- kind: model
id: gpt-4.1-mini
name: AZURE_AI_MODEL_DEPLOYMENT_NAME
@@ -0,0 +1,15 @@
kind: hosted
name: agent-framework-agent-monty-codeact-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}
- name: ENABLE_INSTRUMENTATION
value: "true"
- name: ENABLE_SENSITIVE_DATA
value: "true"
@@ -0,0 +1,92 @@
# Copyright (c) Microsoft. All rights reserved.
import os
from typing import Annotated, Any, Literal
from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from agent_framework_foundry_hosting import ResponsesHostServer
from agent_framework_monty import MontyCodeActProvider
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv
from pydantic import Field
# Load environment variables from .env file (no-op when injected by Foundry).
load_dotenv()
@tool(approval_mode="never_require")
def compute(
operation: Annotated[
Literal["add", "subtract", "multiply", "divide"],
Field(description="Math operation: add, subtract, multiply, or divide."),
],
a: Annotated[float, Field(description="First numeric operand.")],
b: Annotated[float, Field(description="Second numeric operand.")],
) -> float:
"""Perform a math operation used by sandboxed code."""
operations = {
"add": a + b,
"subtract": a - b,
"multiply": a * b,
"divide": a / b if b else float("inf"),
}
return operations[operation]
@tool(approval_mode="never_require")
def fetch_data(
table: Annotated[str, Field(description="Name of the simulated table to query.")],
) -> list[dict[str, Any]]:
"""Fetch simulated records from a named table."""
data: dict[str, list[dict[str, Any]]] = {
"users": [
{"id": 1, "name": "Alice", "role": "admin"},
{"id": 2, "name": "Bob", "role": "user"},
{"id": 3, "name": "Charlie", "role": "admin"},
],
"products": [
{"id": 101, "name": "Widget", "price": 9.99},
{"id": 102, "name": "Gadget", "price": 19.99},
],
}
return data.get(table, [])
def main() -> None:
"""Host a Monty CodeAct agent over the Responses protocol."""
client = FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
credential=DefaultAzureCredential(),
)
# MontyCodeActProvider injects a sandboxed `execute_code` tool into every
# agent run, plus dynamic instructions describing the registered host tools.
# The host tools are hidden from the model - they can only be invoked from
# inside the sandbox (`await compute(...)` or `call_tool(...)`).
codeact = MontyCodeActProvider(
tools=[compute, fetch_data],
approval_mode="never_require",
)
agent = Agent(
client=client,
instructions=(
"You are a friendly assistant. Use `execute_code` to combine "
"Python control flow with the provided host tools whenever the "
"task requires lookups, transformations, or computation."
),
context_providers=[codeact],
# History will be managed by the hosting infrastructure, thus there
# is no need to store history by the service. Learn more at:
# https://developers.openai.com/api/reference/resources/responses/methods/create
default_options={"store": False},
)
server = ResponsesHostServer(agent)
server.run()
if __name__ == "__main__":
main()
@@ -0,0 +1,17 @@
[project]
name = "agent-framework-agent-monty-codeact-responses"
version = "0.1.0"
description = "Foundry-hosted Agent Framework agent with a Monty-backed CodeAct context provider."
requires-python = ">=3.12,<3.14"
dependencies = [
"agent-framework-foundry",
"agent-framework-foundry-hosting>=1.0.0a260630",
# agent-framework-monty is an alpha (1.0.0a*) release on PyPI.
"agent-framework-monty",
]
[tool.uv]
# `agent-framework-monty` is an alpha package; allow the prerelease resolver
# to pick up 1.0.0a* releases from PyPI.
prerelease = "allow"