The authorization gap nobody talks about

AI agents make tool calls. Every tool call is an action taken on your behalf, with your credentials, against your systems. And you did not pre-authorize any of them.

Traditional authorization happens at session start. You authenticate, you get a token, the token carries scopes, and those scopes define what you can do. Clean model. Works for humans who log in and click buttons.

Agents don’t work this way. An agent receives a natural language instruction, decomposes it into steps, and each step is a tool call. The tool calls are determined at runtime by the model, not at design time by the developer. The instruction “research this company and draft a summary” could produce ten tool calls or fifty, hitting web search, file write, database read, credential lookup. You authorized none of those individually. You authorized the intent. The agent chose the actions.

The gap between what you intended and what the agent does is the attack surface. It’s also the place where accidents live.

This is the problem CB4A solves. Not by restricting what agents can do, but by classifying what they’re actually doing, in real time, and routing each action to the appropriate level of oversight.


Four tiers, not four rules

CB4A stands for Content-Based 4-tier Authorization. Every tool call that passes through the authorization layer gets classified into one of four tiers based on what the call actually contains, not just which tool it invokes.

graph TD
    A[Tool Call Arrives] --> B{Fast Path: Regex Rules}
    B -->|Match: HARD rule| C[Tier Assigned]
    B -->|Match: SOFT rule| D[Ceiling Applied]
    B -->|No match / Ambiguous| E{Semantic Path: LLM Classifier}
    E --> C
    D --> C
    C --> F{Tier?}
    F -->|T1: Benign| G[Auto-approve, Log]
    F -->|T2: Review| H[Execute, Queue for Review]
    F -->|T3: Gate| I[Block Until Rule Match or HITL]
    F -->|T4: Block| J[Hard Block, Alert]
CB4A tier classification: every tool call gets a tier before execution

Tier 1: Benign. Read-only operations, web searches, file reads. Auto-approved and logged silently. The agent keeps moving.

Tier 2: Review. Actions that modify state but aren’t dangerous. File writes, database updates, configuration changes. The action executes immediately, but it goes into a review queue. A human sees it within the session or at the daily review.

Tier 3: Gate. Actions that could cause harm if wrong. Git pushes, API calls to external services, infrastructure changes. These block until either a rule match clears them automatically or a human approves through a notification channel.

Tier 4: Block. Hard stop. Credential exposure detected, injection patterns found, actions that would be catastrophic if executed. No override without explicit human approval.

4 Authorization tiers
<5ms Fast path latency
T4 Auto-blocks credentials

Two paths: fast and semantic

The classification engine has two layers. The fast path handles the 90% case. The semantic path handles the rest.

Fast path: regex rules

The fast path is a set of pattern-matching rules. Each rule has a regex pattern, a tier assignment, and a rule type: HARD or SOFT.

HARD rules set the tier directly. If a tool call’s content matches a HARD rule, that’s the tier. No further analysis. A HARD T4 rule for credential patterns means that if the output of a tool call contains what looks like an API key or token, it’s blocked. Period.

SOFT rules set a ceiling. A SOFT T2 rule on file write operations means the action can’t be classified lower than T2, but the semantic layer might push it higher. SOFT rules are guardrails, not verdicts.

The core idea in code looks something like this:

# Simplified rule structure
RULES = [
    # HARD rules: deterministic tier assignment
    {"pattern": r"(credential_prefix)[A-Za-z0-9]{20,}", "tier": 4, "type": "HARD",
     "reason": "credential pattern detected in output"},
    {"pattern": r"<script>|javascript:", "tier": 4, "type": "HARD",
     "reason": "injection pattern detected"},

    # SOFT rules: tier ceiling
    {"pattern": r"(git push|git commit)", "tier": 2, "type": "SOFT",
     "reason": "git write operation"},
    {"pattern": r"(infrastructure mutation keyword)", "tier": 3, "type": "SOFT",
     "reason": "infrastructure change"},
]

Semantic path: LLM classifier

When the fast path produces an ambiguous result, or when a SOFT rule sets a ceiling that needs refinement, the tool call goes to a lightweight LLM classifier. It answers one question: is this tool call mentioning something sensitive, or using something sensitive?

The mention-vs-use distinction matters enormously. A research agent that writes “the company uses API keys stored in environment variables” is mentioning credentials. An agent that outputs an actual token value in a file write is using one. The regex can’t tell the difference. The LLM can.

90% Resolved by fast path
~200ms Semantic path latency
Small model Classifier size

The semantic classifier runs asynchronously. For T3 actions that are already gated, the latency doesn’t matter because the action is blocked anyway. For T2 actions where the SOFT rule might need upgrading, the classifier result determines whether the action goes into the review queue or gets escalated.


Human in the loop via chat notification

