Skip to content

Commit 79619d0

Browse files
alliscodealliscodeCopilot
authored
Toolbox sample (#179)
* Add foundry-toolbox hosted agent sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add foundry-toolbox-server-side hosted agent sample Demonstrates loading a Foundry Toolbox and passing its tools to the agent as server-side tools via GetToolboxToolsAsync(). Contrasts with the existing foundry-toolbox sample, which resolves tools client-side via AddFoundryToolboxes(). Also lists both toolbox samples in the parent README sample index. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add code_interpreter to foundry-toolbox-server-side toolbox Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Specify code_interpreter container for server-side Responses API The Responses API rejects a code_interpreter tool without a container: HTTP 400 invalid_payload, param /tools/0/container. Adding container.type=auto satisfies the requirement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump Agent Framework packages to latest in .NET MAF samples - Microsoft.Agents.AI.Foundry.Hosting 1.2.0-preview.260421.1 -> 1.3.0-preview.260423.1 - Microsoft.Agents.AI.Workflows 0.0.1-preview.260417.2 -> 1.3.0 (workflows sample) - ModelContextProtocol 1.1.0 -> 1.2.0 (mcp-tools sample) Azure.AI.Projects is already at latest (2.1.0-beta.1); Azure.AI.AgentServer.Invocations is already at latest (1.0.0-beta.3). All 9 samples build clean with 0 warnings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bridge platform-injected toolbox endpoint env var in C# foundry-toolbox sample The Foundry hosted-agent runtime injects TOOLBOX_<NAME>_MCP_ENDPOINT (full URL with pinned toolbox version), but Microsoft.Agents.AI.Foundry.Hosting 1.3 expects a base URL in FOUNDRY_AGENT_TOOLSET_ENDPOINT. Without the bridge, the FoundryToolboxService logs 'toolbox support is disabled' and the agent falls back to model-only behavior (hallucinating tools). Derive the base URL and api-version from the injected variable before calling AddFoundryToolboxes(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Connect C# foundry-toolbox sample directly to MCP proxy AddFoundryToolboxes() from Microsoft.Agents.AI.Foundry.Hosting 1.3 cannot be used end-to-end on the current hosted-agent platform: it expects a base URL in FOUNDRY_AGENT_TOOLSET_ENDPOINT (not injected by the runtime) and uses the wrong token audience (cognitiveservices.azure.com/.default) for the Foundry Toolbox MCP proxy, which requires https://ai.azure.com/.default. Replace the helper with a direct ModelContextProtocol McpClient call that: - reads the per-toolbox endpoint from TOOLBOX_<NAME>_MCP_ENDPOINT - attaches a bearer token with the ai.azure.com audience - discovers tools and passes them to AsAIAgent(..., tools: [..tools]) A future SDK release is expected to handle both natively; this sample can then revert to AddFoundryToolboxes(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove C# foundry-toolbox (client-side) sample Remove the client-side AddFoundryToolboxes() sample until the SDK natively handles the hosted-agent platform's TOOLBOX_<NAME>_MCP_ENDPOINT injection and uses the correct (ai.azure.com) token audience for the toolbox MCP proxy. The server-side foundry-toolbox-server-side sample covers toolbox integration in the meantime. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove dangling references to deleted foundry-toolbox sample Cleans up the comment block in Program.cs and the comparison table in README.md that referenced the now-removed client-side foundry-toolbox sample. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add env vars to dotnet agent.yaml files for VS Code dev path The agent.yaml files are consumed by the local VS Code development path and need to declare the same env vars as agent.manifest.yaml. Adds AZURE_AI_MODEL_DEPLOYMENT_NAME to the six samples that use it; mirrors the pattern already in foundry-toolbox-server-side/agent.yaml. invocations-echo-agent declares no env vars and is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 585458f commit 79619d0

22 files changed

Lines changed: 231 additions & 9 deletions

File tree

samples/csharp/hosted-agents/agent-framework/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This directory contains samples that demonstrate how to use the [Agent Framework
1414
| 4 | [mcp-tools](mcp-tools/) | An agent demonstrating client-side and server-side MCP tool integration. |
1515
| 5 | [text-search-rag](text-search-rag/) | A support agent with RAG capabilities using `TextSearchProvider`. |
1616
| 6 | [workflows](workflows/) | A multi-agent translation pipeline using `WorkflowBuilder`. |
17+
| 7 | [foundry-toolbox-server-side](foundry-toolbox-server-side/) | An agent that loads a Foundry Toolbox with `GetToolboxToolsAsync()` and passes its tools as server-side tools — Foundry executes them on the agent's behalf. |
1718

1819
### Invocations API
1920

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
**/bin
2+
**/obj
3+
**/.vs
4+
**/.vscode
5+
**/.idea
6+
**/*.user
7+
**/.env
8+
**/.env.*
9+
!**/.env.example
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Foundry project endpoint — auto-injected in hosted containers.
2+
# Only set manually if running without `azd ai agent run`.
3+
# FOUNDRY_PROJECT_ENDPOINT=https://<account>.services.ai.azure.com/api/projects/<project>
4+
5+
# Model deployment name — must match a deployment in your Foundry project.
6+
AZURE_AI_MODEL_DEPLOYMENT_NAME=
7+
8+
# Toolbox name — must match a toolbox in your Foundry project.
9+
# When deploying with `azd provision`, the toolbox is created automatically
10+
# from the resources declared in agent.manifest.yaml.
11+
TOOLBOX_NAME=agent-tools
12+
13+
# Application Insights — auto-injected in hosted containers.
14+
# Set for local telemetry (optional but recommended).
15+
# APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=...
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
2+
WORKDIR /src
3+
COPY . .
4+
RUN dotnet restore
5+
RUN dotnet build -c Release --no-restore
6+
RUN dotnet publish -c Release --no-build -o /app
7+
8+
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
9+
WORKDIR /app
10+
COPY --from=build /app .
11+
EXPOSE 8088
12+
ENTRYPOINT ["dotnet", "foundry-toolbox-server-side.dll"]
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
/*
4+
* Foundry Toolbox (Server-Side Tools) — Agent Framework Responses agent for C#
5+
*
6+
* Hosted agent that loads a Foundry Toolbox and passes its tools to the agent as
7+
* SERVER-SIDE tools. The Foundry platform handles tool discovery and invocation
8+
* through the Responses API — the agent process does not connect to the toolbox
9+
* MCP proxy or invoke tools locally.
10+
*
11+
* Required environment variables:
12+
* FOUNDRY_PROJECT_ENDPOINT — Foundry project endpoint (auto-injected in hosted containers)
13+
* AZURE_AI_MODEL_DEPLOYMENT_NAME — Model deployment name (declared in agent.manifest.yaml)
14+
* TOOLBOX_NAME — Name of the Foundry Toolbox to load
15+
*/
16+
17+
#pragma warning disable OPENAI001 // GetToolboxToolsAsync is experimental
18+
19+
using Azure.AI.AgentServer.Core;
20+
using Azure.AI.Projects;
21+
using Azure.Identity;
22+
using DotNetEnv;
23+
using Microsoft.Agents.AI;
24+
using Microsoft.Agents.AI.Foundry.Hosting;
25+
26+
// Load .env file if present (for local development)
27+
Env.TraversePath().Load();
28+
29+
var projectEndpoint = new Uri(Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
30+
?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT environment variable is not set."));
31+
32+
var deployment = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME")
33+
?? throw new InvalidOperationException("AZURE_AI_MODEL_DEPLOYMENT_NAME environment variable is not set.");
34+
35+
var toolboxName = Environment.GetEnvironmentVariable("TOOLBOX_NAME")
36+
?? throw new InvalidOperationException("TOOLBOX_NAME environment variable is not set.");
37+
38+
// Fetch the toolbox's tools from Foundry. Omitting the version resolves the toolbox's
39+
// current default version. The returned AITools are passed directly to the agent as
40+
// server-side tools — Foundry will execute them on the agent's behalf.
41+
var projectClient = new AIProjectClient(projectEndpoint, new DefaultAzureCredential());
42+
var tools = await projectClient.GetToolboxToolsAsync(toolboxName);
43+
44+
AIAgent agent = projectClient
45+
.AsAIAgent(
46+
model: deployment,
47+
instructions: "You are a helpful assistant with access to Azure AI Foundry toolbox tools. "
48+
+ "Use the available tools to help answer user questions. Be concise.",
49+
name: "foundry-toolbox-server-side",
50+
description: "Agent with Foundry Toolbox integration using server-side tools.",
51+
tools: [.. tools]);
52+
53+
var builder = AgentHost.CreateBuilder(args);
54+
builder.Services.AddFoundryResponses(agent);
55+
builder.RegisterProtocol("responses", endpoints => endpoints.MapFoundryResponses());
56+
57+
var app = builder.Build();
58+
app.Run();
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Foundry Toolbox — Server-Side Tools
2+
3+
An agent that loads a Foundry Toolbox and passes its tools to the agent as **server-side tools**. The Foundry platform handles tool discovery and invocation through the Responses API — the agent process does not connect to the toolbox MCP proxy or invoke tools locally.
4+
5+
`GetToolboxToolsAsync()` fetches the tool definitions from the configured toolbox and they are then passed to `AsAIAgent(..., tools: ...)`. At runtime the Foundry platform invokes those tools server-side on the agent's behalf, so the agent container only needs the control-plane call to fetch the definitions — it does not broker MCP connections.
6+
7+
## Creating a Foundry Toolbox
8+
9+
You can create a Foundry Toolbox by code. Refer to this sample for an example: [Foundry Toolbox CRUD Sample](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolboxes_crud.py).
10+
11+
You can also create a Foundry Toolbox in the Foundry portal. Read more about it [in the Foundry toolbox documentation](https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/tools/toolbox).
12+
13+
> If you set up a project with this sample and provision the resources using `azd provision`, a Foundry Toolbox will be created with the tools declared in [`agent.manifest.yaml`](agent.manifest.yaml) — by default, `code_interpreter` (server-side code execution) plus an `mcp` tool pointing at the public `https://gitmcp.io/Azure/azure-rest-api-specs` MCP server. Swap either out for any other toolbox tool type that fits your scenario.
14+
15+
## Running the Agent Host
16+
17+
Follow the instructions in the [Running the Agent Host Locally](../README.md#running-the-agent-host-locally) section of the parent README to run the agent host.
18+
19+
## Interacting with the agent
20+
21+
> 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.
22+
23+
```bash
24+
curl -X POST http://localhost:8088/responses -H "Content-Type: application/json" -d '{"input": "What tools do you have?", "stream": false}'
25+
curl -X POST http://localhost:8088/responses -H "Content-Type: application/json" -d '{"input": "Find the latest API version for Microsoft.CognitiveServices accounts in the azure-rest-api-specs repo.", "stream": false}'
26+
curl -X POST http://localhost:8088/responses -H "Content-Type: application/json" -d '{"input": "Use the code interpreter to compute the 30th Fibonacci number.", "stream": false}'
27+
```
28+
29+
## Deploying the Agent to Foundry
30+
31+
To deploy the agent to Foundry, follow the instructions in the [Deploying the Agent to Foundry](../README.md#deploying-the-agent-to-foundry) section of the parent README.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/AgentManifest.yaml
2+
name: foundry-toolbox-server-side-dotnet-agent-framework
3+
displayName: "Foundry Toolbox — Server-Side Tools (.NET, Agent Framework)"
4+
description: >
5+
Agent Framework agent that loads a Foundry Toolbox and passes its tools to the
6+
agent as server-side tools. The Foundry platform executes tool calls through the
7+
Responses API — the agent does not connect to the toolbox MCP proxy locally.
8+
metadata:
9+
tags:
10+
- AI Agent Hosting
11+
- Responses Protocol
12+
- Agent Framework
13+
- Toolbox
14+
- MCP
15+
- Server-Side Tools
16+
- .NET
17+
template:
18+
name: foundry-toolbox-server-side-dotnet-agent-framework
19+
kind: hosted
20+
protocols:
21+
- protocol: responses
22+
version: 1.0.0
23+
environment_variables:
24+
# FOUNDRY_PROJECT_ENDPOINT and APPLICATIONINSIGHTS_CONNECTION_STRING
25+
# are injected by the platform (hosted) and translated by azd (local)
26+
# — do NOT declare them here.
27+
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
28+
value: "{{AZURE_AI_MODEL_DEPLOYMENT_NAME}}"
29+
- name: TOOLBOX_NAME
30+
value: "agent-tools"
31+
resources:
32+
- kind: model
33+
id: gpt-4.1-mini
34+
name: AZURE_AI_MODEL_DEPLOYMENT_NAME
35+
- kind: toolbox
36+
name: agent-tools
37+
tools:
38+
- type: code_interpreter
39+
container:
40+
type: auto
41+
- type: mcp
42+
server_label: api_specs
43+
server_url: "https://gitmcp.io/Azure/azure-rest-api-specs"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml
2+
kind: hosted
3+
name: foundry-toolbox-server-side-dotnet-agent-framework
4+
protocols:
5+
- protocol: responses
6+
version: 1.0.0
7+
resources:
8+
cpu: "0.25"
9+
memory: 0.5Gi
10+
environment_variables:
11+
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
12+
value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME}
13+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<RootNamespace>FoundryToolboxServerSide</RootNamespace>
6+
<AssemblyName>foundry-toolbox-server-side</AssemblyName>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
<NoWarn>$(NoWarn);NU1903;NU1605</NoWarn>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<!-- Agent Framework hosting — provides AgentHost, AddFoundryResponses, MapFoundryResponses,
14+
and the GetToolboxToolsAsync extension on AIProjectClient. -->
15+
<PackageReference Include="Microsoft.Agents.AI.Foundry.Hosting" Version="1.3.0-preview.260423.1" />
16+
<!-- Foundry SDK — provides AIProjectClient and AsAIAgent. -->
17+
<PackageReference Include="Azure.AI.Projects" Version="2.1.0-beta.1" />
18+
<!-- .env file support for local development. -->
19+
<PackageReference Include="DotNetEnv" Version="3.1.1" />
20+
</ItemGroup>
21+
22+
</Project>

samples/csharp/hosted-agents/agent-framework/hello-world/agent.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ protocols:
77
resources:
88
cpu: "0.25"
99
memory: 0.5Gi
10+
environment_variables:
11+
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
12+
value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME}

0 commit comments

Comments
 (0)