Operations · · 6 min read
Five things that keep breaking when AI agents move into production
The operator-pain pattern that keeps recurring in CISO discovery calls, with concrete scenarios and the standard fixes that don't close them.
A user asks a customer-support agent a question that requires comparing their data to other customers' data. The agent decides that is reasonable, reads across tenant boundaries under a service account's broad access, and returns an aggregate. No PII crosses the wire, so the DLP layer never fires. The read still happened.
That is one of five operator-pain points that recur across a year of shipping agentic security in production and several months of CISO discovery calls. They are old categories of risk that autonomous agents expose in ways existing controls do not catch. Each has a standard fix that does not close it, and a different layer where the fix lands.
Cross-tenant data reach#
Agents reach across data they were never scoped to.
The agent runs under a service account with broad read access, because the integration was built around "let the agent answer questions about customer data." The agent decides a question requires comparing against other customers' data and reads it, crossing tenant boundaries inside a single run. The customer who asked got an answer. The customers whose data was sampled have no record of the read in their dashboards.
The standard fix is more guardrails: a content classifier on inputs, a DLP rule on outputs, a prompt-injection detector on the model. None addresses cross-tenant reach. The classifier saw a legitimate question, the DLP rule had no PII to catch, and the injection detector had no injection to detect. The agent decided on its own.
The fix lives at the identity layer. The agent's identity for the run is scoped to the customer the run is helping, and the policy gate refuses reads outside that scope. The model can attempt the read, the gate refuses it, and the loop proceeds without the data.
Without the fix, the security team finds out in a postmortem. That gap between the read and the postmortem is discovery lag. With the fix, they find out at the moment of the attempt, as a denied audit row.
Destructive operations without approval#
The agent has API access that includes destructive verbs: drop tables, force pushes, deletes the operator cannot undo. The model decides a destructive operation is the right next step, sometimes for a misinterpreted reason. The call goes through because the service account has the permission, and the loop continues, making its next decision on top of the destroyed state.
The standard fix is a confirmation step: a prompt asking the model to confirm, or an "are you sure" parameter. Neither works. The model that decided to invoke the operation will confirm it, and the parameter is one more field to pass.
The fix lives at the policy gate, with the require-approval outcome. The gate evaluates the action class against the policy, and destructive operations in a production scope need an operator's approval before the API call is made. The operator approves or denies while the agent waits. The model's confirmation does not substitute for the operator's.
The harder design problem is making sure the operator reads the approval instead of rubber-stamping it, covered in Designing approvals operators actually read.
No kill switch in one place#
Stopping a running agent turns into a research project.
The agent calls six tools. Three use its primary credential, two use separate credentials minted for specific services, and one calls a third-party API on a webhook. "Stop the agent" becomes:
- Find every credential the agent is using and revoke each separately.
- Check for credential paths the operator does not know about.
- Deal with in-flight requests that were already sent.
The standard fix is to redesign the credential layer around one credential. That is the right direction, but it does not cover in-flight actions, spawned sub-agents, or credentials cached downstream. The kill switch has to operate at the run level. The runtime maintains the set of active runs, revoking a run removes it from the set, and the policy gate refuses subsequent actions for any run not in the set. In-flight requests fail their next gate check, and sub-agents inherit the revocation.
The fix lives at the runtime control plane: one button that takes effect on every downstream credential, sub-agent, and in-flight action.
The deeper containment design, with three outcomes (stop, scope, quarantine) instead of one, is in Stopping a running agent.
Missing SIEM attribution#
The SIEM has the action. The chain back to a person is not in the row.
The agent makes an API call. The gateway logs it and ships it to the SIEM, and the row records what was called, when, and which credential was used: the agent's service account. The operator who launched the run is not on the row, because their identity was not propagated through the credential the gateway saw.
Months later, the security team investigates a suspicious call. The row says the service account did it, and that account serves many operators. The investigation falls back on best-guess timestamps or the runtime's own logs, if those still exist.
The standard fix is to ask the agent's authors to include the operator id in request headers. It works until an upstream service drops headers or a proxy normalizes them.
The fix lives at the identity layer. The agent runs under an identity that includes the operator as a verifiable claim. The gateway emits the claim as a structured field in the action's audit row, so the SIEM row carries it end to end instead of depending on a header. The schema in What an agent audit row should carry is the operational form of this fix.
Scope is unknowable#
"What data can this agent actually reach?" comes up in every CISO conversation.
The security team is asked to sign off on an agent's deployment. The builders answer "what will it have access to" with the service account's permissions. Asked what the agent will reach in practice, they have no answer, because the agent decides at runtime what to read. Nobody can name that subset without running it in production and watching, so the security team is being asked to approve a superset.
The standard fix is to scope the service account more tightly. That is the right direction, but it does not survive the next prompt that needs data outside the new scope. The agent fails, the operator widens the scope back, or the team builds an escape hatch.
The fix lives at the policy gate, with run-time scope. The agent's identity at the start of each run is scoped to the work in front of it. The pre-deployment answer becomes: the policy permits these resource classes, each run is scoped within those classes, and the audit log records every resource actually touched. The deployment decision rests on the policy instead of a static service account.
Five gaps, three primitives#
Each pain is a gap between what the agent can do (the service account's broad permission) and what it should do for the work in front of it. Three primitives close that gap:
- Identity scoped to the run, with the operator behind it.
- Runtime enforcement that evaluates every action against that scope before it runs.
- Audit that records every action, every decision, and every operator behind it.
Deixic keeps company context, procedures, tests, and authority outside the worker. Governed tool calls carry identity, policy and approval decisions, and results. Teams can review that history to improve a procedure and test later work against it. See the company layer and Trust.