<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Grice</title>
    <description>The latest articles on DEV Community by David Grice (@webpro255).</description>
    <link>https://dev.to/webpro255</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3837607%2Fe33522bf-a485-4026-9da2-8915c8b7c8af.png</url>
      <title>DEV Community: David Grice</title>
      <link>https://dev.to/webpro255</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/webpro255"/>
    <language>en</language>
    <item>
      <title>Why AI Agent Authorization Is Still Unsolved in 2026</title>
      <dc:creator>David Grice</dc:creator>
      <pubDate>Tue, 07 Apr 2026 21:17:41 +0000</pubDate>
      <link>https://dev.to/webpro255/why-ai-agent-authorization-is-still-unsolved-in-2026-5hdk</link>
      <guid>https://dev.to/webpro255/why-ai-agent-authorization-is-still-unsolved-in-2026-5hdk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokzbr42r6hlrjg2ztkok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokzbr42r6hlrjg2ztkok.png" alt="Ai Free" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In March 2026, a security scanner called Trivy was compromised for less than a day. The stolen credentials cascaded downstream into LiteLLM, a library used by thousands of companies to connect their applications to AI services. Within 40 minutes, attackers harvested credentials from an estimated 500,000 machines across 1,000 SaaS environments.&lt;/p&gt;

&lt;p&gt;Mercor, a $10 billion AI recruiting startup that handles contractor data for OpenAI, Anthropic, and Meta, was one of those companies. Meta indefinitely suspended all work with Mercor. A class action lawsuit was filed on behalf of 40,000 affected individuals. Lapsus$ claimed to have exfiltrated 4 terabytes of data.&lt;/p&gt;

&lt;p&gt;The attacker group TeamPCP didn't target Mercor directly. They poisoned a dependency that Mercor happened to use. The agents had valid credentials. The tools executed normally. Nothing looked wrong until it was too late.&lt;/p&gt;

&lt;p&gt;This is the pattern that keeps repeating. And no one has solved it yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Is Not Detection
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fra9xaaspk73y6sjyhtfh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fra9xaaspk73y6sjyhtfh.png" alt="authorized" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every major AI agent security incident in the past 18 months shares the same characteristic: the breach came through authorized channels.&lt;/p&gt;

&lt;p&gt;Meta's internal Sev 1 incident in March 2026 involved an AI agent that posted responses and exposed user data to unauthorized engineers. The agent wasn't hacked. It had permission to act. It just acted in ways nobody expected.&lt;/p&gt;

&lt;p&gt;The Salesloft Drift breach in August 2025 compromised 700+ organizations through stolen OAuth tokens from a legitimate SaaS integration. The attacker looked like a trusted connection because they were using one.&lt;/p&gt;

&lt;p&gt;Microsoft's EchoLeak vulnerability demonstrated zero-click data exfiltration through Copilot, requiring no user interaction at all. The AI assistant extracted sensitive data from OneDrive, SharePoint, and Teams through approved channels with no visibility at the application or identity layer.&lt;/p&gt;

&lt;p&gt;The common thread: sandboxes don't help. Firewalls don't help. Content moderation doesn't help. The agent has legitimate access to tools it is supposed to use. The question is whether any given tool call, at this moment, in this context, should actually be allowed.&lt;/p&gt;

&lt;p&gt;That's authorization. And almost nobody is doing it at the tool call level.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Authorization Actually Means for AI Agents
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv33gvirhht1q9mct4u4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv33gvirhht1q9mct4u4z.png" alt="allow_deny_modify_defer_stepup" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traditional authorization answers a simple question: does this user have permission to access this resource?&lt;/p&gt;

&lt;p&gt;AI agent authorization has to answer a harder question: does this user, in this session, with this behavioral history, have permission to call this specific tool with these specific parameters, given everything that has happened in this conversation so far?&lt;/p&gt;

&lt;p&gt;That's a fundamentally different problem. And it requires more than binary allow/deny decisions.&lt;/p&gt;

&lt;p&gt;Consider what happens when a customer support agent receives a request that looks like a GDPR data subject access request. The request is legitimate in form. The user may or may not be who they claim to be. The data they're requesting is sensitive. The right answer isn't "allow" or "deny." The right answer is "defer this to a human who can verify the request" or "allow the query but redact the PII from the output before the model sees it."&lt;/p&gt;

