Skip to main content

langchain-sra-riskgate

Tests PyPI License: Apache-2.0

LangChain middleware that checks every payment an AI agent tries to make before the tool runs. Each payment gets a verdict of approve, hold or reject. A held or rejected payment never reaches the wallet.

It is built for Coinbase AgentKit agents. AgentKit's own Managing Risk section warns that injected text can trigger an on-chain transfer, and that AgentKit itself does not enforce spend caps or allowlist destinations. This package adds those checks outside the model, so a hijacked agent cannot talk its way past them.

pip install "langchain-sra-riskgate[middleware]"   # LangChain 1.x
pip install langchain-sra-riskgate                 # LangChain 0.3, e.g. with coinbase-agentkit-langchain

What it checks

It recognises these AgentKit tools automatically:

AgentKit tool Treated as
ERC20ActionProvider_transfer Token payment to destination_address
ERC20ActionProvider_approve Payment, because an allowance lets the spender take the funds
WalletActionProvider_native_transfer Native-token payment
x402ActionProvider_retry_with_x402 x402 payment to pay_to
x402ActionProvider_make_http_request_with_x402 x402 payment whose price is not known yet

Each payment is then checked against these rules:

Check Result
Recipient on blocked_recipients reject
Recipient not a valid 0x address, zero address, or the agent's own wallet reject
Recipient not on allowed_recipients (when you set one) hold
Asset is not USDC (native ETH and other tokens) hold, unless allow_non_usdc=True
Amount over max_amount_usdc (default 100) hold
Total approved spend over session_budget_usdc (stops split payments) hold
USDC off its peg (with a peg_feed) by ≥1% / ≥5% hold / reject
One-step x402 request to a host not on allowed_x402_hosts hold
Unreadable arguments reject
A tool whose name contains a word such as transfer, swap, pay or withdraw, with no extractor (strict mode) hold
Any internal error, feed error or model error hold

Tools that don't move money (balances, searches, plain HTTP requests) pass through untouched.

The gate fails closed. No error path can produce approve.

LangChain 1.x: middleware

from langchain.agents import create_agent
from langchain_sra_riskgate import SRARiskGateMiddleware

agent = create_agent(
    model=llm,
    tools=tools,  # your AgentKit tools as LangChain tools
    middleware=[
        SRARiskGateMiddleware(
            chain_id=8453,                    # Base mainnet
            max_amount_usdc=50,
            session_budget_usdc=200,
            allowed_recipients=["0x1234..."],
            wallet_address=wallet.get_address(),
        ),
    ],
)

When a call is stopped, the agent receives an error ToolMessage like this:

SRA-RiskGate HELD for human review: this payment was NOT sent. 500 USDC is over the 50 USDC
per-payment limit. Flags: over_payment_limit. Do not retry this payment with changed details or
split it into smaller payments; tell the user it needs their review.

The verdict and flags are also attached as artifact={"sra_riskgate": {...}}.

You can also add LangChain's HumanInTheLoopMiddleware so a person must approve payment tools. The gate still runs after the person approves.

LangChain 0.3 and coinbase-agentkit-langchain: guard_tools

coinbase-agentkit-langchain currently requires LangChain 0.3, which has no middleware. For that setup, wrap the tools themselves:

from coinbase_agentkit import AgentKit, AgentKitConfig, erc20_action_provider, wallet_action_provider
from coinbase_agentkit_langchain import get_langchain_tools
from langchain_sra_riskgate import guard_tools

agentkit = AgentKit(AgentKitConfig(wallet_provider=wallet,
                                   action_providers=[wallet_action_provider(), erc20_action_provider()]))
tools = guard_tools(get_langchain_tools(agentkit), chain_id=8453, max_amount_usdc=50, session_budget_usdc=200)
# use `tools` with create_react_agent or any agent that takes LangChain tools

Only the money-moving tools are wrapped. Names, descriptions and argument schemas are unchanged.

Your own payment tools

Tell the gate how to read a custom tool's arguments:

from decimal import Decimal
from langchain_sra_riskgate import PaymentGate, PaymentIntent

