ms-ai-architect/skills/ms-ai-engineering/references/agent-orchestration/agent-monitoring-observability.md
Kjell Tore Guttormsen ddce43d8b2 feat(ms-ai-architect): Spor 1 — Port-1-substrat migrert på 4 ikke-advisor-skills (243 Source + 327 Type + 325 TOC + stale-verified poison fjernet) [skip-docs]
Steg 9 (R4): unified migrate-corpus.mjs --write over engineering/governance/
infrastructure/security. 327 filer mutert, verified=null, prosa byte-identisk
(fra første ## seksjon), advisor urørt (0 endringer).

To applier-fixes oppdaget under kjøring (TDD, RED→GREEN):
- insertHeaderFields: anker faller nå tilbake når en meta-linje selv passerer
  500B (2 filer pakket et avsnitt i **Status:** → Type/Source landet utenfor
  scan-vinduet, applierens post-write-assertion fanget + restaurerte).
- normalizeStaleVerified: fjerner nå ALLE stale non-date **Verified:** i
  500B-vinduet, inkl. stray body-dup rett under --- (9 mlops-genaiops-filer var
  ellers falskt "verified"/fresh, droppet fra worklist). Operatør-godkjent
  utvidelse av carve-out; kun stray metadata-linjer, aldri prosa.

test-transform-criterion: precondition oppdatert til post-migrasjons-sannhet
(fila bærer nå Source). Suite 728/728 grønn.
2026-07-04 10:19:11 +02:00

377 lines
15 KiB
Markdown

# Agent Monitoring, Observability and Debugging
**Last updated:** 2026-02
**Status:** GA / Preview (Agent 365)
**Category:** Agent Orchestration & Automation
**Type:** reference
---
## Innhold
- [Introduksjon](#introduksjon)
- [Kjernekomponenter](#kjernekomponenter)
- [Distributed Tracing for Agents](#distributed-tracing-for-agents)
- [Agent Event Logging](#agent-event-logging)
- [Performance Profiling](#performance-profiling)
- [Error Categorization](#error-categorization)
- [Debugging Tools](#debugging-tools)
- [Observability SDK Integration](#observability-sdk-integration)
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
- [Beslutningsrammeverk](#beslutningsrammeverk)
- [For Cosmo](#for-cosmo)
## Introduksjon
Observability for agentsystemer går utover tradisjonell applikasjonsovervåking. Agenter opererer probabilistisk, tar dynamiske beslutninger, og produserer ulike outputs for identiske inputs. Denne ikke-deterministiske naturen krever spesialiserte overvåkingsverktøy som fanger ikke bare ytelsesmetrikker, men også beslutningsprosesser, verktøybruk, prompt-respons-par og evalueringskvalitet.
Microsoft tilbyr en komplett observability-stack for agenter gjennom Microsoft Foundry Tracing, Application Insights, Azure Monitor og Microsoft Agent 365. Foundry-plattformen integrerer OpenTelemetry-basert tracing med AI-spesifikke semantiske konvensjoner, slik at hvert LLM-kall, tool-invokasjon og orkestreringsbeslutning fanges som spans i en distribuert trace.
Agent 365 er Microsofts unified plattform for agentobservability på tvers av Copilot Studio, Microsoft Foundry og tredjepartsruntimes. Den gir enterprise-grade governance med sikkerhet, compliance og business impact-metrikker for hele agentflåten.
## Kjernekomponenter
| Komponent | Formål | Teknologi |
|-----------|--------|-----------|
| Distributed Tracing | Capture full request lifecycle | OpenTelemetry, Microsoft Foundry Tracing |
| Agent Event Logging | Logg agentbeslutninger og handlinger | Application Insights, Log Analytics |
| Performance Profiling | Identifiser flaskehalser | Azure Monitor Metrics, custom spans |
| Error Categorization | Klassifiser og prioriter feil | Azure Monitor Alerts, Sentinel |
| Debugging Tools | Interaktiv feilsøking | Foundry Portal, Aspire Dashboard |
| Agent 365 | Unified agent governance og observability | Microsoft Agent 365 platform |
## Distributed Tracing for Agents
### OpenTelemetry-basert tracing med Microsoft Foundry
```python
from azure.ai.projects import AIProjectClient
from azure.monitor.opentelemetry import configure_azure_monitor
from azure.identity import DefaultAzureCredential
import os
# Aktiver content recording for full prompt/respons-logging
os.environ["AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED"] = "true"
# Koble til prosjekt
project_client = AIProjectClient(
credential=DefaultAzureCredential(),
endpoint=os.environ["PROJECT_ENDPOINT"]
)
# Hent Application Insights connection string fra prosjektet
connection_string = (
project_client.telemetry
.get_application_insights_connection_string()
)
# Konfigurer Azure Monitor telemetry
configure_azure_monitor(connection_string=connection_string)
```
### Trace-konsepter
| Konsept | Beskrivelse | Eksempel |
|---------|------------|---------|
| Trace | Fullstendig reise for en forespørsel gjennom systemet | Bruker-spørsmål → routing → RAG → LLM → respons |
| Span | Enkeloperasjon innenfor en trace | Ett LLM-kall, ett tool-kall |
| Attributes | Nøkkel-verdi metadata på spans | `gen_ai.prompt`, `gen_ai.completion`, `tool.name` |
| Semantic Conventions | Standardiserte attributtnavn | OpenTelemetry GenAI semantic conventions |
### Custom spans for agentorkestrering
```python
from opentelemetry import trace
tracer = trace.get_tracer("agent-orchestrator")
async def orchestrate_agent_request(query: str, user_id: str):
with tracer.start_as_current_span("agent_orchestration") as root_span:
root_span.set_attribute("user.id", user_id)
root_span.set_attribute("query.text", query)
# Routing span
with tracer.start_as_current_span("intent_routing") as route_span:
routing = await classify_intent(query)
route_span.set_attribute("routing.target", routing.agent)
route_span.set_attribute("routing.confidence", routing.confidence)
route_span.set_attribute("routing.intent", routing.intent)
# RAG retrieval span
with tracer.start_as_current_span("rag_retrieval") as rag_span:
documents = await retrieve_context(query, routing.agent)
rag_span.set_attribute("rag.doc_count", len(documents))
rag_span.set_attribute("rag.sources",
[d.source for d in documents])
# Agent invocation span
with tracer.start_as_current_span("agent_invocation") as agent_span:
agent_span.set_attribute("agent.name", routing.agent)
response = await invoke_agent(routing.agent, query, documents)
agent_span.set_attribute("response.token_count",
response.usage.total_tokens)
agent_span.set_attribute("response.model", response.model)
root_span.set_attribute("total_tokens", response.usage.total_tokens)
return response
```
## Agent Event Logging
### Strukturert hendelseslogging
```python
import logging
import json
from datetime import datetime
class AgentEventLogger:
"""Strukturert logging for agent-hendelser"""
def __init__(self, app_insights_handler):
self.logger = logging.getLogger("agent-events")
self.logger.addHandler(app_insights_handler)
def log_agent_decision(self, event: dict):
"""Logg en agentbeslutning med full kontekst"""
self.logger.info(json.dumps({
"event_type": "agent_decision",
"timestamp": datetime.utcnow().isoformat(),
"agent_name": event["agent"],
"decision_type": event["type"], # routing, tool_selection, response
"input_summary": event.get("input_summary", ""),
"decision": event["decision"],
"confidence": event.get("confidence", None),
"reasoning": event.get("reasoning", ""),
"tokens_used": event.get("tokens", 0),
"latency_ms": event.get("latency_ms", 0),
"metadata": event.get("metadata", {})
}))
def log_tool_invocation(self, tool_name: str, input_params: dict,
output: str, duration_ms: float, success: bool):
self.logger.info(json.dumps({
"event_type": "tool_invocation",
"timestamp": datetime.utcnow().isoformat(),
"tool_name": tool_name,
"input_params": input_params,
"output_preview": output[:200],
"duration_ms": duration_ms,
"success": success
}))
```
## Performance Profiling
### KQL-spørringer for agentytelse
```kql
// Latency-breakdown per agent-komponent
traces
| where timestamp > ago(24h)
| where customDimensions.event_type == "agent_decision"
| extend
agent = tostring(customDimensions.agent_name),
decision_type = tostring(customDimensions.decision_type),
latency = todouble(customDimensions.latency_ms),
tokens = toint(customDimensions.tokens_used)
| summarize
p50_latency = percentile(latency, 50),
p95_latency = percentile(latency, 95),
p99_latency = percentile(latency, 99),
avg_tokens = avg(tokens),
request_count = count()
by agent, decision_type
| order by p95_latency desc
```
```kql
// Identifiser trege tool calls
traces
| where timestamp > ago(7d)
| where customDimensions.event_type == "tool_invocation"
| extend
tool = tostring(customDimensions.tool_name),
duration = todouble(customDimensions.duration_ms),
success = tobool(customDimensions.success)
| summarize
avg_duration = avg(duration),
p95_duration = percentile(duration, 95),
failure_rate = countif(success == false) * 100.0 / count(),
total_calls = count()
by tool
| where p95_duration > 2000 or failure_rate > 5
| order by p95_duration desc
```
### Azure Monitor dashboards
```kql
// Agent health dashboard - hoveddatakilder
let agent_health = traces
| where timestamp > ago(1h)
| where customDimensions.event_type in
("agent_decision", "tool_invocation")
| extend agent = tostring(customDimensions.agent_name)
| summarize
requests = count(),
errors = countif(customDimensions.success == "false"),
avg_latency = avg(todouble(customDimensions.latency_ms)),
avg_tokens = avg(todouble(customDimensions.tokens_used))
by agent, bin(timestamp, 5m);
agent_health
| render timechart
```
## Error Categorization
### Feilkategorisering for agentsystemer
| Kategori | Eksempler | Alvorlighet | Handling |
|----------|-----------|-------------|---------|
| Model Errors | Rate limit, timeout, content filter | Medium | Retry med backoff |
| Tool Failures | API-feil, timeout, ugyldige params | Medium | Fallback til alternativt verktøy |
| Routing Errors | Feil agent valgt, lav confidence | Lav | Logg + iterér på router-prompt |
| Hallucination | Agent fabrikkerer fakta | Høy | Groundedness-evaluering + alert |
| Safety Violations | Upassende innhold generert | Kritisk | Umiddelbar blokkering + varsling |
| Data Quality | RAG returnerer irrelevante dokumenter | Medium | Indeks-kvalitetsjekk |
```python
# Automatisk feilkategorisering
class AgentErrorClassifier:
ERROR_CATEGORIES = {
"rate_limit": {"severity": "medium", "retry": True},
"timeout": {"severity": "medium", "retry": True},
"content_filter": {"severity": "high", "retry": False},
"tool_failure": {"severity": "medium", "retry": True},
"hallucination": {"severity": "high", "retry": False},
"routing_error": {"severity": "low", "retry": True},
}
def classify(self, error: Exception, context: dict) -> dict:
if "429" in str(error):
return {**self.ERROR_CATEGORIES["rate_limit"],
"wait_seconds": self._extract_retry_after(error)}
if "timeout" in str(error).lower():
return self.ERROR_CATEGORIES["timeout"]
if "content_filter" in str(error).lower():
return self.ERROR_CATEGORIES["content_filter"]
# Default
return {"severity": "unknown", "retry": False}
```
## Debugging Tools
### Microsoft Foundry Portal
Foundry-portalen gir visuell trace-inspeksjon:
1. **Traces-visning**: Filter traces etter tidsrom, agent, bruker eller status
2. **Span-detaljer**: Se inputs, outputs og attributter for hver operasjon
3. **Call tree**: Visualiser hierarkisk relasjon mellom spans
4. **Evaluering**: Se evalueringsresultater direkte på traces
### Aspire Dashboard for lokal debugging
```python
# Lokal debugging med Aspire Dashboard
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
OTLPSpanExporter
)
# Eksporter til Aspire Dashboard (localhost:4317)
exporter = OTLPSpanExporter(endpoint="http://localhost:4317")
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(SimpleSpanProcessor(exporter))
trace.set_tracer_provider(tracer_provider)
# Alle agent-operasjoner vises nå i Aspire Dashboard
# Start med: docker run --rm -p 18888:18888 -p 4317:18889 \
# mcr.microsoft.com/dotnet/aspire-dashboard:latest
```
### Debugging-strategi for agenter
```
1. Reprodusér → Finn den spesifikke tracen i Foundry/AppInsights
2. Isolér → Identifiser hvilken span som forårsaket problemet
3. Inspiser → Se prompt, kontekst og respons for den spannen
4. Hypotese → Er det routing? RAG? Modell? Verktøy?
5. Test → Kjør isolert test med samme input
6. Fiks → Oppdater prompt/config/verktøy
7. Verifiser → Sammenlign metrikker før/etter
```
## Observability SDK Integration
### Agent Framework observability
```csharp
// Microsoft Agent Framework med full observability
var builder = WebApplication.CreateBuilder(args);
// Aktiver agent observability
builder.Services.AddAgentObservability(options =>
{
options.EnableSensitiveData = true; // Full prompt logging
options.ServiceName = "customer-support-agent";
options.ExportToApplicationInsights(
connectionString: builder.Configuration["AppInsights:ConnectionString"]
);
});
```
## Norsk offentlig sektor
| Aspekt | Krav | Implementering |
|--------|------|----------------|
| Logging av AI-beslutninger | EU AI Act Art. 12 | Full trace med decision reasoning |
| Personvern i logger | GDPR Art. 5 | Redact PII fra traces, eller disable content recording |
| Arkivering | Arkivloven | Retensjon av agent-traces minimum 5 år |
| Innsyn | Offentlighetsloven | Tilgjengeliggjør agent-beslutningslogger for innsyn |
| Sikkerhetshendelser | NSM Grunnprinsipper | Azure Sentinel-integrasjon for anomali-deteksjon |
### Personvern i observability
```python
# Sensitive data redaction for offentlig sektor
import re
class PIIRedactor:
PATTERNS = {
"fnr": r"\b\d{11}\b", # Fødselsnummer
"email": r"\b[\w.-]+@[\w.-]+\.\w+\b",
"phone": r"\b(?:\+47|0047)?\s*\d{8}\b",
}
def redact(self, text: str) -> str:
for pii_type, pattern in self.PATTERNS.items():
text = re.sub(pattern, f"[REDACTED_{pii_type.upper()}]", text)
return text
# Bruk i tracing
redactor = PIIRedactor()
span.set_attribute("query.text", redactor.redact(query))
```
## Beslutningsrammeverk
| Scenario | Anbefaling | Begrunnelse |
|----------|------------|-------------|
| Utvikling/testing | Aspire Dashboard + full content recording | Maksimal synlighet for debugging |
| Pre-produksjon | Foundry Tracing + evaluatorer | Kvalitetssikring før lansering |
| Produksjon standard | Application Insights + 10% sampling | Balanse mellom synlighet og kostnad |
| Produksjon høy-risiko | 100% tracing + Sentinel + Agent 365 | Full compliance og sikkerhet |
| Multi-team organisasjon | Agent 365 + sentralisert Log Analytics | Unified governance på tvers av team |
## For Cosmo
- **OpenTelemetry-basert tracing er fundamentet** -- all agent-observability bygger på traces med spans. Implementer fra dag 1, ikke legg til etterpå.
- **Agent 365** er veien fremover for enterprise-scale agent governance -- det gir unified synlighet på tvers av Copilot Studio, Foundry og tredjepartsagenter.
- **Redact PII i traces for offentlig sektor** -- bruk `AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED=false` i produksjon med persondata, eller implementer custom redaction.
- **KQL er ditt viktigste verktøy** for å analysere agent-atferd i produksjon -- bygg dashboards for latency, feilrater, token-bruk og kvalitetsmetrikker per agent.
- **Debugging-workflow**: Start alltid med å finne tracen, deretter isolér den problematiske spannen -- 90% av agent-feil kan diagnostiseres ved å inspisere prompt, kontekst og respons.