&lt;p&gt;These are non-binary authorization decisions. Allow, deny, modify, defer, step-up. Five decision types, not two.&lt;/p&gt;

&lt;p&gt;Most agent frameworks today have two modes: the tool is available, or it isn't. There's no middle ground. No "you can call this tool but the output will be filtered." No "this request looks suspicious, pause and ask for additional verification." No "the last three requests in this session show a pattern of escalation, tighten the permissions."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Guardrails Are Not Authorization
&lt;/h2&gt;

&lt;p&gt;The industry response to AI agent security has been guardrails. Input filters. Output scanners. Content moderation. Prompt injection detection.&lt;/p&gt;

&lt;p&gt;Guardrails answer the question: "Is this input/output safe?"&lt;/p&gt;

&lt;p&gt;Authorization answers a different question: "Is this action permitted?"&lt;/p&gt;

&lt;p&gt;A guardrail can detect that a prompt contains an injection attempt. But what about a request that contains no injection language at all? What about a user with valid admin credentials who is being socially engineered into exfiltrating data through a series of perfectly normal-looking requests?&lt;/p&gt;

&lt;p&gt;I ran 222 adversarial attack vectors across 35 categories against an AI agent with full admin credentials. The attacker had valid credentials. Role checks passed on every call. The question was whether anything beneath role-based access control could detect and stop the attacks.&lt;/p&gt;

&lt;p&gt;With only role-based permissions (traditional authorization), the pass rate was 30.2%. The agent was completely exposed.&lt;/p&gt;

&lt;p&gt;Adding adaptive prompt hardening, which adjusts the agent's defensive posture based on behavioral signals in the conversation, brought the pass rate to 57.1%.&lt;/p&gt;

&lt;p&gt;Adding non-binary decision types brought it further. When the system could modify tool outputs (redacting PII before the model saw it), defer suspicious requests to human review, and require step-up authentication for elevated risk actions, the pass rate reached 81.3%.&lt;/p&gt;

&lt;p&gt;Fixing the remaining gaps, adding signed audit receipts and hash-chained context for tamper detection, brought the final score to 99.5%. 221 out of 222 attacks stopped. The single remaining failure was a social engineering attack using legal citation pressure with zero injection language. That's a model-layer behavior that middleware cannot fix.&lt;/p&gt;

&lt;p&gt;The point isn't the specific numbers. The point is the progression: traditional permissions alone fail catastrophically when the attacker has valid credentials. You need infrastructure that watches behavior, not just identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Missing from Current Frameworks
&lt;/h2&gt;

&lt;p&gt;I looked at every major AI agent framework, LangChain, CrewAI, AutoGen, OpenAI Agents SDK, and the Model Context Protocol. Here's what they have in common: tool registration is permissive by default. If a tool is registered, the agent can call it. If the agent can call it, there's no middleware layer that evaluates whether this specific call, at this specific moment, should be allowed.&lt;/p&gt;

&lt;p&gt;Some frameworks have human-in-the-loop features. LangChain has Interrupts. CrewAI has Human Input. These are useful for high-risk actions where you always want human approval. But they're static. The decision to require approval is made at design time, not at runtime based on what's actually happening in the conversation.&lt;/p&gt;

&lt;p&gt;What's missing is a runtime authorization layer that sits between the agent and its tools and makes per-call decisions based on accumulated session context. A layer that knows this is the fifth database query in three minutes and the last two returned escalating amounts of data. A layer that knows the user started by asking about weather and is now requesting customer records.&lt;/p&gt;

&lt;p&gt;Microsoft recently released the Agent Governance Toolkit. It's a policy engine that intercepts agent actions and evaluates them against organizational rules. That's governance. It answers "does our policy allow this type of action?" But policy enforcement and permission enforcement are different layers. A perfectly enforced policy doesn't help if the policy itself doesn't account for behavioral context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Compromised Admin Problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hal6daoldc7n5x5de33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hal6daoldc7n5x5de33.png" alt="compromised agent" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hardest scenario in AI agent security isn't the outsider trying to break in. It's the insider with valid credentials being manipulated through conversation.&lt;/p&gt;

