DEV Community

Cover image for What should trigger an autonomous agent in production?
Ben Yemini for Causely

Posted on Originally published at causely.ai

What should trigger an autonomous agent in production?

Originally posted to causely.ai by Ben Yemini

TL;DR

Trigger an autonomous agent on a diagnosis. Anthropic's AI-native SDLC playbook closes the loop by using a deterministic script to monitor production and start a Claude session when a control band is breached. That works, but it also means the agent spends its first and most expensive phase working out what broke. A trigger that sets off a causal chain carries it further along.

Anthropic published The AI-Native SDLC Playbook last month. It walks through six stages, from plan through maintain, and describes what each one looks like when agents do the work, and people stay accountable for the decisions. Most of the attention (and value delivered) by large language models so far has gone to Build. But Stage six, Maintain, is the more interesting one, and it’s the one that turns the line into a loop. It is also the one worth reading closely if you run production.

In our last post, we set up Claude managed agents against a local Kubernetes cluster, gave them Grafana and Causely MCP tools, and worked through the authentication pattern for each. This post is about the trigger because it sets up the agent for everything it does afterward.

Stage six

Stage six closes the loop with a script that monitors production and invokes Claude when a metric falls outside its expected range. The playbook picks one metric with a rolling baseline, applies Western Electric rules so that slow drift registers alongside spikes, and selects the next step based on how far the metric strays. At 1σ, the script logs. At 2σ, Claude is invoked read-only to diagnose. At 3σ, Claude may act only by opening a PR into the review gate or by triggering a pre-approved runbook. I hope I have not lost those of you who dislike statistics.

The agent writes what it finds as an intent.md in the Stage one format, and the finding re-enters the pipeline like any other piece of work. Nobody starts it.

The detection half stays out of the model's hands. Louis Claxton, writing for Anthropic, is direct about it:

"detection stays entirely deterministic, with no model involved."

That constraint is the right one. A trigger that fired because a language model felt uneasy is not a trigger you can audit, tune, or explain to a change board.

A band breach carries one fact

A band breach tells you that a metric left its range. The affected entity, which symptoms are consequences of which, and how far the problem reaches, all must be reconstructed before the agent can decide anything. That reconstruction is the job for the diagnosis.

The other challenge with this approach is that each band watches a single metric, so you need a detection script for every failure mode you anticipate. In a cluster of dependent services, degradation spreads across many entities at once and often breaches nothing decisively on any single one. Every service looks slightly worse than usual. No script fires, and the loop never starts.

A diagnosis carries the causal chain behind it

A Causely Issue names the affected entity, designates a primary diagnosis, and exposes the chain of evidence behind it. The agent opens by explaining what could explain the symptom and why, rather than deriving that from the raw cluster state.

Causely computes this from the instrumentation you already run. The causal model encodes, ahead of time, which root causes each type of entity can have and which observable signals each one produces, on that entity and on the entities that depend on it. Faulty error handling on an RPC method, a slow consumer on a topic, a saturated connection pool on a database client: each has a known signature. A slow consumer shows up as growing queue depth on the topic and rising latency on whatever is waiting for the result. Faulty error handling shows up as a high error rate on that method and on every service that calls it.

At runtime, metrics, alerts, and events are mapped to entities and become observed signals. The model then asks, for the set of currently active signals, which diagnosis best explains them. Because the signatures are encoded in advance, this is a lookup against the model, not a search through raw telemetry. What arrives in the Issue is that diagnosis and the chain of observed signals that supports it, not a shorter list of alerts.

This inference is deterministic. The same signals on the same topology produce the same diagnosis. That matters for Stage six: the causal layer can sit on the detection side of the playbook's line without breaking the rule that no model participates in detection.

Here is an example: a Causely Issue becomes a pull request with nobody in the loop

Causely posts an Issue notification to a webhook receiver you host. The receiver turns it into the agent's first message and starts a session. The receiver is a small FastAPI app in our example repository. The Managed Agents API has no inbound webhook of its own.