T3 and T4 actions need human approval. The human-in-the-loop (HITL) path runs through a self-hosted messaging platform.

sequenceDiagram
    participant Agent
    participant AuthGate
    participant Chat
    participant Human

    Agent->>AuthGate: Tool call
    AuthGate->>AuthGate: CB4A classify (T3)
    AuthGate->>Agent: Immediate block response
    AuthGate->>Chat: DM to operator via bot
    Note over Chat: Action, tier, context, reason
    Human->>Chat: APPROVE / DENY
    Chat->>AuthGate: Callback
    AuthGate->>Agent: Release or cancel
HITL approval flow: authorization gate to messaging to human to action

The messaging integration sends a direct message through a bot account with the action details, tier, and classification reason. The message format is designed for quick scanning on mobile: what’s being done, why it was flagged, and the approval options.

The design is notify-then-block, not block-then-notify. The agent gets an immediate block response so it can handle the interruption gracefully (retry, skip, or wait). The chat notification fires in the background. This means the agent never hangs waiting for a human who might be asleep.


The false positive problem

Any content-based classification system will produce false positives. CB4A’s approach is to make false positives cheap and false negatives expensive.

A false positive at T2 means an action goes into the review queue when it didn’t need to. Cost: a few seconds of human review time, eventually. A false positive at T3 means an action blocks when it should have proceeded. Cost: agent pauses, human gets a chat notification, approves in seconds.

A false negative at T4 means a credential leaks. That cost is not comparable.

The tiers are designed so that over-classification costs minutes and under-classification costs weeks of incident response.

The SOFT rule system is the primary false-positive management mechanism. Instead of making every file write a T3 (which would flood the approval queue), SOFT rules set a ceiling at T2 and let the semantic classifier decide if the specific content warrants escalation. A file write containing a markdown summary stays T2. A file write containing a raw token gets pushed to T4 by the HARD rule before the SOFT ceiling even applies.


Where it lives

CB4A is implemented as middleware inside an authorization gateway service. The gateway sits in the tool call path for all agents, including autonomous agent fleets that run without a human at the keyboard.

graph LR
    A[Agent Tool Call] --> B[Authorization Gateway]
    B --> C[Intent Validation]
    C --> D[CB4A Tier Classification]
    D --> E[PII Scanner]
    E --> F{Tier Decision}
    F -->|T1/T2| G[Execute + Log]
    F -->|T3| H[Gate + HITL Approval]
    F -->|T4| I[Block + Alert]
Authorization gateway: CB4A as one layer in a multi-stage pipeline

The service stack is layered: an intent validation layer evaluates whether the action aligns with the user’s original intent and the agent’s assigned role. CB4A evaluates the content of the specific tool call. PII scanning catches personal data that should never appear in agent output. Each layer operates independently. A tool call that passes intent validation can still be blocked by CB4A if the content is dangerous.

Configuration is managed declaratively, which means CB4A can be toggled without redeploying the service. A lesson learned here: if you use a gitops tool that automatically reconciles state, manually patching a config value will get silently reverted within minutes. You either commit the change to git or you watch your toggle flip itself back on three times before you figure out what’s happening.


What broke and what I learned

v1 had one rule type. Every regex match was a verdict. This meant git push always triggered the same tier regardless of context. The HARD/SOFT split in v2 was the fix.

The semantic classifier needed a precise question. Early prompts asked “is this action safe?” which is unanswerable without full system context. The question that works is narrower: “Is this content mentioning something sensitive, or using it?” The LLM can answer that from the tool call content alone.

Image caching will bite you. If your deployment environment caches container images locally, pushing a new image to your registry does not mean the running service picks it up. You have to clear the local cache and pull fresh. This is fine for air-gapped setups, but it adds a manual step to every deploy that is easy to forget.

SSL verification on internal services. The HITL approval path failed silently on first deploy. Self-signed certs behind a VPN need explicit SSL bypass on every HTTP client instance. “Both” means both, not “the one you remembered to change.”

v2 Current version
2 Rule types (HARD/SOFT)
0 T4 false negatives

What’s next

The current classifier uses a small, fast cloud model. For ambiguous cases, a more capable model might improve precision. The plan is to route through a local model for zero API cost on the semantic path.

The feedback loop from approval decisions back into rule tuning is not yet automated. Every APPROVE on a T3 action is a data point that the rule might be too aggressive. Every DENY is validation. Collecting these decisions and adjusting SOFT rule ceilings automatically is the next iteration.

CB4A currently evaluates individual tool calls in isolation. The sequence matters too: ten benign file reads followed by a file write that combines all of them is a data exfiltration pattern that no single-call classifier would catch. Sequence-level evaluation is the path toward session-level threat detection, and it is next on the list.