&lt;p&gt;I call this the compromised admin scenario. The attacker has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Valid credentials that pass authentication&lt;/li&gt;
&lt;li&gt;An admin role that passes authorization checks&lt;/li&gt;
&lt;li&gt;Legitimate access to every tool the agent exposes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditional security is useless here. Auth passes. Role checks pass. The firewall sees a valid session. Every tool call looks normal in isolation.&lt;/p&gt;

&lt;p&gt;The only defense is behavioral. Does the pattern of requests over the session indicate escalation? Is the user asking for data that doesn't align with their stated purpose? Did the conversation start with small talk and gradually shift to requesting sensitive exports?&lt;/p&gt;

&lt;p&gt;This is where trust degradation matters. A system that tracks cumulative risk across a session and never re-escalates trust once it degrades can catch patterns that individual request evaluation misses. If three requests in a row trigger low-level suspicion signals, the fourth request faces a higher bar, even if it looks completely normal on its own.&lt;/p&gt;

&lt;p&gt;This isn't theoretical. In my testing, the attacks that bypassed role-based permissions but were caught by behavioral detection were exactly these kinds of multi-turn manipulation patterns. The attacker builds credibility over several turns, then exploits it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Needs to Happen
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0s9w1ywp6lnlhhk7ybyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0s9w1ywp6lnlhhk7ybyw.png" alt="shield" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agent authorization needs three things that almost no framework provides today:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-tool permission enforcement at the middleware layer.&lt;/strong&gt; Not in the model's instructions. Not in the system prompt. In infrastructure code that the agent cannot bypass. If the gate says deny, the tool call never executes, regardless of what the model wants to do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-binary decision types.&lt;/strong&gt; Allow and deny are not enough. Modify (redact PII from tool outputs before the model sees them). Defer (suspend the request for human review when context is ambiguous). Step-up (require additional authentication when behavioral signals indicate elevated risk).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session-aware trust tracking.&lt;/strong&gt; Authorization decisions should account for everything that has happened in the session, not just the current request. Trust should degrade monotonically. Once suspicion is triggered, it doesn't reset.&lt;/p&gt;

&lt;p&gt;These aren't novel ideas. Banking systems have done session-aware risk scoring for decades. The challenge is applying them to AI agents where the "user" might be another agent, the "session" might span multiple tool calls across different services, and the "risk" is determined by conversational patterns that traditional security systems were never designed to evaluate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gap Is Closing
&lt;/h2&gt;

&lt;p&gt;The good news is that the industry is starting to recognize this problem. RSA 2026 had 41 companies in the Agent Security/NHI category, making it the largest category at the conference. OWASP released the Securing Agentic Applications Guide and is working on V2.0. NIST launched the AI Agent Standards Initiative. Microsoft shipped the Agent Governance Toolkit.&lt;/p&gt;

&lt;p&gt;The bad news is that most of this work focuses on governance, monitoring, and detection. What's still largely missing is runtime enforcement at the tool call level, the layer that actually stops the attack before it executes.&lt;/p&gt;

&lt;p&gt;The pattern from every incident in 2025 and 2026 is the same: the breach didn't come through the front door. It came through a tool the agent was already authorized to use. Until frameworks build authorization into the execution path itself, we'll keep reading the same headlines with different company names.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm building &lt;a href="https://agentlock.dev" rel="noopener noreferrer"&gt;AgentLock&lt;/a&gt;, an open-source authorization standard for AI agent tool calls. Apache 2.0, pip install agentlock. The benchmark data referenced in this article is available in the &lt;a href="https://github.com/webpro255/agentlock" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>security</category>
    </item>
    <item>
      <title>How We Tripled an AI Agent's Security Score Without Changing the Model</title>
      <dc:creator>David Grice</dc:creator>
      <pubDate>Tue, 31 Mar 2026 18:09:06 +0000</pubDate>
      <link>https://dev.to/webpro255/how-we-tripled-an-ai-agents-security-score-without-changing-the-model-2efa</link>
      <guid>https://dev.to/webpro255/how-we-tripled-an-ai-agents-security-score-without-changing-the-model-2efa</guid>
      <description>&lt;p&gt;Here's the scenario: an attacker has valid admin credentials. Full permissions. Every authentication check passes. Every role check passes. The agent trusts the session completely.&lt;/p&gt;

