Skip to content

Enterprise deploymentFully managed today; customer-hosted available as a pilot.Contact salesView pricing

Guide12 min read

Guardrails developers won't route around

When a security control makes AI calls slower or more confusing than calling the model directly, developers switch to a personal key and the control protects nothing. How to make the governed path the easiest one, and how to measure bypass.

IntertraceSecurity engineering

Plain-language guidance for teams adopting AI — the risk, the cost, the compliance, and what to ask before you buy.

August 1, 2026 · 12 min read

Developer ExperienceAI GatewayShadow AIPlatform EngineeringGuardrails
A developer reaches the model by two paths: a short governed path through the gateway and a dashed side door using a personal key
If the governed path is shorter than the side door, developers take it without being told to.Fig. 0 · Cover
Contents
  1. 01Why developers route around AI controls
  2. 02One base URL, same API
  3. 03Fast paths: spend checks where consequence is
  4. 04A denial is a user interface
  5. 05Exceptions developers can request in minutes
  6. 06Measure bypass, don't guess it
  7. 07A worked example: the platform team at Hollin Freight
  8. 08Close the side doors last
  9. 09What to do this quarter

The pattern is familiar to anyone who has rolled out an AI control. Security launches a gateway or an approval process, the dashboard shows traffic flowing through it, and the program is declared a success. A quarter later, the AI provider invoice is larger than the gateway's own usage numbers can explain. Someone traces the difference to personal keys on corporate cards, a team calling the provider directly from a batch job, and an evaluation pipeline that was moved off the gateway because, in the team lead's words, it kept blocking things and nobody could say why.

It is tempting to read that as a compliance failure. It is better read as a product failure. Every developer who routes around a control paid a cost the control's designers did not see. Fix the cost and most of the bypass disappears; enforcement then handles the remainder, which is much smaller and much easier to justify.

Why developers route around AI controls

Bypass has a small number of causes, and each has a specific design fix. Before you change anything, interview three teams that left the governed path and sort what they tell you into this table.

Common frictions in AI controls, what developers do instead, and the design fix
FrictionWhat the developer experiencesWhat they do insteadDesign fix
Setup costA ticket and several days of waiting for an API keyCreate a personal key in the provider consoleSelf-serve keys in minutes, scoped to a project and an environment
A different APIAn internal SDK wrapper with its own request shape that lags the provider's featuresCall the provider SDK directlyKeep the provider's API and change only the base URL
Latency everywhereEvery call, including trivial ones, waits on the heaviest checkTurn the control off in development, then forget to turn it back onCheap checks for low-consequence calls; spend time where consequence is
Opaque denialsA bare 403 that says the request was blockedRetry, rephrase the prompt, or switch pathsA denial with the rule, the reason, a decision ID and a next step
No exception pathA feature blocked for weeks waiting on a reviewShip a shadow deployment on a separate keySelf-serve, time-limited exceptions with a named owner
Feature gapsStreaming, tool calls or a new model work directly but not through the controlUse the direct path for the features that matterTreat feature parity as a requirement and publish the gaps

Two of these do most of the damage in practice. Setup cost decides which path a new project starts on, and projects rarely move later. Opaque denials decide whether a team stays: a developer who hits three unexplained blocks in a week stops trusting the path, even if each block was correct.

One base URL, same API

Make the governed path a configuration change, not a code change. Most model SDKs already let you point the client at a different endpoint. The OpenAI Python library, for example, accepts a base_url argument and also reads the OPENAI_BASE_URL environment variable [3]. If your control speaks the same API, a team adopts it by setting one variable and swapping one key, and every feature the provider ships keeps working unless you deliberately block it.

Do the same for tool traffic. If agents reach MCP servers and internal tools through the same front door as model calls, there is one endpoint to configure, one key to rotate and one place where policy applies. A separate integration for each kind of traffic multiplies the setup cost you are trying to remove.

  • Put the governed base URL into every project template, internal starter kit and CI image, so a new service is on the governed path before anyone makes a choice.
  • Hold provider credentials centrally and never hand them to developers. If the only working provider key lives behind the control, a personal key is not faster; it is a second account to set up and expense.
  • Issue keys self-serve per project or per agent, tagged with an environment such as development or production, so policy can treat a test run differently from production traffic.
  • Publish a one-page quick start that fits on a screen: the base URL, how to get a key, what is checked, and where denials are explained.

Fast paths: spend checks where consequence is

Not every call deserves the same scrutiny. A chat completion that summarizes an internal document and a tool call that deletes a production table are different risks, and a control that charges both the same latency will be resented on the first and under-powered on the second. Sort calls by consequence, meaning the worst realistic outcome of one call judged by reversibility and reach, and spend inspection where it changes outcomes.

