ms-ai-architect/skills/ms-ai-engineering/references/agent-orchestration/agent-compliance-and-audit-trails.md
Kjell Tore Guttormsen 3a73eeafdc refactor(ms-ai-architect): R13 del 1 — nøytraliser Cosmo-personaen i ref-korpusets headinger, etter å ha rettet en gate som var målt usann to ganger
Ordre 20260912T193441Z-7358817909. Steg 1 var ikke transformen, men å rette
roadmapens R13-gate og få den ratifisert. Gaten `grep -rl "Cosmo"
skills/*/references -> 0` var usann på to uavhengige måter:

1. Ordren fanget den første: 451 av forekomstene er Azure Cosmos DB, ekte
   produktinnhold. Diskriminatoren er ikke bokstaven «s» — `Cosmos <norsk
   substantiv>` er genitiv av personaen (`### Cosmos tonalitet`), mens
   `Cosmos DB`/`CosmosClient`/`cosmos_ru` er produkt.
2. Denne økten fant den andre: 132 persona-forekomster ligger i prosa,
   tabeller, dialog-replikker og proveniens-linjer. Heading-nøytralisering
   kan ikke nå dem, så «0 persona» er uoppnåelig også under den ratifiserte
   formen. Operatøren ratifiserte alternativ A: gaten speiler formen, og de
   132 bokføres til R13b/R14.

Tre korreksjoner av premisser som sto i ordren og STATE:
  «ca 320 produkt»   -> 451 (case-sensitivt nett manglet 327 lowercase
                        TOC-ankre + 99 identifikatorer; sann nevner 1 638)
  «169 headinger»    -> 401. 169 var `^## For Cosmo`-prefikset (168) og var
                        internt inkonsistent med sin egen topp-variant (204)
  «417 matcher ingen
   populasjon»       -> 417 er cosmo-headinger utenfor kodefences; briefens
                        nevner var reell hele tiden

Fence-bevissthet er målt skadelig, ikke nødvendig: begge toggle-regler er
gale på dette korpuset (naiv toggle skjuler en ekte heading i
chain-of-thought-prompting.md, CommonMark-regelen ubalanserer
service-level-documentation-dr.md). Fence-agnostisk deteksjon finner 401
heading-linjer i nøyaktig de samme 40 variantene som fence-bevisst finner
400 i — ingen kodeblokk-linje er byte-identisk til en persona-heading. Derfor
nøkles transformen på 40 enumererte heading-tekster og ignorerer fences. En
ukjent variant kaster; en slug-kollisjon kaster. Ingenting auto-fikses.

TOC-en regenereres ikke, den rettes kirurgisk: alle 327 persona-lenker hadde
lenketekst lik én av de 40 heading-tekstene og anker lik slugify av den
(327/327, 0 avvik), så heading og TOC-entry skrives i samme operasjon og
ingen mellomtilstand etterlater en død lenke.

Ratifisert målform: `For Cosmo`, `For Cosmo Skyberg` og `For arkitekten
(Cosmo)` konvergerer på `For arkitekten`. To filer kolliderte og er adjudisert
ved å lese dem, ikke ved regel.

Verifisering (alle 7 kriterier fra ordren):
  G1 persona på heading-linjer   401 -> 0
  G2 døde fragmentlenker         1 -> 1 (pre-eksisterende, unntatt)
  G3 produkt-forekomster         451 -> 451; `Cosmos DB|Azure Cosmos` 308 = 308
  de 3 kun-produkt-filene        byte-identiske
  nettet validert begge veier    injisert persona feller G1; genitiv feller G1;
                                 produkt-heading og de 3 filene passerer
  hele diffen                    802 heading-linjer + 654 TOC-linjer, ANNET = 0
  linjeantall                    728 lagt til = 728 slettet
  suite                          1120/1120 (1097 + 23 nye)
  validate-plugin                250 PASS / 0 FAIL
  stikkprøve                     10 filer, alle 5 skills, inkl. de 3 mest
                                 produkt-tunge (26/20/19) — kun heading+TOC

Utenfor scope, urørt: de 4 SKILL.md, de 23 commands, CLAUDE.md, README.md,
NOTICE.md, docs/ (alt R14).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 22:12:28 +02:00

18 KiB

Agent Compliance and Audit Trail Management