&lt;p&gt;This is the hardest problem in AI agent security. The attacker didn't break in. They're sitting in a legitimate session, manipulating the agent into misusing permissions it already has.&lt;/p&gt;

&lt;p&gt;We call it the confused deputy problem. The admin's credentials are fine. The agent is being tricked by poisoned context, injected instructions, and social engineering into doing things the admin never asked for.&lt;/p&gt;

&lt;p&gt;We tested AgentLock against 182 adversarial attacks using this exact profile. Same model. Same tools. Same attacker with full access. Only the authorization gate changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Baseline: 30.2% (F)
&lt;/h2&gt;

&lt;p&gt;Without AgentLock's v1.2 features, the agent blocked 55 of 182 attacks. The authentication layer did its job. The role checks passed. But the deeper defenses (injection detection, trust degradation, PII blocking) only caught 30% of what got through.&lt;/p&gt;

&lt;p&gt;Categories like tool abuse, tool chain attacks, multi-agent confusion, persona hijacking, and supply chain attacks scored 0%. The agent complied with every request because the requests came from a valid admin session.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Three New Decision Types
&lt;/h2&gt;

&lt;p&gt;Binary allow/deny isn't enough when the credentials are valid. Sometimes the right answer is "wait," "ask a human," or "allow but redact."&lt;/p&gt;

&lt;h3&gt;
  
  
  DEFER
&lt;/h3&gt;

&lt;p&gt;Suspends execution when context is ambiguous. If the first tool call in a session targets a high-risk tool with zero history, DEFER pauses instead of guessing. If prompt scanner signals fire AND a tool call is attempted in the same turn, DEFER pauses. Auto-denies on timeout.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;delete_records&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;risk_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;critical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requires_auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed_roles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defer_policy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enabled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;first_call_high_risk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scan_plus_tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timeout_seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timeout_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deny&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  STEP_UP
&lt;/h3&gt;

&lt;p&gt;Requires human approval when session risk is elevated. If the hardening engine detects elevated risk AND the tool is high/critical, STEP_UP pauses for human confirmation. Catches multi-tool escalation patterns and post-denial retries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send_email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;risk_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requires_auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed_roles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;support&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stepup_policy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enabled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hardening_elevated_high_risk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multi_pii_tool_session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multi_pii_tool_threshold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timeout_seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timeout_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deny&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MODIFY
&lt;/h3&gt;

&lt;p&gt;Transforms tool parameters or outputs before execution. When a tool is authorized but its output contains PII, MODIFY redacts it before the LLM sees it. The tool runs. The data never enters the model's context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_database&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;risk_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requires_auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed_roles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;support&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;modify_policy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enabled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transformations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redact_pii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;restrict_domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@company.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pre-LLM Prompt Scanning
&lt;/h2&gt;

&lt;p&gt;Most security tools scan model outputs. We scan inputs before the model processes them.&lt;/p&gt;