Spend checks where consequence isFig. 1
Agent callmodel or toolRead the calltool name + argumentsREADS · REVERSIBLE CHANGESCheap checksreal secrets · card numbersRunsno waitIRREVERSIBLE · OUTBOUND · MONEYFull inspectionarguments · policy · DLPAsks a personBlockedstructural checks run on every call · the expensive work runs only where one call can do damage

Reads and reversible changes take a short path with cheap checks and run; irreversible, outbound, financial and administrative calls take the full path and may ask a person or be blocked. Most developer traffic never waits on the expensive path.

Environment matters as much as action. In development, an agent deleting a row in a disposable test database should not wait for a person. In production, the same call should. Outbound messages, payments and administrative changes are the exception: they reach the outside world or change who can do what, so they should ask everywhere, including in development, where a test message to a real customer is still a real message.

The fast path is not a weaker path. Structural checks, such as detecting real credentials or card numbers in a prompt, are cheap and should run on every call. What the fast path skips is the expensive work that only matters when a call can do damage.

A denial is a user interface

Most developers meet your control for the first time when it says no. That response is the control's user interface, and a bare 403 with the text request blocked is the worst one available. It tells the developer that something is wrong without telling them what, whether it is their fault, or what to do next. They rephrase the prompt, retry, and, when that fails, find another path.

HTTP already has a standard for this. RFC 9457 defines problem details: a machine-readable error body with a type URI that identifies the problem, a short human-readable title, a detail field specific to this occurrence, and an instance URI for the occurrence itself, and it allows problem types to add their own extension members [1]. Use it, and add the fields developers need to act.

A denial developers can act onFig. 2
Bare denialHTTP 403Request blocked.WHICH RULE?WILL A RETRY HELP?WHO DO I ASK?Structured denialILLUSTRATIVE VALUES403 · application/problem+jsontype/problems/data-ruletitleCard number in requestdetailcard-like value in messages[2]ruleorg.data.card-numberslayerorganizationretryno · remove the value firstdecisiondec_7f3a91nextrequest exception · rule docsa denial is the control's user interface · it should tell the developer what happened and what to do next

The bare denial on the left gives the developer nothing to do but retry or leave. The structured denial on the right names the rule and the reason, says whether a retry helps, and links to the exception request.

  • Name the rule and the layer that decided, for example an organization-wide data rule versus a rule specific to this agent, so the developer knows whom to talk to.
  • Say what was found and where, without echoing the sensitive value: a value that looks like a card number in the third message, not the number itself.
  • Say whether a retry can succeed. Policy denials will not change on retry; rate limits will. RFC 6585 defines 429 Too Many Requests for rate limiting and allows a Retry-After header saying how long to wait [2]. Keep the two distinct so client retry logic does the right thing.
  • Return a decision ID that support and security can look up, so a developer can report a false positive in one message.
  • Link to the next step: the documentation for the rule, the exception request, or the approval that is now pending.

Before a new rule blocks anything, run it in monitor mode and replay it against recent traffic. Count which teams it would have blocked and read a sample. A rule that would have denied a hundred legitimate calls a day is not ready, however sound its threat model.

Exceptions developers can request in minutes

Some denials will be correct in general and wrong for one team this week. If the only remedy is a security review with a two-week queue, the team will find another path. Make exceptions self-serve within limits instead, and make them expire.

  • An exception is named, scoped to one agent or project, and carries a written reason and the requester's name.
  • It has a default expiry measured in days and a hard maximum, so it cannot quietly become permanent.
  • Low-consequence exceptions take effect immediately and are reviewed afterward; exceptions that touch outbound, financial or administrative actions need an approver before they apply.
  • The agent's owner and the security channel are notified automatically, and every decision made under the exception records that it was the exception that allowed it.
  • Exceptions that are renewed repeatedly are reviewed as evidence that the rule is wrong, not as evidence that the team is careless.

Measure bypass, don't guess it

The headline metric is governed share: the fraction of AI usage that goes through the control. The difficulty is the denominator, because bypassed traffic is by definition the traffic you do not see. Build it from several sources. AI provider organizations list keys and usage per key. Expense systems show subscriptions bought on cards. Egress logs and DNS show which hosts call provider API domains. Identity providers show OAuth grants to AI applications. Repository scanning finds committed keys; GitHub secret scanning, for example, lists both OpenAI and Anthropic API keys among its supported patterns [4].