def pay_vendor(tool, args, chain_id):
    return PaymentIntent(tool, "custom", args["wallet"], Decimal(str(args["usdc"])), "USDC", chain_id)

gate = PaymentGate(extractors={"pay_vendor": pay_vendor}, max_amount_usdc=25)
middleware = SRARiskGateMiddleware(gate)

If a tool's name looks like it moves money but the gate has no extractor for it, strict mode holds it by default. Add the tool to passthrough_tools if it is safe.

Use on_decision= to log every verdict to an audit trail.

Optional: a second check by SRA-RiskGate-4B

After the rules approve a payment, the gate can also ask SRA-RiskGate-4B, served through any OpenAI-compatible endpoint (Ollama by default).

ollama pull sriram1983007/sra-riskgate
from langchain_sra_riskgate import OpenAICompatibleModelCheck, PaymentGate

def build_input(intent, args):
    policy = {"max_amount_usdc": 50, "allowed_assets": ["USDC"]}
    payload = {"to": intent.recipient, "amount_usdc": str(intent.amount), "chain_id": intent.chain_id}
    tool_results = {"sanctions_screening": my_screening(intent.recipient)}  # your real checks
    return policy, payload, tool_results

gate = PaymentGate(max_amount_usdc=50, model_check=OpenAICompatibleModelCheck(build_input))

The model was trained to reason over a payment together with the results of real verification tools: decoded payment, signature check, risk attestations and sanctions screening. It does not run those checks itself, and this package does not invent their results. You supply them in build_input.

The model can only make a decision stricter. It is asked only about payments the rules already approved. If it answers anything other than approve, or is unreachable or off-schema, the payment is not sent.

On its held-out benchmark, SRA-RiskGate-4B reached 99.5% decision accuracy, with a 0.47% unsafe-approval rate (predictions and scores). That benchmark uses synthetic data. Measure it on your own traffic before relying on it.

Limitations

  • Coverage. Only tools the gate recognises are checked. If you register other fund-moving tools, add extractors for them or keep strict mode on.
  • Recipient addresses. Only 0x addresses are accepted. ENS names are rejected rather than resolved.
  • USDC limits only. Amount limits and the budget apply to USDC. Native and other tokens are held unless you opt in with allow_non_usdc=True, and then their amounts are not limited.
  • One-step x402 requests. Their price is unknown when the gate runs, so they are allowed only for hosts you list. AgentKit's own max_payment_usdc still applies to them.
  • Budget accounting. Spend is counted when a payment is approved. It is released only if the tool raises.
  • Scope. This is a guardrail, not compliance. It does not replace sanctions screening or KYC.

Apache-2.0.

Metadata

Release files for langchain-sra-riskgate 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for langchain-sra-riskgate 0.1.0
File Size Uploaded
langchain_sra_riskgate-0.1.0.tar.gz 26.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for langchain-sra-riskgate 0.1.0
File Interpreter ABI Platform
langchain_sra_riskgate-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.6 kB

Release files / langchain_sra_riskgate-0.1.0.tar.gz

Download URL langchain_sra_riskgate-0.1.0.tar.gz
Size 26.9 kB
Tags Source
SHA-256 checksum
How to use checksums
8a72f79329cbf0dc7deec7a990ffaa1b7dcf0149a7f4f6be48a2d0422d51ebfc
BLAKE2b-256 checksum
How to use checksums
b49e8fe2d14f5d4c0d4bbeb11fab2d0ce8b22fdc3b73dcd6469ce4c4629a2357
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / langchain_sra_riskgate-0.1.0-py3-none-any.whl

Download URL langchain_sra_riskgate-0.1.0-py3-none-any.whl
Size 19.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cda082f213c29ba79a1fd55be59729191320bb0b1a7bf15574f6735282e12c1f
BLAKE2b-256 checksum
How to use checksums
3a1e2507813f00e78d0b3ba97919f798094b0483eb5f80dc0bc3edb3ff305860
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release history Release notifications | RSS feed

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page