Last updated: 2026-02 Status: GA Category: Agent Orchestration & Automation Type: reference


Innhold

Introduksjon

Compliance og revisjonsspor for AI-agenter er ikke lenger en "nice-to-have" -- det er et regulatorisk krav under EU AI Act, GDPR, og nasjonale regelverk som den norske Forvaltningsloven. Organisasjoner må dokumentere hva agenter gjør, hvilke data de aksesserer, hvilke beslutninger de tar, og hvordan disse beslutningene kan etterprøves. Uten strukturerte revisjonsspor risikerer virksomheter regulatoriske sanksjoner og tap av tillit.

Microsoft tilbyr en governance-stack for agentcompliance gjennom Microsoft Foundry Control Plane for unified agentsynlighet, Microsoft Purview Compliance Manager for regulatorisk mapping, Microsoft Entra Agent ID for identitets- og tilgangsstyring, Azure Monitor og Log Analytics for sentralisert logging, og Microsoft Agent 365 for enterprise-grade agentovervåking. Disse verktøyene til sammen sikrer at enhver agenthandling kan spores tilbake til en spesifikk brukerforespørsel, gjennom agentens resonnering, til det endelige resultatet.

For norsk offentlig sektor er kravene spesielt strenge: Forvaltningsloven krever dokumentasjon av saksbehandling, Arkivloven krever journalføring, Offentlighetsloven gir innsynsrett, og EU AI Act stiller krav til risikostyring og logging av høyrisiko AI-systemer.

Kjernekomponenter

Komponent Formål Teknologi
Action Audit Logging Logg alle agenthandlinger Azure Monitor, Log Analytics
Decision Trail Dokumentér beslutningskjeden OpenTelemetry traces, custom attributes
Retention Policies Bevar data iht. regelverk Azure Storage lifecycle, Purview
Regulatory Alignment Map kontroller til regelverk Microsoft Purview Compliance Manager
Compliance Reporting Generer compliance-rapporter Azure Monitor Workbooks, Power BI
Agent Identity Spor hvem/hva som handlet Microsoft Entra Agent ID

Action Audit Logging

Comprehensive agent audit log

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
import json

class AgentActionType(Enum):
    QUERY_RECEIVED = "query_received"
    INTENT_CLASSIFIED = "intent_classified"
    AGENT_ROUTED = "agent_routed"
    RAG_RETRIEVAL = "rag_retrieval"
    TOOL_INVOKED = "tool_invoked"
    LLM_CALLED = "llm_called"
    RESPONSE_GENERATED = "response_generated"
    RESPONSE_FILTERED = "response_filtered"
    ERROR_OCCURRED = "error_occurred"
    HUMAN_ESCALATED = "human_escalated"

@dataclass
class AgentAuditEntry:
    timestamp: str = field(
        default_factory=lambda: datetime.utcnow().isoformat()
    )
    trace_id: str = ""
    span_id: str = ""
    session_id: str = ""
    user_id: str = ""
    agent_id: str = ""
    agent_name: str = ""
    action_type: str = ""
    action_details: dict = field(default_factory=dict)
    input_summary: str = ""  # Redacted/summarized
    output_summary: str = ""  # Redacted/summarized
    data_accessed: list = field(default_factory=list)
    tools_used: list = field(default_factory=list)
    model_used: str = ""
    tokens_consumed: int = 0
    duration_ms: float = 0
    success: bool = True
    error_message: str = ""
    compliance_flags: list = field(default_factory=list)

class AgentAuditLogger:
    def __init__(self, log_analytics_client):
        self.client = log_analytics_client

    async def log(self, entry: AgentAuditEntry):
        """Logg audit entry til Azure Log Analytics"""
        await self.client.upload(
            rule_id=os.environ["DCR_IMMUTABLE_ID"],
            stream_name="Custom-AgentAuditLog_CL",
            logs=[{
                "TimeGenerated": entry.timestamp,
                "TraceId": entry.trace_id,
                "SpanId": entry.span_id,
                "SessionId": entry.session_id,
                "UserId": entry.user_id,
                "AgentId": entry.agent_id,
                "AgentName": entry.agent_name,
                "ActionType": entry.action_type,
                "ActionDetails": json.dumps(entry.action_details),
                "InputSummary": entry.input_summary,
                "OutputSummary": entry.output_summary,
                "DataAccessed": json.dumps(entry.data_accessed),
                "ToolsUsed": json.dumps(entry.tools_used),
                "ModelUsed": entry.model_used,
                "TokensConsumed": entry.tokens_consumed,
                "DurationMs": entry.duration_ms,
                "Success": entry.success,
                "ErrorMessage": entry.error_message,
                "ComplianceFlags": json.dumps(entry.compliance_flags)
            }]
        )

