watsonx.governance Enforcement Tracking — Sampled Compliance and the Unevidenced Run
By Vladimir Mikhalev · Solutions Architect · Docker Captain · IBM ChampionSixteen months. That is how far Regulation (EU) 2026/1744 moved the AI Act’s high-risk deadline when it entered into force on 27 July 2026, pushing standalone Annex III obligations from 2 August 2026 out to 2 December 2027. The deferral moved the deadline. It did not move the record, and sampled compliance is the shape of what is left: governance evidence collected in windows, agent behavior that runs without one. I reviewed the configuration and the evidence model for IBM watsonx.governance Enforcement Tracking, which shipped on 11 August 2026, against the question an auditor actually asks.
This failure shape is older than agents. In banking it was hourly configuration snapshots, and the snapshot became the definition of what the configuration was, because nothing between snapshots existed on paper. In telecom it was a five-minute polling interval on the network management system, and every incident timeline quietly rounded to five minutes. The interval always wins. When the interval is the only record, the interval becomes the truth, and everything between two samples becomes testimony instead of artifact. I wrote about the same gap on the infrastructure side in the Apply Gate your auditor will ask about.
What sampled compliance looks like in a running agent
Here is how most teams ship a containerized agent today.
# kubernetes 1.30 — claims-triage agent as most teams ship itapiVersion: apps/v1kind: Deploymentmetadata: name: claims-triage-agentspec: replicas: 3 selector: matchLabels: app: claims-triage-agent template: metadata: labels: app: claims-triage-agent spec: containers: - name: agent image: registry.internal/claims-triage-agent:1.4.2 env: - name: ORCHESTRATE_ENDPOINT valueFrom: secretKeyRef: name: wxo-credentials key: endpointNothing on that manifest connects a single execution to a governance record. The agent runs, it writes to stdout, and the only durable statement about its behavior is whatever the evaluation schedule captured. Ask for run 4192 and you get a shrug and a log query against whatever retention the cluster happens to have.
The change is small and it is structural.
# kubernetes 1.30 — same agent, every execution addressableapiVersion: apps/v1kind: Deploymentmetadata: name: claims-triage-agent labels: ai.use-case-id: uc-claims-triage-eu ai.policy-version: "2026.08.1"spec: replicas: 3 selector: matchLabels: app: claims-triage-agent template: metadata: labels: app: claims-triage-agent ai.use-case-id: uc-claims-triage-eu ai.policy-version: "2026.08.1" spec: containers: - name: agent image: registry.internal/claims-triage-agent:1.4.2 env: - name: ORCHESTRATE_ENDPOINT valueFrom: secretKeyRef: name: wxo-credentials key: endpoint - name: OTEL_EXPORTER_OTLP_ENDPOINT value: http://otel-collector.observability:4317 - name: OTEL_RESOURCE_ATTRIBUTES value: ai.use_case.id=uc-claims-triage-eu,ai.policy.version=2026.08.1Two additions. The workload now carries the same use-case identifier the governance system uses, and every execution emits a span under that identifier with the policy version that was live at the time. You are not storing prompts or outputs. You are storing the fact that a run occurred, under which policy, touching which tools. That is the join key, and without it the two systems can never be reconciled at all.
Twenty years of production infrastructure and this pattern has arrived in three different decades of stack: snapshot intervals in banking, SNMP polling in telecom, and a change-management record sampling a pipeline that fired hundreds of times a day in a Series D environment. Each time the fix was the same and each time it looked like overhead until the first audit.
The interval is the record. Everything between two samples is a story.
Why this keeps happening
The regulation asks for two different things and vendors ship the easier one first, because it is the one with a clean product surface.
Article 12 of the AI Act requires high-risk systems to automatically record events across the lifetime of the system, with three stated purposes: identifying risk situations under Article 79, feeding post-market monitoring under Article 72, and supporting deployer oversight under Article 26, paragraph 5. Article 19 sets the retention floor for providers at six months, longer where other Union or national law applies, and Article 26, paragraph 6 places a parallel six-month duty on deployers for the logs under their control. Article 18 puts technical documentation on a ten-year clock. None of those clauses describes a threshold check. They describe a per-event record with a retention obligation attached.
Enforcement Tracking, per IBM’s announcement of 11 August 2026, connects watsonx Orchestrate to watsonx.governance, associates agents with governance use cases and controls, retrieves evaluation metrics on a scheduled basis for production agents, evaluates agents still in development on demand, and writes pass or breach results against business-set thresholds directly into the governance record. Hallucination, helpfulness and toxicity are the named metrics. That is a control attestation pipeline, automated, and it removes the quarterly scramble of assembling evidence by hand.
The second thing is harder to productize because it is specific to your deployment. A vendor cannot know your correlation identifier, your policy versioning scheme, or which of your systems holds the execution ledger. So it stays where it has always stayed. The vendor shipped the evidence pipeline. The join key is still yours.
Risk and blast radius
Direct exposure runs through retention and traceability rather than through the metrics themselves. If your agent falls inside Annex III, the Article 12 record has to exist and the Article 19 and Article 26, paragraph 6 floors mean six months of it has to still be there when someone asks. A threshold snapshot taken on a schedule does not satisfy a per-event recording obligation, and no amount of dashboard polish converts one into the other. Penalty tiers under the Act put transparency and high-risk breaches at up to 15 million euro or 3% of worldwide turnover, with prohibited practices at 35 million euro or 7%.
Read what the deferral actually deferred, because the headline flattens it. Annex III systems moved to 2 December 2027 and high-risk AI embedded in already-regulated products under Annex I moved to 2 August 2028. Article 50 transparency duties did not move at all; they took effect on 2 August 2026 as originally scheduled, alongside the prohibited-practices regime that has applied since February 2025 and the GPAI obligations running since August 2025. The Omnibus attached one new near-term date to them: systems already on the market before 2 August 2026 have until 2 December 2026 to carry machine-readable marking of AI-generated content. Sixteen months of relief on Annex III. Fourteen weeks on the marking obligation. And the stated reason for the delay was procedural rather than political: the CEN and CENELEC harmonised standards were not finished and several Member States had not designated their competent authorities. A deadline that moved because the referee was late is not a signal that the rules got softer.
Systemic exposure is the part the deferral headline hides. Systems already placed on the EU market before the new deadlines are grandfathered out of full high-risk compliance unless they are later substantially modified, and regulators have not yet defined that threshold. For an agent that reasons over changing context, calls tools dynamically, and gets its prompts and models updated on a normal release cadence, “substantially modified” is not a rhetorical question. It is an evidentiary one, and answering it requires a change record joined to an execution record. Sampling cannot produce that answer in either direction.
Before assuming Article 26, paragraph 6 is your ceiling, check which side of Article 25 you are standing on. A deployer who puts their own name or trademark on a high-risk system, or substantially modifies one already placed on the market, is treated as its provider. Assemble agents on a vendor platform, ship them under your own brand, and the provider obligations follow: the Article 12 recording capability and the Article 19 retention floor, not merely the deployer’s duty to keep whatever the platform hands you. The original provider is relieved of them at that moment and owes you cooperation instead. The platform did not transfer the obligation. It transferred the role.
Then the arithmetic. An agent invoked every five minutes executes 288 times a day, or 8,640 times over thirty days. Against a daily metrics synchronisation, that month closes with 30 evidence records covering 8,640 executions, or 0.35% of runs individually evidenced. Tighten the schedule to hourly and you get 720 records against 8,640 runs, which is 8.3%. The schedule is the right design for attesting a control. It is the wrong artifact for reconstructing an incident.
A deferral you cannot document is not a deferral.
Options compared
Storage figures below are back-of-envelope from stated unit sizes, not measured: trace metadata at about 1.5 KB per span, full payload capture at about 1 MB per run average for a tool-calling agent, hash digest at about 150 bytes.
| Approach | Evidence granularity | Storage per 1M runs | Question it answers at audit | Fit |
|---|---|---|---|---|
| Scheduled enforcement tracking (watsonx.governance) | One record per evaluation window | Under 10 MB | Were thresholds met at time T | Control attestation. Required baseline, not the event record |
| Per-execution trace metadata (OpenTelemetry) | One span per run, no payload | ~1.5 GB | Did run X occur, when, under which policy, touching which tools | The reconciliation layer. Cheapest path to Article 12 traceability |
| Full request and response archival | Every prompt and output | ~1 TB | What exactly did the agent say and do | Highest fidelity, highest GDPR and cost exposure |
| Sampled payload capture (1% plus all breaches) | Statistical, full on breach | ~15 GB | What does a normal run look like, plus every bad one in full | Pragmatic middle for non-regulated estates |
| Hash-chained execution digest | One signed digest per run | ~150 MB | Has the record been altered since it was written | Tamper-evidence for regulated or contested estates |
Most teams need rows one and two together. Row one without row two is a control with no event behind it.
Framework: reconciling the execution ledger with the evidence ledger
Layer 1: use-case binding and execution inventory (week 1)
Start inside watsonx.governance, because that is where the identifier everything else joins to gets defined. Connect the watsonx Orchestrate instance, associate each agent with the AI use case and the controls it has to satisfy, and set the thresholds the business is prepared to defend in front of an auditor.
Two options in that configuration change what the control is worth, and both are easy to leave on their defaults. Agents still in development can be evaluated on demand before they ship, which moves a threshold breach from the first production window back to build time. And a metric that crosses its limit can drive an automated workflow rather than only writing a result into the record. Turn both on. A control that pages someone beats a control that files something.
That is the attestation half, and it is the half a vendor can ship for you. The other half is the identifier itself. Most organizations cannot yet say how many agents are running at all, which is the prerequisite problem behind Agent Sprawl. Give every run an identity carrying the same use-case id watsonx.governance now knows it by: one span per execution, three attributes that matter, no payload.
# opentelemetry-sdk 1.x — one span per agent execution, carrying the governance join keyfrom opentelemetry import trace
tracer = trace.get_tracer("wxo.agent.claims_triage")
def run_agent(request, ai_use_case_id: str, policy_version: str): with tracer.start_as_current_span("agent.execution") as span: span.set_attribute("ai.use_case.id", ai_use_case_id) span.set_attribute("ai.policy.version", policy_version) span.set_attribute("ai.agent.id", "claims-triage") result = agent.invoke(request) span.set_attribute("ai.tools.invoked", ",".join(result.tool_calls)) span.set_attribute("ai.outcome", result.status) return resultShip spans to an OpenTelemetry Collector and land them in a store you control, with retention set to your longest applicable obligation rather than your default. Six months is the AI Act floor. Financial services deployers answer to their own regime under Article 26, paragraph 6, measured in years. Set it at your ceiling now. Raising retention later does not recover what already aged out.
Owner: AI governance lead for the watsonx.governance binding, platform engineer for the spans.
Layer 2: policy binding (week 2)
The join key belongs in infrastructure, not in a runbook. Terraform tags the agent’s execution role with the same use-case identifier the governance system uses, and a permissions boundary states the blast radius as code.
# terraform 1.x, aws provider 5.x — bound the agent's execution role, carry the governance join keyresource "aws_iam_role" "agent_execution" { name = "wxo-agent-claims-triage" permissions_boundary = aws_iam_policy.agent_boundary.arn assume_role_policy = data.aws_iam_policy_document.agent_trust.json
tags = { ai_use_case_id = var.ai_use_case_id # same key on every span and every evidence record policy_version = var.policy_version }}
resource "aws_iam_policy" "agent_boundary" { name = "wxo-agent-boundary" policy = data.aws_iam_policy_document.agent_boundary.json}
data "aws_iam_policy_document" "agent_trust" { statement { effect = "Allow" actions = ["sts:AssumeRoleWithWebIdentity"]
principals { type = "Federated" identifiers = [var.oidc_provider_arn] }
condition { test = "StringEquals" variable = "${var.oidc_provider_host}:sub" values = ["system:serviceaccount:default:claims-triage-agent"] } }}
variable "ai_use_case_id" { type = string }variable "policy_version" { type = string }variable "oidc_provider_arn" { type = string }variable "oidc_provider_host" { type = string }
data "aws_iam_policy_document" "agent_boundary" { statement { effect = "Allow" actions = ["s3:GetObject"] resources = ["arn:aws:s3:::claims-reference/*"] }
statement { effect = "Deny" actions = ["iam:*", "sts:AssumeRole"] resources = ["*"] }}If the estate runs HCP Terraform or Terraform Enterprise, gate the plan before the apply. Sentinel reads the plan directly, so a role provisioned without the governance tag never reaches state.
# sentinel policy — refuse a plan that provisions an agent role with no governance use caseimport "tfplan/v2" as tfplan
required_tag = "ai_use_case_id"
agent_roles = filter tfplan.resource_changes as _, rc { rc.type is "aws_iam_role" and rc.mode is "managed" and (rc.change.actions contains "create" or rc.change.actions contains "update")}
main = rule { all agent_roles as _, rc { rc.change.after.tags[required_tag] else "" is not "" }}That catches the resource at provision time. The second gate catches the workload at admission time, because a correctly tagged role says nothing about whether the pod that assumes it emits anything.
# opa 1.x / conftest — block agent deploys that cannot be joined to a governance use casepackage agent.evidence
deny contains msg if { input.kind == "Deployment" not input.metadata.labels["ai.use-case-id"] msg := "missing ai.use-case-id label: runs cannot be joined to governance evidence"}
deny contains msg if { input.kind == "Deployment" some c in input.spec.template.spec.containers not otlp_configured(c) msg := sprintf("container %q has no OTEL_EXPORTER_OTLP_ENDPOINT: executions will not be recorded", [c.name])}
otlp_configured(c) if { some e in c.env e.name == "OTEL_EXPORTER_OTLP_ENDPOINT"}Owner: security engineer.
Layer 3: reconciled audit (week 3 onward)
Two ledgers, one key, one number that tells you whether the record has holes in it.
# prometheus 2.x — alert when agent runs have no matching governance evidence recordgroups: - name: agent-evidence-coverage interval: 5m rules: - record: agent:runs_unevidenced:ratio1h expr: | 1 - ( sum by (ai_use_case_id) (increase(agent_runs_evidenced_total[1h])) / clamp_min(sum by (ai_use_case_id) (increase(agent_runs_total[1h])), 1) )
- alert: AgentEvidenceCoverageBelowFloor expr: agent:runs_unevidenced:ratio1h > 0.05 for: 15m labels: severity: page control: eu-ai-act-art-12 annotations: summary: Agent runs without a matching governance evidence record description: > {{ $value | humanizePercentage }} of runs for use case {{ $labels.ai_use_case_id }} have no evidence record in the last hour.The alert does not say the agent misbehaved. It says the record has a hole in it, which is the failure you cannot fix retroactively. Put the same ratio on a Grafana panel beside your evaluation metrics, so the governance lead reads both in one frame. Quality tells you how the agent behaved. Coverage tells you whether you can prove it.
Owner: SRE, with the AI governance lead setting the floor.
Tradeoffs
Adoption friction is real and it is mostly week one. Instrumenting spans across every agent path takes a sprint, the OTLP collector and its retention tier need a budget line, and someone has to own a versioning scheme for policies that was previously implicit. At roughly 1.5 KB per span you are looking at about 1.5 GB per million executions before compression, which is a rounding error next to any observability bill you already pay.
Ignoring it costs asymmetrically. The evidence you did not collect cannot be reconstructed after the request arrives, and the request arrives at the worst possible moment: a complaint, an incident, a due-diligence questionnaire, a market surveillance authority asking under Article 26, paragraph 6. The sixteen-month deferral makes this feel optional. It is the opposite. Sixteen months is exactly how long you now have to accumulate the record that proves your system was not substantially modified.
The closing argument
Adopt Enforcement Tracking for what it is. It automates the control attestation, it writes pass and breach evidence without a human assembling screenshots, and for teams currently maintaining governance evidence by hand it removes real work on day one. Hold on treating it as the audit trail, because a threshold snapshot and a per-event record are different artifacts with different retention clocks. The gap is not a defect in the release; it is the part that was always going to be specific to your deployment, and the join key was always going to be yours to define. The storage is cheap. The reconstruction is not.
Sources
- IBM, From governance policies to governance proof with Enforcement Tracking for watsonx Orchestrate, August 11, 2026
- IBM Documentation, Configuring metrics synchronization for watsonx Orchestrate agents (evaluation schedule, threshold evidence), accessed August 2026
- Official Journal of the European Union, Regulation (EU) 2026/1744 (Digital Omnibus on AI), published July 24, 2026, in force July 27, 2026
- European Commission AI Act Service Desk, Article 19: Automatically generated logs (six-month retention floor), accessed August 2026
- White & Case, EU AI Omnibus enters into force, amending the AI Act (Annex III and Annex I deadlines, Article 50 unchanged), 2026
- Cooley, Digital AI Omnibus Delays Key Deadlines, Introduces New Rules (2 December 2026 marking deadline, Annex I and public-authority dates), 2026
- Gibson Dunn, EU AI Act Omnibus Agreement: Postponed High-Risk Deadlines and Other Key Changes (CEN/CENELEC standards, authority designation), May 2026
Discussion
If you have wired agent executions to a governance record, or you have decided the sampled attestation is enough for your risk profile, drop a comment on the post. Counterarguments are welcome and the comment thread is where I respond first. For longer back-and-forth with senior practitioners, join the discussion on Discord.