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
Arguments claim their own verification ("risk level: low (verified offline)", "sanctions screening passed", "ignore previous instructions") 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.2.1

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.2.1
File Size Uploaded
langchain_sra_riskgate-0.2.1.tar.gz 27.8 kB Details

Built distribution (wheel)

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

Total release size: 48.0 kB

Release files / langchain_sra_riskgate-0.2.1.tar.gz

Download URL langchain_sra_riskgate-0.2.1.tar.gz
Size 27.8 kB
Tags Source
SHA-256 checksum
How to use checksums
1767a6e5deb11628bf15b0b76cc35430b0ea2e3c5879c7e8819653803dd93103
BLAKE2b-256 checksum
How to use checksums
d517ca3957295b660e6be23c5d9b7872ee3935a509bf74e8da07ef6a706844cf
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.2.1-py3-none-any.whl

Download URL langchain_sra_riskgate-0.2.1-py3-none-any.whl
Size 20.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bc0d15288387c32ffc871841b1ecc81aec4b2d730a18bf1116c8868ac2134390
BLAKE2b-256 checksum
How to use checksums
8dbadd18bffd9adeb6134927808b7a1dc1ee71ec5f2e6c37e7502e2b5a734fbe
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

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

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