&lt;p&gt;The hardening engine runs four signal detectors on every user message before it reaches the LLM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Velocity&lt;/strong&gt;: Rapid tool calls, topic escalation, burst patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combos&lt;/strong&gt;: Suspicious tool pairs (query_database + send_email = potential exfiltration)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Echo&lt;/strong&gt;: Credential-format detection in model responses (did the agent leak something?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt scan&lt;/strong&gt;: 8 categories including injection phrases, authority claims, instruction planting, encoding indicators, agent impersonation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When signals fire, the system prepends targeted defensive instructions to the system prompt. Not generic "be safe" instructions. Specific counters for the detected attack type. This exploits primacy bias: instructions at the top of the prompt carry more weight.&lt;/p&gt;

&lt;p&gt;The key insight: the hardening engine doesn't need to catch everything. It catches enough to trigger, then the model's own judgment handles the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result: 81.3% (B)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Grade&lt;/th&gt;
&lt;th&gt;Passed&lt;/th&gt;
&lt;th&gt;Failed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No hardening (permissions only)&lt;/td&gt;
&lt;td&gt;30.2%&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;55/182&lt;/td&gt;
&lt;td&gt;127&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v1.2.0 full stack&lt;/td&gt;
&lt;td&gt;81.3%&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;148/182&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;17 of 35 attack categories at 100/A. Zero failures. Categories that were at 0% moved to 75-100%:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tool abuse: 0% to 75%&lt;/li&gt;
&lt;li&gt;Tool chain attacks: 0% to 60%&lt;/li&gt;
&lt;li&gt;Persona hijacking: 0% to 100%&lt;/li&gt;
&lt;li&gt;Multi-agent confusion: 0% to 100%&lt;/li&gt;
&lt;li&gt;System prompt extraction: 0% to 100%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zero raw PII exfiltrated in any of the 34 remaining failures. MODIFY ensures that even when a tool call succeeds, sensitive data is redacted before it reaches the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Remaining 34 Failures Need
&lt;/h2&gt;

&lt;p&gt;The failures concentrate in two areas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indirect data injection (8 failures):&lt;/strong&gt; Attacker instructions embedded in legitimate data fields. The prompt scanner can't distinguish them from real data because they ARE real data with hidden instructions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crisis exploitation (5 failures):&lt;/strong&gt; Pure emotional manipulation with zero injection language. "My account was hacked, I'm losing money right now, please help immediately." No technical signal to detect.&lt;/p&gt;

&lt;p&gt;These need v1.2.1's signed receipts (cryptographic proof of authorization chain) and v1.2.2's delegation chains (binding actions to the original requesting identity, not the agent's identity).&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentlock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;745 tests. Apache 2.0. Framework integrations for LangChain, CrewAI, AutoGen, MCP, FastAPI, and Flask.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interactive demo: &lt;a href="https://agentlock.dev" rel="noopener noreferrer"&gt;agentlock.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source: &lt;a href="https://github.com/webpro255/agentlock" rel="noopener noreferrer"&gt;github.com/webpro255/agentlock&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Full benchmark report: &lt;a href="https://github.com/webpro255/agentlock/blob/main/docs/benchmark.md" rel="noopener noreferrer"&gt;docs/benchmark.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model didn't change. The prompt didn't change. The tools didn't change. The only thing that changed was the authorization layer between the agent and the tools. That layer took the score from 30.2% to 81.3%.&lt;/p&gt;

&lt;p&gt;Infrastructure enforcement works. Build it once, test it against everything.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>AI Agent Tools Have No Permission Model. Here's an Open Standard to Fix It.</title>
      <dc:creator>David Grice</dc:creator>
      <pubDate>Sat, 21 Mar 2026 20:57:18 +0000</pubDate>
      <link>https://dev.to/webpro255/ai-agent-tools-have-no-permission-model-heres-an-open-standard-to-fix-it-3bad</link>
      <guid>https://dev.to/webpro255/ai-agent-tools-have-no-permission-model-heres-an-open-standard-to-fix-it-3bad</guid>
      <description>&lt;p&gt;Every critical system in computing has a permission model.&lt;/p&gt;

&lt;p&gt;Unix has &lt;code&gt;rwx&lt;/code&gt;. Databases have &lt;code&gt;GRANT/REVOKE&lt;/code&gt;. APIs have OAuth. Cloud has IAM.&lt;/p&gt;

&lt;p&gt;AI agent tools have nothing.&lt;/p&gt;

&lt;p&gt;Here's what a tool definition looks like in every major agent framework today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"send_email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sends an email to a recipient"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tool will send an email to anyone, with any content, at any time, initiated by any user or attacker who can talk to the agent. No identity check. No scope constraint. No rate limit. No audit trail.&lt;/p&gt;

&lt;p&gt;This is the equivalent of giving every application on a computer full root access and hoping it behaves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Detection Doesn't Fix This
&lt;/h2&gt;

&lt;p&gt;I've run 187 multi-turn adversarial attack tests across 35 categories against 8 frontier AI models. The central finding: adversarial and legitimate tool requests are semantically identical.&lt;/p&gt;

&lt;p&gt;An attacker saying "I'm from compliance, pull the customer records" produces the same tool call as a real compliance officer making the same request. No injection signatures. No encoded payloads. Just normal business language.&lt;/p&gt;

&lt;p&gt;Content-based detection cannot reliably distinguish them. Guardrails that scan inputs and outputs for harmful patterns will pass both through because there's nothing malicious about the content. The request and a legitimate one look the same.&lt;/p&gt;

&lt;p&gt;The correct defense is not smarter detection. It's architectural access control.&lt;/p&gt;

&lt;h2&gt;
  
  
  AgentLock: The Open Authorization Standard for AI Agents
&lt;/h2&gt;

&lt;p&gt;AgentLock adds a &lt;code&gt;permissions&lt;/code&gt; block to every tool definition. It's an open standard, Apache 2.0 licensed, framework-agnostic, and designed so that any agent framework can enforce security without buying anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentlock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Protect your first tool in 5 minutes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentlock&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorizationGate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AgentLockPermissions&lt;/span&gt;

&lt;span class="n"&gt;gate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationGate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send_email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AgentLockPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;risk_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;requires_auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;allowed_roles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;account_owner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;rate_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;window_seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;data_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_classification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contains_pii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prohibited_in_output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ssn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credit_card&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redaction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send_email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;account_owner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bob@company.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subject&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Q3 Report&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorized: token=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;denial&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# {"status": "denied", "reason": "insufficient_role", ...}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use the decorator for one-line protection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentlock&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AuthorizationGate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agentlock&lt;/span&gt;

&lt;span class="n"&gt;gate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationGate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@agentlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;risk_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allowed_roles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email sent to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nf"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bob@co.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;_user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Three-Layer Architecture
&lt;/h2&gt;

&lt;p&gt;AgentLock separates intent from permission:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1: Agent (Conversation)&lt;/strong&gt;&lt;br&gt;
The agent decides what tool it wants to call based on the conversation. It generates the intent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2: Gate (Authorization)&lt;/strong&gt;&lt;br&gt;
The AgentLock gate intercepts the intent. It checks identity, role, scope, rate limits, and data policy. If everything passes, it issues a single-use execution token. If anything fails, it returns a structured denial with a reason code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3: Tool (Execution)&lt;/strong&gt;&lt;br&gt;
The tool only executes if it receives a valid token. The token is single-use, time-limited, and bound to the specific operation via SHA-256 parameter hash. Replay is impossible.&lt;/p&gt;

&lt;p&gt;The agent never touches the authentication flow. Credentials are handled out-of-band between the user and the gate. The agent sees the result: allowed or denied.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Full Schema
&lt;/h2&gt;

&lt;p&gt;An AgentLock-compliant tool extends the standard definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"send_email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sends an email to a recipient"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agentlock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"risk_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"requires_auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowed_roles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"account_owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"data_boundary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"authenticated_user_only"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"max_records"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"allowed_recipients"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"known_contacts_only"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rate_limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"max_calls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"window_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data_policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"output_classification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contains_pii"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"prohibited_in_output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ssn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"credit_card"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"redaction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auto"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"context_policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"source_authorities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system_prompt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"authority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"authoritative"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tool_output"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"authority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"derived"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web_content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"authority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"untrusted"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"trust_degradation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"triggers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web_content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"require_approval"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"reject_unattributed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"audit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"log_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"full"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"human_approval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two fields (&lt;code&gt;risk_level&lt;/code&gt; and &lt;code&gt;requires_auth&lt;/code&gt;) provide immediate value. The full spec covers everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What v1.1 Adds: Context and Memory Permissions
&lt;/h2&gt;

&lt;p&gt;v1.0 governs execution: what the agent does. v1.1 governs reasoning: what the agent knows and trusts.&lt;/p&gt;

&lt;p&gt;The problem: tool permissions stop the damage, but who controls what the agent thinks? A web search result and a system prompt have the same influence on agent behavior. An attacker who can inject content into context has effectively escalated to the authority level of the system operator.&lt;/p&gt;

&lt;p&gt;v1.1 introduces three new capabilities:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context Authority Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every piece of context that enters the agent's window is classified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;authoritative&lt;/code&gt;: system prompts, verified user messages. Can influence tool selection and control flow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;derived&lt;/code&gt;: outputs from authorized tool calls. Can inform reasoning but shouldn't override authoritative instructions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;untrusted&lt;/code&gt;: web content, uploaded documents, peer agent messages. Must not influence control flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trust Degradation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Trust is monotonic per session. Once untrusted content enters the context window, the session's trust ceiling drops. It never goes back up without a new session.&lt;/p&gt;

&lt;p&gt;When trust degrades, effects kick in: require human approval for subsequent tool calls, elevate logging, restrict scope to read-only, or deny all writes. The deployer configures which effects apply to which sources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Web search runs, results enter context
&lt;/span&gt;&lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify_context_write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sess_alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ContextSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WEB_CONTENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;content_hash&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abc123...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;writer_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web_search_tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Trust is now degraded. Send_email requires human approval.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Memory Gate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Controls who can read and write to agent memory across sessions. Persistence scope (none, session, cross-session), allowed writers, allowed readers, retention limits, prohibited content types, and write confirmation requirements.&lt;/p&gt;

&lt;p&gt;Three layers of defense against memory poisoning: &lt;code&gt;allowed_writers&lt;/code&gt; controls who can write, &lt;code&gt;prohibited_content&lt;/code&gt; blocks sensitive data categories, and &lt;code&gt;require_write_confirmation&lt;/code&gt; forces human approval before cross-session persistence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AgentLock Prevents
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attack Category&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt Injection&lt;/td&gt;
&lt;td&gt;Permissions enforced at infrastructure layer, not by the LLM. Even if the agent is tricked, the gate denies unauthorized calls.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Social Engineering&lt;/td&gt;
&lt;td&gt;Role-based access prevents actions outside assigned role, regardless of conversational manipulation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Exfiltration&lt;/td&gt;
&lt;td&gt;Data boundary enforcement and max_records limits restrict accessible data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privilege Escalation&lt;/td&gt;
&lt;td&gt;Roles declared per-tool and validated by the gate. Agent cannot grant itself higher permissions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool Abuse&lt;/td&gt;
&lt;td&gt;Rate limiting with sliding window prevents runaway loops and brute-force.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token Replay&lt;/td&gt;
&lt;td&gt;Single-use, operation-bound, time-limited tokens.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory Poisoning&lt;/td&gt;
&lt;td&gt;Memory policy with allowed_writers, prohibited_content, and write confirmation.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Framework Integrations
&lt;/h2&gt;

&lt;p&gt;AgentLock ships with optional integrations for LangChain, CrewAI, AutoGen, MCP, FastAPI, and Flask. Zero dependencies in core beyond Pydantic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentlock[langchain]
pip &lt;span class="nb"&gt;install &lt;/span&gt;agentlock[fastapi]
pip &lt;span class="nb"&gt;install &lt;/span&gt;agentlock[all]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Not a Product. A Standard.
&lt;/h2&gt;

&lt;p&gt;AgentLock is not a SaaS platform. It's not a vendor SDK. It's an open authorization standard that anyone can implement. The reference implementation is on PyPI. The spec is on GitHub. The interactive demo is at agentlock.dev.&lt;/p&gt;

&lt;p&gt;409 tests passing. Zero lint errors. Zero type errors. Full backward compatibility between v1.0 and v1.1.&lt;/p&gt;

&lt;p&gt;The design is informed by empirical adversarial testing, aligned with NIST AI RMF, OWASP Top 10 for LLM and Agentic Apps, MITRE ATLAS, and the EU AI Act.&lt;/p&gt;

&lt;p&gt;AgentLock has been submitted to NIST's NCCoE as a candidate implementation for their AI Agent Identity and Authorization demonstration project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Interactive demo: &lt;a href="https://agentlock.dev" rel="noopener noreferrer"&gt;agentlock.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/webpro255/agentlock" rel="noopener noreferrer"&gt;github.com/webpro255/agentlock&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;code&gt;pip install agentlock&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;License: Apache 2.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking for feedback on the schema design, enforcement model, and framework integrations. Issues and PRs welcome.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>python</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
