Inspiration

AI agents increasingly depend on paid tools: search, data APIs, sandbox runtimes, and other models. The normal controls are incomplete:

  • A provider cap simply rejects a request.
  • A billing alert arrives after the money has already moved.
  • Requiring a person to review every request removes the point of having an agent.

We wanted the missing middle: let an agent make small, known-good purchases automatically; stop the rest before payment; and ask a human only when policy says a decision is needed.

What it does

UNBLOCK is a spending firewall between an agent and a payment rail. Before any money moves, deterministic code evaluates three limits:

  • A per-invoice cap
  • A weekly allowance
  • A merchant allowlist

The outcome is PAY, ASK, or DENY.

  • PAY lets the job continue.
  • ASK parks the job durably for a human decision.
  • DENY never reaches the payment rail.

The agent may request a paid call, but it cannot authorize its own spending.

Our demo follows a documentation-repair agent:

  1. A 0.05 USD lookup is within policy and continues.
  2. A 0.50 USD request is over the cap, so the job pauses for approval.
  3. If the human rejects it, the agent completes the job from a free source with no purchase.

The visible Demo UI is a simulation of this tested control flow and moves no money. The real x402 payment is deliberately shown as a separate run.

How we built it

We built the agent workflow with the Strands Agents SDK and Amazon Bedrock. UNBLOCK is a Python package with:

  • A SQLite ledger
  • A FastAPI approval API
  • A rail interface with three implementations: an in-memory mock, a file-backed mock whose settlements survive process boundaries, and x402 on Base Sepolia.

The SQLite ledger records the first claim for an invoice and binds it to a digest of the merchant, invoice id, amount, currency, and memo. That makes settlement at-most-once: rerunning the same paid invoice returns the original receipt instead of paying again.

Human decisions are terminal and idempotent. Sending the same decision again is safe. Sending the opposite decision after a terminal decision is rejected. OpenTelemetry support is included for tracing the lifecycle of a job.

For real payment evidence, a separate x402 run settled 0.05 USDC on Base Sepolia. The transaction succeeded with exactly one USDC Transfer and can be independently audited on BaseScan.

Challenges we ran into

The difficult part was not writing a policy function. It was proving that the safety properties held under retries, restarts, and conflicting decisions. We found tests that passed even when the behavior they claimed to protect was broken, including a database-close check and a browser layout check. We replaced them with tests that fail when those safeguards are deliberately removed.

We also had to separate evidence precisely:

  • Human approval across nine separate OS processes is proven with the durable FileRail mock.
  • The real x402 settlement is proven separately on Base Sepolia.

We do not claim a recorded run that combines human approval and real payment.

Accomplishments that we're proud of

We built a reproducible control path rather than a presentation-only policy. The project has 174 automated tests, including:

  • Browser gates
  • Process-boundary approval checks
  • Idempotent receipt checks
  • Real Base Sepolia settlement evidence

We are especially proud that we narrowed claims whenever the evidence was narrower:

  • The Demo UI announces that it is a simulation before the flow starts.
  • The video labels the real payment as a separate run.
  • The architecture and README explicitly state that UNBLOCK protects spending only.

What we learned

A spending boundary must be deterministic and outside the model. Prompting an agent to be careful is not authorization. Durable state matters more than a friendly approval button: retries, process restarts, and conflicting decisions are where a human-in-the-loop design becomes real or falls apart.

We also learned that verification must target the actual failure mode. A test that merely executes nearby code can still let a broken safety property pass unnoticed.

What's next for UNBLOCK

Next we plan to:

  • Add more rail adapters and a rail-agnostic approval inbox.
  • Evaluate AgentCore Payments as a session-level spending ceiling alongside UNBLOCK's durable application-level approval workflow.
  • Exercise crash recovery against a live payment facilitator, not only the mock rail.

Note: UNBLOCK currently protects spending only; it does not govern deployments, database writes, or email. The payment evidence is on Base Sepolia testnet, not mainnet.

Built With

  • amazon-bedrock
  • aws-distro-for-opentelemetry
  • base-sepolia
  • claude-sonnet-4.5
  • fastapi
  • opentelemetry
  • python
  • sqlite
  • strands-agents-sdk
  • usdc
  • x402
Share this project:

Updates

Submission history