Immutable audit log med Azure Storage

# Immutable storage for regulatorisk krav
from azure.storage.blob import BlobServiceClient

class ImmutableAuditStore:
    def __init__(self, connection_string: str, container: str):
        self.client = BlobServiceClient.from_connection_string(
            connection_string
        )
        self.container = self.client.get_container_client(container)
        # Container konfigurert med immutability policy

    async def store_audit_record(self, record: AgentAuditEntry):
        """Lagre audit record i immutable blob storage"""
        blob_name = (
            f"audit/{record.timestamp[:10]}/"
            f"{record.agent_name}/{record.trace_id}.json"
        )
        blob_client = self.container.get_blob_client(blob_name)
        await blob_client.upload_blob(
            json.dumps(record.__dict__),
            overwrite=False  # Immutable -- kan ikke overskrives
        )

Decision Trail Documentation

Komplett beslutningskjede

from opentelemetry import trace

tracer = trace.get_tracer("agent-decision-trail")

async def process_with_full_trail(query: str, user_id: str):
    """Dokumentér komplett beslutningskjede for etterprøvbarhet"""

    with tracer.start_as_current_span("decision_trail") as root:
        root.set_attribute("user.id", user_id)
        root.set_attribute("query.hash", hash(query))  # Ikke full tekst

        # Steg 1: Intent classification
        with tracer.start_as_current_span("classify_intent") as span:
            intent = await classify(query)
            span.set_attribute("decision.type", "intent_classification")
            span.set_attribute("decision.result", intent.label)
            span.set_attribute("decision.confidence", intent.confidence)
            span.set_attribute("decision.reasoning",
                f"Klassifisert som '{intent.label}' basert på "
                f"nøkkelord-matching og semantisk likhet"
            )

        # Steg 2: Agent selection
        with tracer.start_as_current_span("select_agent") as span:
            agent = select_best_agent(intent)
            span.set_attribute("decision.type", "agent_selection")
            span.set_attribute("decision.result", agent.name)
            span.set_attribute("decision.reasoning",
                f"Valgt '{agent.name}' basert på intent '{intent.label}' "
                f"og agent capability score {agent.score}"
            )

        # Steg 3: Data retrieval
        with tracer.start_as_current_span("retrieve_data") as span:
            docs = await retrieve(query, agent)
            span.set_attribute("decision.type", "data_retrieval")
            span.set_attribute("data.sources",
                [d.source for d in docs])
            span.set_attribute("data.doc_count", len(docs))
            span.set_attribute("decision.reasoning",
                f"Hentet {len(docs)} dokumenter fra "
                f"{set(d.source for d in docs)}"
            )

        # Steg 4: Response generation
        with tracer.start_as_current_span("generate_response") as span:
            response = await agent.invoke(query, docs)
            span.set_attribute("decision.type", "response_generation")
            span.set_attribute("model.used", response.model)
            span.set_attribute("tokens.total", response.total_tokens)
            span.set_attribute("decision.reasoning",
                f"Generert svar med {response.model}, "
                f"{response.total_tokens} tokens"
            )

        return response

Retention Policies

Data lifecycle management

Datatype Retensjon Begrunnelse Implementering
Audit logs (sammendrag) 7 år Arkivloven, bokføringsloven Immutable Blob Storage
Full traces med innhold 12 måneder Debugging og forbedring Log Analytics, TTL
Samtalehistorikk 6 måneder Brukeropplevelse Cosmos DB TTL
Evaluerings-data 24 måneder Kvalitetssikring Log Analytics
PII-holdige logger 3 måneder GDPR dataminimering Automatisk sletting
Aggregerte metrikker Ubegrenset Trendanalyse Azure Monitor Metrics

Automatisert retensjon

