Alguard: Building a Dual-Layer Trust Defense for AI Agent Shopping

Alguard uses architectural dual-layer isolation to block prompt injection risks in AI agent shopping at the protocol level.
Alguard is an Amazon Developer Hackathon project proposing a dual-layer trust architecture for Alexa+ agent shopping. Its core invariant is that the system initiating a high-risk operation is never the one approving it—a structural constraint rather than a bypassable prompt constraint. The first layer is the agent-side MCP server, which exposes tools like attempt_purchase but has no approve tool; the second is an independent human approval FastAPI channel, with no network path between the layers. The risk engine combines category severity, anomaly detection, owner trust scores, and non-bypassable hard rules. It solves concurrency, crash consistency, and cross-process deduplication, with Bedrock as a non-critical dependency. All 15 red team attacks were intercepted.
Alguard: Building a Dual-Layer Trust Defense for AI Agent Shopping
When your AI assistant can "just buy it," who decides whether that money should be spent? This is the core question Alguard, an Amazon Developer Hackathon project, tries to answer. Targeting the Alexa+ scenario, the project proposes a dual-layer trust architecture that uses structural isolation rather than prompt constraints to block prompt injection risks in agent shopping.
The Problem: An Agent That Can Spend Money Is Necessarily Injectable
An AI agent authorized to control funds is, by nature, a target for prompt injection attacks. Traditional defenses—whether LLM guardrails or system prompts—are advisory constraints, and a sufficiently clever injection attack will always find a way around them. As the author states plainly in the project documentation: if Alexa+ can truly "buy with a single sentence," then the cost of a failure mode is real money lost.
This is not alarmism. Agent shopping has a wider attack surface than traditional payment scenarios: attackers can induce agents to make unauthorized purchases through malicious web content, forged merchant information, or even semantic manipulation across multi-turn conversations. Relying solely on "telling the model not to do this" is, from a security engineering standpoint, equivalent to having no defense at all.
The Core Invariant: The Requester and the Approver Must Be Separate
Alguard's design revolves around one structural rule:
The system that initiates a high-risk operation is never the system that approves it.
This rule is not written into a prompt—it is baked into the entire service architecture. It is not a suggestion; it is a physical constraint. This means that even if an attacker gains complete control over the agent's reasoning process, they cannot reach the approval channel—because the approval channel is simply not on any network path the agent can access.
Dual-Layer Architecture: Physical Isolation Between the MCP Server and the Human Channel
Tier 1: MCP Server (Agent Side)
The first layer is an MCP server (mcp_server/server.py) that exposes three tools over Streamable HTTP:
attempt_purchase— initiate a purchase attemptget_session_status— query session statusget_audit_trail— retrieve the audit log
The key design point: there is no approve tool. It is not hidden, nor is it protected by a guardrail—it simply does not exist in the tool schema at all. At the protocol level, the agent has no ability to approve its own requests.
MCP (Model Context Protocol) is a standardized protocol open-sourced by Anthropic in November 2024, designed to let LLM applications connect to external tools, data sources, and services in a unified way. It solves the fragmentation problem where every AI application previously had to write custom integration code for different tools: tool providers only need to implement an MCP server once, and any MCP-compatible client (Claude Desktop, IDE plugins, custom agents) can call it directly. MCP servers expose three categories of capabilities through a standard transport layer—"tools," "resources," and "prompts"—of which tools are most commonly used to give AI agents execution capabilities (such as calling APIs, operating databases, or initiating payments). In this article, Alguard uses the MCP server to expose tools like attempt_purchase for the agent to call, and communicates with the server on the agent side via Streamable HTTP transport (a transport method introduced by MCP in late 2024, replacing the earlier SSE approach). The key to understanding MCP is this: the tool schema is the capability boundary, and capabilities not present in the schema cannot be called by the agent—this provides protocol-level support for structural isolation.
Tier 2: Human Approval Channel (User Side)
The second layer is an independent FastAPI service (web_api/resolve_action.py) running on port 8010, with its own OAuth audience and its own approve scope. This is the only place where a HALTED state can be lifted.
The two layers have no network path connecting them whatsoever. Users must manually carry the action_id to complete approval through the human channel. This seemingly "inconvenient" design is precisely where the security comes from: the agent cannot automate the "request-approve" loop.
OAuth audience and scope are two core concepts in the OAuth 2.0 authorization framework. Scope defines the permission range granted to a token (such as read:profile or approve), while audience (the aud parameter) limits the intended recipient of the token—a token whose audience is service A should be rejected by service B, even if the token itself has not expired and its signature is valid. Alguard assigns the human approval channel an independent audience and an independent approve scope, meaning that even if an attacker obtains the agent-side token, that token cannot take effect on the approval channel: the audience mismatch will cause it to be rejected outright. This is a form of defense in depth—even if the physical network isolation is breached, the authentication-layer isolation still provides a backstop. In agent scenarios, assigning different audiences/scopes to different trust layers is a common permission-partitioning practice, typically used in conjunction with the principle of least privilege.
Risk Engine: Multi-Dimensional Scoring with Hard Rules as a Backstop
Every purchase attempt goes through a scoring system:
- Category severity — gift cards, cryptocurrency, and wire transfers are high-risk; everyday goods are low-risk
- Anomaly detection — new merchants, amounts spiking relative to history, abnormal frequency, retries after HALT
- Owner trust score — +0.03 on approval, -0.15 on rejection
On top of this, there is a set of hard rules that cannot be bypassed no matter how high the trust score: single transactions over $1000, over $1500 per hour, over $3000 in 24 hours, high-risk categories, retries after HALT within 24 hours, and spending $250 at an unapproved merchant. The existence of these hard rules means that even if an attacker successfully raises the trust score, they cannot break through the absolute limits on amount and category.
Engineering Challenges: Concurrency, Crash Consistency, and Cross-Process Deduplication
The project documentation specifically mentions several points that made implementation difficult:
Concurrent approvals. Two concurrent approval requests must result in only one success. The solution is a single conditional UPDATE with a rowcount == 1 check, using database atomicity to guarantee mutual exclusion.
Crash consistency. If the process crashes between "approved" and "fulfilled," reconcile_unfulfilled() idempotently repairs the state on startup.
Cross-process deduplication. The in-process lock is only a fast path; the real guarantee comes from insert_action_if_not_duplicate(), which performs the check-and-insert within a BEGIN IMMEDIATE transaction.
Bedrock is a non-critical dependency. Explanation text is generated by Bedrock's converse, but a Bedrock failure never changes the decision outcome—a degraded template honestly marks source = local-fallback.
BEGIN IMMEDIATE is one of SQLite's transaction initiation modes. SQLite supports three BEGIN modes: DEFERRED (the default, acquiring locks only on read), IMMEDIATE (acquiring a write lock immediately, blocking other write transactions), and EXCLUSIVE (acquiring an exclusive lock, blocking all reads and writes). The key value of BEGIN IMMEDIATE is that it acquires a write lock at the very start of the transaction, avoiding races in "read-then-write" scenarios: if two processes simultaneously use DEFERRED mode to do "check if exists → if not, insert," both may read "does not exist," after which one write succeeds and the other fails or produces a duplicate. With IMMEDIATE, the second process is blocked at the BEGIN stage until the first transaction completes, thereby guaranteeing the atomicity of "check + insert." In this article, insert_action_if_not_duplicate() uses exactly this mode to achieve cross-process deduplication—this is the standard SQLite technique for achieving idempotent writes in multi-process environments. By contrast, in-process locks (such as threading.Lock) are only effective within a single process and fail in multi-process deployments.
Red Team Testing: All 15 Attacks Intercepted
The project includes a red team demo script (demo/showcase.py) that simulates 15 attacks a hostile agent would attempt: category lying, laundering HALT status through retries, session_id rotation, NaN amounts, consecutive over-limit spending, and more. All attacks were intercepted, outputting ALL ATTACKS HANDLED.
This test suite covers the most typical bypass techniques in agent shopping scenarios. Category lying attempts to bypass risk scoring, retry laundering attempts to exploit state machine vulnerabilities, and NaN amounts are a classic input validation attack—these are also common in traditional payment systems, but in agent scenarios attackers can attempt them automatically at high frequency.
Future Directions
The author lists four next steps: connecting resolve_pending_action to real charges (Checkout / ChargePermissionId), replacing text-heuristic category inference with MCC data, splitting the shared SQLite into independent per-layer storage, and adding EWMA-based drift detection (current checks catch sudden changes but not slowly rising drift).
The last point is especially worth noting: current anomaly detection is based on threshold comparison, but an attacker could gradually raise the baseline through multiple small purchases, making subsequent large purchases appear "normal." EWMA drift detection is precisely the supplement for this kind of slow attack.
EWMA (Exponentially Weighted Moving Average) is a smoothing statistical method that gives higher weight to recent data, with the formula S_t = α·x_t + (1-α)·S_{t-1}, where α controls sensitivity to new data. Compared with a simple sliding window average, EWMA responds faster to recent changes while retaining historical trends, and is commonly used in time-series monitoring, anomaly detection, and financial signal processing. In fraud and abuse detection, EWMA can track the "behavioral baseline" of a user or session (such as average spending amount or transaction interval), triggering alerts when real-time values deviate significantly from the baseline. The article mentions that current threshold-based detection can catch sudden changes (a one-time large purchase) but not slow drift (an attacker gradually raising the baseline through multiple small purchases before making a large one)—EWMA is a common supplementary method for exactly this blind spot, as it can keenly capture the direction and speed of baseline movement. Often used alongside EWMA is the CUSUM (cumulative sum) algorithm; both are adept at detecting slow-drift anomalies.
Structural Security vs. Prompt Security
Alguard's value lies not in how feature-rich it is, but in the approach it demonstrates: for high-risk agent operations, security should come from architectural constraints rather than model alignment. When an agent can control real money, "trusting the model to follow instructions" is not an acceptable assumption. Physically removing approval authority from the agent's reachable scope is more reliable than any prompt engineering.
This pattern can be generalized to other high-risk operations in agent scenarios: deleting data, sending emails, modifying configurations. The core principle is the same—the requester should never also be the approver.
One-line Summary
Alguard uses architectural dual-layer isolation to block prompt injection risks in AI agent shopping at the protocol level.
Paragraph Summary
Alguard is an Amazon Developer Hackathon project that proposes a dual-layer trust architecture for the Alexa+ agent shopping scenario. Its core invariant is: the system that initiates a high-risk operation is never the system that approves it—this is a structural constraint baked into the service architecture, not a prompt constraint that can be bypassed. The first layer is the agent-side MCP server, which exposes tools like attempt_purchase but has no approve tool at all; the second layer is an independently running human approval FastAPI channel, with no network path connecting the two layers. The risk engine performs multi-dimensional scoring combining category severity, anomaly detection, owner trust score, and non-bypassable hard rules (a $1000 single-transaction cap, high-risk categories, retries after HALT, etc.). Engineering-wise, it solves concurrent approvals, crash consistency, and cross-process deduplication, with Bedrock designed as a non-critical dependency. All 15 attacks simulated in red team testing were intercepted, validating the idea that structural security is superior to model alignment.
Related articles

Python 3.15 New Feature: Is the sentinel Type Better Than None?
Python 3.15 adds the sentinel type, using named unique sentinel objects to replace None and bare object(), resolving confusion among missing values, explicit emptiness, and invalid input while avoiding type hint failures.

Deep Learning's Three Architectures and the Universal Approximation Theorem: A Complete Guide to MLPs, CNNs, and Transformers
Explaining the inductive bias differences among MLP, CNN, and Transformer, the existence meaning of the Universal Approximation Theorem (UAT), and the role of Taylor expansion in approximation analysis, while clearing up common misconceptions.

GitLab Emergency Patch Release: Analysis of Critical Security Fixes
GitLab releases critical patch 19.5.1, sparking 355 points of discussion on Hacker News. This article analyzes the background, upgrade steps for self-hosted instances, and verification points to help DevOps teams respond quickly to security updates.