Dashboard for monitoring autonomous AI agents with audit trail and kill switch

    AI Agent Ops: How to Monitor, Audit, and Control Agents in Production

    18. März 20267 min read
    Till Freitag

    TL;DR:An agent in production needs three things: Observability (what is it doing?), Audit (what has it done?), and Control (how do I stop it?). Here's the operational playbook."

    Till Freitag

    In 30 Seconds

    Governance defines the rules. But rules without enforcement are worthless. This article covers the operational side: how to monitor agents in production, make every decision traceable, and intervene within seconds when needed.

    The Problem: Agents Are Not APIs

    An API is deterministic: same input, same output. An agent is non-deterministic: it decides which tools to call, in what order, and with what parameters. That makes traditional monitoring useless.

    APIAgent
    BehaviorDeterministicNon-deterministic
    Call chainKnownDynamic
    Failure modeException → RetryBad decision → Side effects
    MonitoringStatus code + latencyReasoning trace + tool calls + outcome

    What we need: a monitoring stack that captures not just whether something happened, but why it happened.

    The Three Pillars of Agent Ops

    1. Observability: What Is the Agent Doing Right Now?

    Observability for agents goes beyond metrics. You need the complete reasoning trace:

    @dataclass
    class AgentTrace:
        trace_id: str
        timestamp: datetime
        input_hash: str          # Never log plaintext
        reasoning_steps: list[ReasoningStep]
        tool_calls: list[ToolCall]
        model_used: str
        routing_decision: str    # local / cloud
        total_tokens: int
        total_latency_ms: float
        outcome: str             # success / error / timeout / killed
    
    @dataclass
    class ToolCall:
        tool_name: str
        input_hash: str
        output_hash: str
        sandbox_type: str        # container / wasm / kernel
        latency_ms: float
        status: str              # success / error / timeout
        side_effects: list[str]  # ["db_write", "email_sent", ...]

    Critical: Every tool call must declare its side effects. That's the only way to reconstruct what the agent actually changed after the fact.

    Dashboards That Matter

    Forget vanity metrics. These four metrics define whether an agent is viable in production:

    MetricWhat It ShowsThreshold
    Tool-Call Rejection RateHow often is a tool call rejected by policy?>5% → Policy too strict or agent hallucinating
    Privacy Route RatioShare of queries on the local pathIndustry-dependent, but trackable
    Reasoning DepthAverage steps to reach an answer>10 → Agent might be stuck in loops
    Side Effect RateHow often does the agent trigger write actions?Every write action needs an audit entry

    2. Audit: What Has the Agent Done?

    Audit is not the same as logging. Logging is for developers, audit is for compliance. The difference:

    LoggingAudit
    AudienceDevelopersCompliance, management, regulators
    ContentTechnical detailsDecisions and their rationale
    RetentionDays to weeksYears (GDPR: up to 10 years)
    ImmutabilityNice-to-haveRequired
    FormatFreeformStructured, machine-readable

    Audit Trail Architecture

    class AuditTrail:
        def __init__(self, storage: AuditStorage):
            self.storage = storage
        
        def record(self, event: AuditEvent):
            """Append-only. No update, no delete."""
            signed_event = self._sign(event)
            self.storage.append(signed_event)
        
        def _sign(self, event: AuditEvent) -> SignedAuditEvent:
            """Cryptographic signature for immutability."""
            previous_hash = self.storage.get_last_hash()
            event_hash = hash_chain(previous_hash, event)
            return SignedAuditEvent(
                event=event,
                hash=event_hash,
                previous_hash=previous_hash,
            )
    
    @dataclass
    class AuditEvent:
        timestamp: datetime
        agent_id: str
        action_type: str        # "tool_call" | "routing" | "escalation"
        decision: str           # What was decided?
        policy_basis: str       # Which policy drove the decision?
        data_classification: str  # sensitive | non_sensitive
        model_path: str         # local | cloud
        outcome: str
        human_override: bool    # Was there manual intervention?

    Hash chain: Each audit entry references the hash of the previous entry. Tampering with a single entry breaks the chain – comparable to a mini-blockchain for agent decisions.

    What Must Be Audited?

    Not everything. But at minimum:

    1. Every routing decision – Which model was chosen and why?
    2. Every write tool call – DB writes, emails, API calls with side effects
    3. Every escalation – When did the agent hand off to a human?
    4. Every policy violation – Including blocked attempts
    5. Every manual intervention – Kill switch, override, config change

    3. Control: How Do I Stop the Agent?

    This is the part most people forget. Starting an agent is easy. Stopping it in a controlled manner is the real challenge.

    Kill Switch Hierarchy

    Level 0: Soft Stop
      → Agent finishes current task, accepts no new ones
      → Graceful shutdown
    
    Level 1: Immediate Stop
      → Running tool calls are aborted
      → Pending side effects are rolled back (where possible)
      → Agent enters quarantine mode
    
    Level 2: Emergency Kill
      → Process terminated immediately
      → All containers stopped
      → Network access revoked
      → Incident created

    Implementation

    class AgentController:
        def __init__(self, agent_id: str):
            self.agent_id = agent_id
            self.state = AgentState.RUNNING
        
        async def soft_stop(self, reason: str):
            """Level 0: Agent finishes current task."""
            self.state = AgentState.DRAINING
            await self._notify_agent("stop_accepting")
            await self._wait_for_current_task(timeout=60)
            self.state = AgentState.STOPPED
            self._audit("soft_stop", reason)
        
        async def immediate_stop(self, reason: str):
            """Level 1: Immediate stop with rollback."""
            self.state = AgentState.STOPPING
            await self._cancel_running_tools()
            await self._rollback_pending_effects()
            self.state = AgentState.QUARANTINED
            self._audit("immediate_stop", reason)
        
        async def emergency_kill(self, reason: str):
            """Level 2: Emergency abort."""
            self.state = AgentState.KILLED
            await self._kill_process()
            await self._stop_all_containers()
            await self._revoke_network()
            self._create_incident(severity="critical", reason=reason)
            self._audit("emergency_kill", reason)

    Automatic Triggers

    Kill switches should not only be manually triggerable:

    AUTO_KILL_TRIGGERS = [
        # Agent stuck in a loop
        Trigger(
            condition="reasoning_steps > 20 in single task",
            action="soft_stop",
            reason="Possible reasoning loop detected",
        ),
        # Too many write actions in a short time
        Trigger(
            condition="side_effects > 10 in 60 seconds",
            action="immediate_stop",
            reason="Abnormal side effect rate",
        ),
        # Attempt to send sensitive data to cloud
        Trigger(
            condition="privacy_violation_attempt",
            action="emergency_kill",
            reason="Privacy policy violation",
        ),
        # Unknown tool call
        Trigger(
            condition="tool_call not in allowed_tools",
            action="immediate_stop",
            reason="Unauthorized tool call attempted",
        ),
    ]

    Human-in-the-Loop: Where Humans Must Intervene

    Not every decision needs a human. But some do:

    Agent Decision
      └── Is it a write action?
           ├── No  Automatic
           └── Yes
                └── Does it involve sensitive data?
                     ├── No  Automatic with audit
                     └── Yes  Human approval required
                          └── Is it reversible?
                               ├── Yes  Approval by 1 person
                               └── No  Approval by 2 people (four-eyes)

    Approval Gates

    class ApprovalGate:
        def __init__(self, required_approvers: int = 1):
            self.required = required_approvers
        
        async def request_approval(
            self,
            action: str,
            context: dict,
            timeout_minutes: int = 30,
        ) -> ApprovalResult:
            ticket = await self._create_approval_ticket(action, context)
            
            # Wait for approval or timeout
            result = await self._wait_for_approvals(
                ticket, 
                required=self.required,
                timeout=timeout_minutes * 60,
            )
            
            if result.timed_out:
                return ApprovalResult.DENIED  # Timeout = denial
            
            return result

    Important: Timeout always means denial. An agent waiting for approval that never comes is just as dangerous as one without approval.

    Alerting: The Right Signals

    Too many alerts are as bad as none. The art is alerting only on real problems:

    Alert LevelTriggerAction
    InfoAgent completed task with unusually many stepsDashboard entry
    WarningPrivacy route ratio deviates >20% from averageSlack notification to agent owner
    ErrorTool call failed after 3 retriesPagerDuty to on-call
    CriticalPrivacy violation attempt or kill switch triggeredPagerDuty + Incident + Agent stopped

    The Complete Stack

    ┌─────────────────────────────────────────────┐
    │                  Alerting                    │
    │  (PagerDuty / Slack / monday.com Incidents) │
    ├─────────────────────────────────────────────┤
    │               Control Plane                  │
    │   Kill Switches │ Approval Gates │ Policies │
    ├─────────────────────────────────────────────┤
    │              Audit Trail                     │
    │   Hash Chain │ Compliance Reports │ Retention│
    ├─────────────────────────────────────────────┤
    │             Observability                    │
    │   Traces │ Metrics │ Dashboards │ Logs      │
    ├─────────────────────────────────────────────┤
    │              Agent Runtime                   │
    │   Privacy Router │ Sandbox │ Tool Execution  │
    └─────────────────────────────────────────────┘

    Integration with Existing Tools

    Agent Ops doesn't need to be built from scratch. Existing tools can be adapted:

    FunctionToolAdaptation
    TracesOpenTelemetryCustom spans for reasoning steps
    MetricsPrometheus / GrafanaAgent-specific metrics
    AuditAppend-only DB (e.g., EventStore)Schema for agent events
    AlertsPagerDuty / OpsGenieAgent-specific severity rules
    Incidentsmonday.com ServiceAutomatic ticket creation
    ApprovalSlack / monday.comApproval workflows

    Checklist: Agent Production Readiness

    Before an agent goes to production, these points must be met:

    • Observability: Complete reasoning trace is captured
    • Audit trail: Append-only, signed, with hash chain
    • Kill switch: All three levels implemented and tested
    • Automatic triggers: Loop detection, rate limiting, policy enforcement
    • Human-in-the-loop: Approval gates for sensitive write actions
    • Alerting: Graduated (Info → Warning → Error → Critical)
    • Privacy routing: Sensitive data stays local (Privacy Router)
    • Sandboxing: Tool calls isolated (Container/WASM/Kernel)
    • Rollback plan: How is a faulty agent run reversed?
    • Incident playbook: Who gets notified when and what happens next?

    Conclusion

    Building an agent is the easy part. Running it in production – securely, auditably, controllably – is the real work. The three pillars of Observability, Audit, and Control are not optional. They're the prerequisite for deploying autonomous agents in any enterprise.

    Three takeaways:

    1. Observability ≠ Logging – You need the complete reasoning trace, not just status codes and latency
    2. Audit trails must be immutable – Hash chain, cryptographically signed, append-only
    3. Kill switches need three levels – Graceful, Immediate, Emergency – with automatic triggers

    Autonomous AI Agents: Governance FrameworkBuilding a Privacy Router with OpenClawAgent Sandboxing: Containers vs. WASM vs. KernelThe 5 Building Blocks of an AI AgentGet in touch

    TeilenLinkedInWhatsAppE-Mail

    Related Articles

    Field journal with handwritten notes about OpenClaw, a red lobster figurine beside it under warm desk light
    June 29, 20264 min

    Half a Year of OpenClaw in Production – A Field Report from the Engine Room

    Six months of OpenClaw in production, every day. No marketing, no audit – an honest field report: what we ripped out, wh

    Read more
    Field journal with handwritten OpenClaw notes next to a red lobster figurine under warm desk light
    June 29, 20264 min

    Half a Year of OpenClaw in Production – A Field Report from the Engine Room

    Six months of OpenClaw in production, every day. No marketing, no audit – an honest field report: what we ripped out, wh

    Read more
    Minimalist illustration of a developer with a ponytail and oval glasses skeptically reviewing code on a screen
    June 14, 20265 min

    Ponytail: The Best Code Is the Code You Never Wrote

    A dev built Ponytail because his AI agents wrote 500 lines for a 5-line problem. The result: 80-94% less code, 47-77% ch

    Read more
    Enterprise AI agents connecting securely through the Gemini Enterprise Agent Marketplace
    May 28, 20263 min

    Google's Agent Marketplace Goes Live – And monday.com Is Already Inside

    Google just opened Gemini Enterprise to partner-built AI agents – and monday.com is one of the first in. What that means

    Read more
    Pipeline schematic of a Dark Software Factory: a JIRA ticket in status \"Ready for Dev\" triggers parallel Claude Code sub-agents that produce a draft GitHub pull request, with a human review gate before merge
    April 30, 20266 min

    AI Agentic First at Groupon: What Ales Drabek's Dark Software Factory Teaches Us

    Ales Drabek, CTIO at Groupon, runs two patterns in production: Dark Software Factory and Speedboats. What that reveals a

    Read more
    Architecture diagram: central orchestrator agent connecting three specialised sub-agents (Sales, CRM, Ops) via TOOLS.md interfaces to operational enterprise systems
    April 30, 20267 min

    Enterprise-Grade Agentic Setup: Why an API Key Is Not an AI Strategy

    An API key on your website is child's play. An agentic setup with specialised sub-agents, TOOLS.md, clean system prompts

    Read more
    Personal AI agent as central hub, connected to mail, calendar, chat and code – sitting on a secure runtime layer
    April 23, 20265 min

    Globster: monday.com Enters the Personal AI Agent Game – on NVIDIA's NemoClaw

    monday agent labs just launched Globster: personal AI agents built on OpenClaw, secured by NVIDIA's NemoClaw runtime. Wh

    Read more
    Futuristic marketplace for AI agents – Agentalent.ai by monday.com
    March 24, 20263 min

    Agentalent.ai: monday.com Launches the First Marketplace for Hiring AI Agents

    monday.com launches Agentalent.ai – a marketplace where companies can 'hire' AI agents for real business roles. Here's w

    Read more
    Three isolation layers for AI agents: containers, WASM, and kernel-level
    March 17, 20265 min

    Agent Sandboxing: Containers vs. WASM vs. Kernel – Three Ways to Contain AI Agents

    AI agents need isolation. But which kind? Containers, WASM, or kernel-level – three approaches compared with concrete tr

    Read more