Here is one session end-to-end. Payments are failing in a cluster: checkout returns errors, billing logs timeouts, and the frontend is slow. Nobody has been paged.

18:14:03. Causely raises an Issue on payment-adapter, severity Critical: calls to external-payment-api:8115 are timing out and being canceled. The receiver forwards it. The agent's first message carries the affected entity, the diagnosis, the evidence, and the Issue id, with an instruction to call get_issue_details before anything else.

18:14:05. The agent makes that call. Causely returns the causal chain. The external payment API is slow to accept charges. Payment-adapter holds the caller's request open while it waits. Checkout's 5s client timeout fires and cancels the whole chain, so the errors land three hops from the cause: 796 canceled calls on payment-adapter, 500 failed calls from billing-service, 657 timeouts on checkout, five services affected. Causely's suggested remediation is attached: add circuit-breaking in the payment-adapter so a slow dependency doesn't take checkout down with it.

18:14:19. The agent has the root cause, the evidence, and the blast radius. Sixteen seconds. It moves to the fix.

18:14:20 to 18:18:57. Everything from here happens inside the repository. The agent readspayment-adapter/main.go, finds the outbound call, edits, reviews its own diff, commits, pushes, and opens the pull request. It never goes back to Causely, Grafana, or Kubernetes. It already knows what it is fixing and why.

The pull request adds a circuit breaker and a per-call deadline around the external payment call, 87 lines in one file. The description explains why this fix, and not another: the external API is outside the repository, the cascade is inside it, and stopping the cascade restores checkout. Causely's diagnosis and evidence are in the PR body for the reviewer.

Four minutes and fifty-four seconds from Issue to pull request. Seventeen seconds of that was diagnosis. The first human involvement is the review.

Example managed agent being triggered by Causely Issue notificationExample managed agent being triggered by Causely Issue notification

Under a threshold trigger, the same session would have opened on "checkout error rate is high" and spent its first minutes listing services, pulling error rates, and reading logs to discover that the payment-adapter was where the cancellations originated and that the external API was why. Here, that work was done deterministically by the causal model before the session started. The agent's tokens are spent on the code fix.

FAQ

What is a control band in the AI-native SDLC?

A control band is the expected range for a production metric, defined by a deterministic script rather than by a model. Anthropic's AI-native SDLC playbook sets bands from a rolling baseline and tiers the response by how far the metric strays: log at 1σ, invoke an agent read-only to diagnose at 2σ, allow a pull request or a pre-approved runbook at 3σ.

What is the difference between triggering an agent on an alert and triggering it on a diagnosis?

An alert reports that one signal left its range. A diagnosis names the affected entity and exposes the causal chain that explains the symptom. An agent, triggered by an alert, reconstructs the chain from the raw cluster state before it can act. An agent, triggered by a diagnosis, starts from that diagnosis and spends its budget on the fix.

How do I trigger a Claude managed agent from an external system?

Host a receiver yourself. The Managed Agents API supports cron and manual deployment triggers, and its webhook helper handles outbound notifications about session state, so there is no inbound webhook you can point a monitoring tool at. Run a small HTTP service that authenticates the payload, turns it into the agent's first message, and calls the sessions API.

How do I keep an autonomous agent from investigating everything?

Filter at the source. Send only Critical and High severity notifications, and send Issues rather than individual defects, so that one incident produces one investigation instead of several. Every session costs tokens and runs without supervision, so the severity filter does double duty as a cost control and a noise control.

If the agent starts from a diagnosis, who checks the diagnosis? The reviewer on the pull request, using the causal chain the diagnosis carries. Causely exposes what could explain the symptom and the evidence for each candidate, so a person or a second agent can ask why this diagnosis rather than an alternative before any change is made. Branch protection keeps the agent from approving its own work.

What to do next

Clone the example repository and point a Causely Issue notification at a managed agent. The Kubernetes half runs against a local kind cluster, so you can see a session start from a notification before you connect anything real.

Next Claude Managed Agents post: multiple scenarios run with and without causal context, measuring tokens, time to diagnosis, and whether the pull request the agent opened fixed the fault.

Top comments (0)