# Azure Storage lifecycle policy for audit data
lifecycle_policy = {
    "rules": [
        {
            "name": "audit-tier-to-cool",
            "type": "Lifecycle",
            "definition": {
                "actions": {
                    "baseBlob": {
                        "tierToCool": {"daysAfterModificationGreaterThan": 90},
                        "tierToArchive": {"daysAfterModificationGreaterThan": 365},
                        "delete": {"daysAfterModificationGreaterThan": 2555}
                        # 7 år
                    }
                },
                "filters": {
                    "blobTypes": ["blockBlob"],
                    "prefixMatch": ["audit/"]
                }
            }
        },
        {
            "name": "pii-cleanup",
            "type": "Lifecycle",
            "definition": {
                "actions": {
                    "baseBlob": {
                        "delete": {"daysAfterModificationGreaterThan": 90}
                    }
                },
                "filters": {
                    "blobTypes": ["blockBlob"],
                    "prefixMatch": ["pii-logs/"]
                }
            }
        }
    ]
}

Regulatory Alignment

EU AI Act mapping

EU AI Act krav Artikkel Agent-implementering
Risikostyringssystem Art. 9 Trusselmodellering + continuous monitoring
Datakvalitet Art. 10 RAG data quality checks + lineage
Teknisk dokumentasjon Art. 11 Agent manifest + arkitekturdokumentasjon
Journalføring Art. 12 Audit logs med full beslutningskjede
Transparens Art. 13 AI-disclosure i brukergrensesnitt
Menneskelig tilsyn Art. 14 Human-in-the-loop for høyrisiko-beslutninger
Nøyaktighet og robusthet Art. 15 Continuous evaluation + red teaming

Microsoft Purview Compliance Manager

# Integrer agent-compliance med Purview
# Purview Compliance Manager gir:
# 1. Pre-definerte assessment-maler for EU AI Act
# 2. Compliance score tracking over tid
# 3. Improvement actions med prioritering
# 4. Evidence collection og documentation

# Bruk Purview APIs for automatisert compliance-sjekk
from azure.purview.compliance import PurviewComplianceClient

client = PurviewComplianceClient(
    endpoint=os.environ["PURVIEW_ENDPOINT"],
    credential=DefaultAzureCredential()
)

# Sjekk compliance-status for agent-kontroller
assessment = await client.get_assessment(
    template_id="eu-ai-act-high-risk",
    group_id="ai-agents"
)

# Rapportér compliance-gap
for action in assessment.improvement_actions:
    if action.status != "Completed":
        print(f"GAP: {action.title} - {action.category}")

Compliance Reporting

KQL-basert compliance rapport

// Compliance rapport: Alle agenthandlinger siste 30 dager
let audit_summary = AgentAuditLog_CL
| where TimeGenerated > ago(30d)
| summarize
    total_actions = count(),
    unique_users = dcount(UserId),
    unique_agents = dcount(AgentName),
    errors = countif(Success == false),
    human_escalations = countif(ActionType == "human_escalated"),
    pii_access = countif(array_length(
        parse_json(ComplianceFlags)) > 0),
    total_tokens = sum(TokensConsumed),
    avg_response_time = avg(DurationMs)
    by AgentName;

// Detaljerte compliance-flagg
let compliance_flags = AgentAuditLog_CL
| where TimeGenerated > ago(30d)
| where ComplianceFlags != "[]"
| extend flags = parse_json(ComplianceFlags)
| mv-expand flag = flags
| summarize flag_count = count() by tostring(flag), AgentName
| order by flag_count desc;

audit_summary
| join kind=leftouter compliance_flags on AgentName

Power BI compliance dashboard

// Data for Power BI compliance dashboard
AgentAuditLog_CL
| where TimeGenerated > ago(90d)
| extend
    Week = startofweek(TimeGenerated),
    Agent = AgentName,
    Action = ActionType,
    HasPII = array_length(parse_json(ComplianceFlags)) > 0,
    ResponseTime = DurationMs
| summarize
    Actions = count(),
    Errors = countif(Success == false),
    PIIAccess = countif(HasPII),
    AvgResponseMs = avg(ResponseTime),
    P95ResponseMs = percentile(ResponseTime, 95),
    TokensUsed = sum(TokensConsumed)
    by Week, Agent, Action

Norsk offentlig sektor