Metrics that show whether developers prefer the governed path
MetricHow to compute itHealthy direction
Governed share of spendSpend through the control divided by total provider spend across all organizations and expensed accountsRising toward nearly all
Keys outside the controlProvider keys not issued through the control, from provider org listings and repository scansFalling, with each one assigned an owner
Time to first governed callMinutes from a new project's key request to its first successful callShort enough that nobody looks for a shortcut
Denials overturnedShare of denials later reversed as false positives or granted an exceptionLow and falling; a spike means a bad rule
Time from denial to resolutionMinutes from a denial to a successful call or a granted exceptionFalling
Exception renewalsExceptions renewed more than once for the same ruleEach renewal reviewed as a rule defect

When you find a bypass, contact the team before you revoke anything. Ask what they were trying to do and what stopped them on the governed path. Most answers map to a row in the friction table, and fixing that row helps every team rather than one.

A worked example: the platform team at Hollin Freight

Consider Hollin Freight, a fictional logistics company with forty product teams. All numbers in this example are illustrative. A central platform team ran an AI gateway that required a ticket for a key, which took about four days. It shipped a custom SDK that did not support streaming, and its denials returned a generic message. A discovery pass found twenty-three provider keys that had never been issued through the gateway, and the finance team estimated that a little over half of AI spend went through it.

Over one quarter the platform team changed five things, in this order. Keys became self-serve with a development or production tag. The custom SDK was retired in favor of the provider's own SDK pointed at the gateway's base URL, which brought streaming and tool calls back. Denials adopted the problem-details format with rule, reason, decision ID and an exception link. New rules spent two weeks in monitor mode before enforcing. And teams could grant themselves a seven-day exception for low-consequence rules, with a notification to security.

Only after those changes did the team close side doors. It gave every owner of an outside key thirty days' notice, offered to migrate their workloads, then revoked the remaining keys in the provider organizations and blocked provider API domains from production networks. By the end of the quarter, governed share was above ninety percent, time to first call was under ten minutes, and the most common exception had exposed a rule that flagged internal shipment IDs as card numbers. The rule was fixed and the exception stopped being requested.

What Hollin did not do matters too. It did not announce enforcement first, it did not name teams in an all-hands, and it did not treat the twenty-three keys as policy violations. Blocking first would have pushed the same workloads onto laptops and personal accounts, where nothing can see them.

Close the side doors last

Enforcement is still necessary; it just comes last. Once the governed path is the easier one, restrict egress to provider API domains from production networks, revoke provider keys that were not issued through the control, turn on push protection for provider keys in your repositories, and decline AI subscriptions on expense reports that duplicate a governed service. Announce each step with a date and a migration offer. Each one now removes an inferior option instead of the only working one.

What to do this quarter

  1. Interview three teams that left the governed path and sort their reasons into the friction table.
  2. Measure governed share of spend from provider organizations, expense data and repository scans, and record a baseline.
  3. Make keys self-serve and put the governed base URL into every project template and CI image.
  4. Adopt a structured denial format with rule, reason, retry guidance, decision ID and next step, and test it by showing three developers a denial and asking what they would do.
  5. Put every new rule through monitor mode and a replay against recent traffic before it enforces.
  6. Launch time-limited, self-serve exceptions for low-consequence rules and review renewals monthly.
  7. Only then set dates for revoking outside keys and restricting egress, and track the metrics table monthly.

Where a runtime gateway helps

A runtime gateway can carry most of the design above. With Intertrace, teams change their base URL and use a runtime key, and the same front door covers model calls, MCP traffic and agent-to-agent messages. The gateway assigns each call a consequence tier from the tool name and its arguments, so reads and reversible changes run while outbound messages, payments and administrative changes ask a person. Each decision records the rule and the layer that made it, exceptions are named, scoped to one agent and expire after seven days by default and ninety at most, and a proposed rule can be replayed against the last thirty days of real decisions before it blocks anything. The work of interviewing teams and closing side doors remains yours.

Sources

Reporting, research and specifications this piece draws on. Links go to third-party sources; analysis and recommendations are Intertrace’s own.

  1. 01RFC 9457: Problem Details for HTTP APIs · IETF
  2. 02RFC 6585: Additional HTTP Status Codes (429 Too Many Requests) · IETF
  3. 03OpenAI Python API library: configuring the HTTP client · OpenAI
  4. 04Supported secret scanning patterns · GitHub Docs

Dated August 1, 2026 · added to intertrace.ai October 19, 2026

+ Runtime enforcement

See these controls on your own agent traffic.

Intertrace sits inline between your agents and the models, tools and MCP servers they call, and decides every call before it runs.

Keep reading

All insights →