Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/publish .

ENV ASPNETCORE_URLS=http://0.0.0.0:8088
EXPOSE 8088

ENTRYPOINT ["dotnet", "SystemUtilityAgent.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Azure.AI.AgentServer.Core.Context;
using Azure.AI.AgentServer.Responses.Invocation;
using Microsoft.Extensions.DependencyInjection;

// Run Agent Server with customized agent invocation factory
// Uses DI to provide IAgentInvocation.
await AgentServerApplication.RunAsync(new ApplicationOptions(
ConfigureServices: services => services.AddSingleton<IAgentInvocation, SystemUtilityAgentInvocation>(),
TelemetrySourceName: "SystemUtilityAgent"
)).ConfigureAwait(false);
Comment on lines +7 to +10
Copy link
Contributor

@iuiaoin iuiaoin Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the .NET version of adapter sample usage is like:

var agent = new ChatClientAgent(chatClient,
      name: "AgentWithHostedMCP",
      instructions: @"You are a helpful assistant with access to tools for fetching Microsoft documentation.

  IMPORTANT: When the user asks about Microsoft Learn articles or documentation:
  1. You MUST use the microsoft_docs_fetch tool to retrieve the actual content
  2. Do NOT rely on your training data
  3. Always fetch the latest information from the provided URL

  Available tools:
  - microsoft_docs_fetch: Fetches and converts Microsoft Learn documentation
  - microsoft_docs_search: Searches Microsoft/Azure documentation
  - microsoft_code_sample_search: Searches for code examples")
      .AsBuilder()
      .UseFoundryTools(FoundryConnectedTool.Mcp(toolConnectionId))
      .UseOpenTelemetry(sourceName: "Agents", configure: (cfg) => cfg.EnableSensitiveData = true)
      .Build();

// Run agent with tool support using ToolDefinition objects
await agent.RunAIAgentAsync(telemetrySourceName: "Agents");

Is SystemUtilityAgentInvocation an existing built-in AgentInvocation, or do I need to implement it myself? I was trying running this sample locally, but I couldn’t find SystemUtilityAgentInvocation in the codebase ('SystemUtilityAgentInvocation' could not be found).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"SystemUtilityAgent": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"AZURE_AI_PROJECT_ENDPOINT": "",
"AZURE_AI_MODEL_DEPLOYMENT_NAME": "gpt-4o-mini",
"OPENAI_API_VERSION": "2025-03-01-preview",
"AZURE_OPENAI_API_KEY": "",
"AGENT_MAX_TURNS": "10",
"AGENT_APP_INSIGHTS_ENABLED": "true",
"APPLICATIONINSIGHTS_CONNECTION_STRING": ""
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md).

Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct.

Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates.

Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output.

# What this sample demonstrates

This sample demonstrates a **C# System Utility Agent** hosted using the Azure AI AgentServer SDK.

It shows:

- How to host a custom agent by implementing `IAgentInvocation`
- How to emit OpenAI Responses-compatible REST responses (streaming and non-streaming)
- How to add **custom spans** into hosted agent traces (via `ActivitySource`)
- How to call **Azure OpenAI** (Responses API) and use the model to decide which tool(s) to invoke (tool-calling loop)
- A set of cross-platform “system utility” actions (processes, ports, DNS, env vars) that are container-aware

## How It Works

### System Utility Agent

This agent is designed for diagnostics and “what’s running here?” questions. It is **container-aware** and will report whether the agent is likely seeing the container namespace vs the host.

The agent exposes a small set of utility actions and returns results as JSON.

At runtime, the agent:

1. Sends the user request to Azure OpenAI (Responses API) along with the available tool definitions
2. Executes any tool calls the model requests
3. Feeds tool results back to the model as `function_call_output`
4. Repeats until the model returns a final assistant message

Actions supported:

1. **capability_report** - Report what the agent can likely observe (host vs container scope)
2. **system_info** - OS / runtime metadata
3. **resource_snapshot** - Process + GC + disk snapshot (best-effort cross-platform)
4. **list_processes** - List running processes (visibility depends on container scope)
5. **process_details** - Get details for a specific PID
6. **check_port** - Check whether a TCP port is reachable
7. **dns_lookup** - Resolve a hostname
8. **list_environment_variables** - List environment variables (supports redaction)

### Tracing (custom spans)

This sample demonstrates how to add **custom spans** to hosted agent traces using .NET `ActivitySource`.

Spans are created for:

- Each tool-calling iteration of the agent loop (`SystemUtilityAgent.agent_run_iteration`)
- Each tool call execution (`SystemUtilityAgent.tool_call_execution`), including tags such as:
- `gen_ai.tool.name`
- `gen_ai.tool.call.arguments` (truncated)
- `gen_ai.tool.call.result`

The hosted endpoint also emits the standard AgentServer request spans for the overall invocation.

### Agent Hosting

The agent is hosted using the Azure AI AgentServer SDK, which provisions a REST API endpoint compatible with the OpenAI Responses protocol.

## Running the Agent Locally

### Prerequisites

Before running this sample, ensure you have:

1. .NET 8 SDK installed
2. An Azure OpenAI endpoint configured
3. A deployment of a chat model (e.g., `gpt-4o-mini`)

### Environment Variables

Set the following environment variables:

- `AZURE_OPENAI_ENDPOINT` - Your Azure OpenAI endpoint URL (required)
- `AZURE_AI_MODEL_DEPLOYMENT_NAME` - The Azure OpenAI model deployment name (optional, defaults to `gpt-4o-mini`)

Authentication (choose one):

- `AZURE_OPENAI_API_KEY` for key-based auth, OR
- `az login` so `DefaultAzureCredential` can acquire a token

Optional:

- `OPENAI_API_VERSION` - Defaults to `2025-03-01-preview`

```powershell
$env:AZURE_OPENAI_ENDPOINT="https://your-openai-resource.openai.azure.com/"
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"

# Option A: key-based
$env:AZURE_OPENAI_API_KEY="<your key>"

# Option B: AAD-based
# az login

# Optional
$env:OPENAI_API_VERSION="2025-03-01-preview"
```

### Running the Sample

From the project folder:

```powershell
cd samples/csharp/hosted-agents/AgentWithCustomFramework/SystemUtilityAgent

dotnet run
```

By default, the AgentServer host listens on `http://localhost:8088`.

### Interacting with the Agent

You can interact with the agent workflow using:

- The `run-requests.http` file in this directory to test and prompt the agent
- Any OpenAI Responses compatible client by sending requests to `http://localhost:8080/`

### Deploying the Agent to Microsoft Foundry

To deploy your agent to Microsoft Foundry, follow the comprehensive deployment guide at https://aka.ms/azdaiagent/docs

## Troubleshooting

### After deployed, the agent appears stateless (chat history is not preserved)

This agent will remain stateless before Azure.AI.Projects supports conversation client.

### Images built on Apple Silicon or other ARM64 machines do not work on our service

We **recommend using `azd` cloud build**, which always builds images with the correct architecture.

If you choose to **build locally**, and your machine is **not `linux/amd64`** (for example, an Apple Silicon Mac), the image will **not be compatible with our service**, causing runtime failures.

**Fix for local builds**

Use this command to build the image locally:

```shell
docker build --platform=linux/amd64 -t image .
```

This forces the image to be built for the required `amd64` architecture.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);OPENAI001</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.AI.AgentServer.Core" Version="1.0.0-beta.5" />
<PackageReference Include="Azure.AI.AgentServer.Contracts" Version="1.0.0-beta.5" />
<PackageReference Include="Azure.Identity" Version="1.16.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="OpenAI" Version="2.8.0" />
</ItemGroup>
</Project>
Loading