Spesifikke krav

Regelverk Krav Agent-implementering
Forvaltningsloven §11a Dokumentasjonsplikt for vedtak Komplett beslutningskjede for agenter som bidrar til vedtak
Arkivloven Journalføring av korrespondanse Agent-interaksjoner med borgere journalføres
Offentlighetsloven Innsynsrett i dokumenter Agent-logger tilgjengelig for innsynsbegjæring
GDPR Art. 22 Rett til ikke å bli utsatt for automatiserte beslutninger Human-in-the-loop for agenter som gjør enkeltvedtak
EU AI Act Logging av høyrisiko AI Full audit trail for agenter i saksbehandling
Sikkerhetsloven Beskyttelse av gradert info Isolerte audit logs for sikkerhetsgraderte agenter
Digdir prinsipper Etterprøvbarhet Transparent dokumentasjon av AI-bruk

Implementering for norsk offentlig sektor

# Journalføring av agent-interaksjoner i henhold til arkivloven
class NorwegianPublicSectorCompliance:
    def __init__(self, noark_client, audit_logger):
        self.noark = noark_client  # NOARK 5-kompatibelt system
        self.audit = audit_logger

    async def log_citizen_interaction(
        self,
        interaction: AgentAuditEntry,
        case_number: str = None
    ):
        """Journalfør borgerinteraksjon med agent"""

        # 1. Standard audit logging
        await self.audit.log(interaction)

        # 2. NOARK-journalpost for interaksjoner som
        #    berører saksbehandling
        if interaction.action_type in [
            "response_generated", "tool_invoked"
        ]:
            await self.noark.create_journal_entry(
                title=f"AI-agent interaksjon: {interaction.agent_name}",
                case_number=case_number,
                document_type="U",  # Utgående
                classification="Offentlig",  # Eller gradert
                content_reference=interaction.trace_id,
                metadata={
                    "ai_agent": interaction.agent_name,
                    "model": interaction.model_used,
                    "trace_id": interaction.trace_id,
                    "user_id": interaction.user_id
                }
            )

    async def handle_innsyn_request(
        self, request_period: tuple, agent_name: str = None
    ) -> list:
        """Håndter innsynsbegjæring for agent-logger"""
        query = f"""
        AgentAuditLog_CL
        | where TimeGenerated between (
            datetime('{request_period[0]}') ..
            datetime('{request_period[1]}'))
        """
        if agent_name:
            query += f"| where AgentName == '{agent_name}'"

        # Rediger PII før utlevering
        results = await self.query_logs(query)
        return [self.redact_pii(r) for r in results]

Beslutningsrammeverk

Scenario Anbefaling Begrunnelse
Informasjonsagent (lav risiko) Standard audit logging + 12 mnd retensjon Tilstrekkelig for debugging og kvalitet
Saksbehandlingsagent Full beslutningskjede + NOARK-integrasjon + 7 år Regulatorisk krav
Borgerrettet agent Audit + GDPR-compliance + innsynsstøtte Offentlighetsloven + GDPR
Sensitiv data-agent Immutable storage + strengere access control Personvern og sikkerhet
Multi-agent system Distribuert tracing + sentralisert audit Etterprøvbarhet på tvers av agenter

For arkitekten

  • Audit logging er ikke valgfritt -- det er et regulatorisk krav under EU AI Act Art. 12 og norsk forvaltningsrett. Implementer fra dag 1, ikke som etterpåklok.
  • Beslutningskjeden er det viktigste -- logg ikke bare hva agenten svarte, men HVORFOR: hvilken intent ble klassifisert, hvilken agent ble valgt, hvilke data ble hentet, hvilken modell ble brukt.
  • Retensjonspolicies må differensieres -- PII-holdige logger slettes etter 3 måneder (GDPR), men audit-sammendrag bevares i 7 år (Arkivloven). Automatisér med Azure Storage lifecycle policies.
  • For norsk offentlig sektor: Integrer agent-logging med NOARK 5 for journalføring, implementer innsynsstøtte for Offentlighetsloven, og sørg for human-in-the-loop for GDPR Art. 22.
  • Microsoft Purview Compliance Manager er verktøyet for å spore EU AI Act-compliance -- bruk pre-definerte assessment-maler og automatisér evidence collection.