📘 Full step-by-step tutorial:
Build an Evidence-First Incident Triage Agent with Microsoft Agent Framework
This repository contains the verified companion implementation for the tutorial above. The sample focuses on deterministic evidence, read-only function tools, AgentSession, streaming, and explicit separation between observed facts, inference, guidance, unknowns, and unproven claims.
A minimal .NET 10 console companion sample for the Microsoft Agent Framework tutorial. It builds a tool-using AI agent that triages a sample incident using deterministic operational evidence, read-only function tools, and a shared agent session — with no live model required to build or test it.
This sample is an independent educational reference and is not an official Microsoft sample or specification.
IChatClientprovider boundary — provider-specific OpenRouter configuration stays inProgram.cs; everything else works against the neutralIChatClientabstraction.AIAgent— agent creation, instructions, and tool registration are centralized in a factory.AgentSession— one session is created for the incident and reused for the same-session follow-up question.- Streaming — model responses are produced with
RunStreamingAsyncand consumed asAgentResponseUpdate. - Three read-only function tools —
get_service_health,get_recent_deployment, andget_runbook, created withAIFunctionFactory.Create. - Deterministic evidence — observed operational facts are loaded from embedded JSON (
services.json,deployments.json). - Separate runbook guidance — reference investigation guidance is loaded independently from evidence (
runbooks.json). - Missing-field behavior — absent evidence stays unknown; the agent is instructed never to invent missing facts.
- Correlation vs causation — the sample shows that temporal correlation does not establish root cause.
- Deterministic tests without an API key — the evidence, guidance, and tool layers are fully unit-tested offline.
Program.cs → IChatClient → TriageAgentFactory → AIAgent → AgentSession
│
┌───────────────┬───────────────┬────────┘
▼ ▼ ▼
ServiceHealthTool DeploymentTool RunbookTool
│ │ │
EvidenceStore EvidenceStore RunbookStore
│ │ │
services.json deployments.json runbooks.json
See docs/architecture.md for the full design discussion.
AgentFrameworkIncidentTriage.slnx
global.json
verified-environment.json
docs/
├── architecture.md
├── evidence-first-contract.md
├── sample-run.md
├── tool-risk-ladder.md
└── verified-environment.md
src/
└── IncidentTriageAgent/
├── Program.cs
├── Agents/TriageAgentFactory.cs
├── Data/ (embedded JSON evidence + runbooks)
├── Evidence/ (EvidenceItem, EvidenceStore)
├── Guidance/ (RunbookItem, RunbookStore)
└── Tools/ (ServiceHealthTool, DeploymentTool, RunbookTool)
tests/
└── IncidentTriageAgent.Tests/
├── EvidenceStoreTests.cs
├── RunbookStoreTests.cs
└── ToolTests.cs
- .NET 10 SDK
- An API key is required only for live execution. Building and testing require no API key and no internet connection to a model provider.
dotnet restore AgentFrameworkIncidentTriage.slnx
dotnet build AgentFrameworkIncidentTriage.slnx --configuration Release --no-restore
dotnet test AgentFrameworkIncidentTriage.slnx --configuration Release --no-buildExpected: build with 0 errors, and 14/14 deterministic tests passing.
With no OPENROUTER_API_KEY set, the application prints a short notice and exits safely — it makes no live model call:
dotnet run --project src/IncidentTriageAgentOPENROUTER_API_KEY is not configured.
The project can build and test without an API key.
Run 'dotnet test' to verify the deterministic evidence and tool layers.
Set OPENROUTER_API_KEY only when you want to run the live agent.
The live path uses OpenRouter's OpenAI-compatible endpoint with model openai/gpt-4o-mini (override with OPENROUTER_MODEL).
PowerShell:
$env:OPENROUTER_API_KEY="YOUR_KEY"
dotnet run --project src/IncidentTriageAgentBash:
export OPENROUTER_API_KEY="YOUR_KEY"
dotnet run --project src/IncidentTriageAgent.env files are not automatically loaded. Replace YOUR_KEY with a real key only when you intend to make a live model request — never commit it.
The agent retrieves operational evidence (for example E-101, E-201) and separate runbook guidance (RB-CHECKOUT-03), and distinguishes what is known from what is inferred. Missing fields remain unknown, guidance is not evidence, and correlation is not treated as proof of causation. This is the repository-specific Evidence-First Agent Contract — see docs/evidence-first-contract.md.
All three tools in this sample are read-only Level 0 / Level 1 tools: they query deterministic stores and perform no operational write. The agent can recommend investigation steps but cannot restart services, roll back deployments, or modify configuration. See docs/tool-risk-ladder.md.
A controlled live run was captured while the deterministic tests were passing — see docs/sample-run.md. Note that LLM wording is probabilistic and may vary between runs; the deterministic layer is stable and fully tested.
This first Agent Framework sample deliberately does not implement: MCP, RAG, vector search, persistent long-term memory, multi-agent workflows, automatic remediation, write-capable tools, service restart/rollback tools, configuration mutation, human approval workflows, durable orchestration, production hosting, A2A, or AG-UI. The tutorial focuses on provider abstraction, tool calling, session state, deterministic evidence, and evidence-aware reasoning. See docs/architecture.md and the full tutorial for the follow-on topics.
| Item | Value |
|---|---|
| Target framework | net10.0 |
| SDK baseline | 10.0.401 |
| Microsoft.Agents.AI.OpenAI | 1.22.0 |
| Deterministic tests | 14/14 passing |
| Live provider used for verification | OpenRouter |
| Live model used for verification | openai/gpt-4o-mini |
| Live run verification date | 26 September 2026 |
Environment details: docs/verified-environment.md · verified-environment.json
Repository-owned sample code is available under the MIT License.