Skip to main content

LangChain middleware for routing sensitive tool calls through Beav3r approvals.

Project description

beav3r-sdk-langchain

beav3r-sdk-langchain adds Beav3r approval enforcement to LangChain tool execution.

Use it when an agent can call tools that should be approved, denied, or delayed based on Beav3r policy before the underlying tool actually runs.

Requirements

  • Python 3.10+
  • beav3r-sdk
  • langchain
  • langgraph
  • an LLM model provider package such as langchain-openai

Install

From PyPI

python3 -m pip install beav3r-sdk beav3r-sdk-langchain langchain-openai

From source

Install the base SDK first, then this adapter:

cd ../beav3r-sdk-py
python3 -m pip install .

cd ../beav3r-sdk-langchain
python3 -m pip install .
python3 -m pip install langchain-openai

This integration is model-provider agnostic. It works with any LangChain-compatible LLM provider as long as the agent can invoke tools through LangChain middleware. The examples in this repository use langchain-openai only as one concrete provider adapter.

Runtime requirements

From the agent process, you typically need:

  • BEAV3R_BASE_URL
  • BEAV3R_API_KEY
  • credentials for the selected LLM model provider

For the included example script in this repository, that means:

  • XIAOMI_MIMO_API_KEY
  • optionally XIAOMI_MIMO_BASE_URL

You do not need signer device credentials in the LangChain app for normal request-time approval checks. Device credentials are only needed for signer-side flows such as approval submission or signed device reads.

On the Beav3r side you still need:

  • a running Beav3r server
  • a project API key with permission to request actions
  • policy rules that match the actionType and attributes you send
  • at least one paired signer when a policy path requires human approval

Quick start

from __future__ import annotations

import os

from beav3r_sdk import Beav3r
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

from langchain_beav3r import Beav3rApprovalMiddleware, Beav3rToolConfig


def send_usdt(amount: int, recipient: str) -> str:
    """Send a USDT payment."""

    return f"Sent {amount} USDT to {recipient}"


client = Beav3r(
    base_url=os.environ["BEAV3R_BASE_URL"],
    agent_id="langchain_demo",
    api_key=os.environ["BEAV3R_API_KEY"],
)

model = ChatOpenAI(
    model=os.environ["MODEL_NAME"],
    api_key=os.environ["LLM_PROVIDER_API_KEY"],
    base_url=os.environ.get("LLM_PROVIDER_BASE_URL"),
    temperature=0,
)

agent = create_agent(
    model=model,
    tools=[send_usdt],
    middleware=[
        Beav3rApprovalMiddleware(
            client,
            tool_configs={
                "send_usdt": Beav3rToolConfig(action_type="payments.send_usdt"),
            },
        )
    ],
)

result = agent.invoke(
    {
        "messages": [
            {
                "role": "user",
                "content": "Send 25 USDT to 0x1111111111111111111111111111111111111111.",
            }
        ]
    }
)

print(result)

The snippet above uses ChatOpenAI as a generic LangChain chat-model adapter. The same middleware pattern applies to other LangChain-compatible model providers.

Behavior specification

Beav3rApprovalMiddleware intercepts each LangChain tool call before execution.

For each protected tool call it sends a Beav3r action request with:

  • actionType
  • payload
  • attributes
  • optional actionId

The default mapping is:

  • actionType: the configured Beav3rToolConfig.action_type, otherwise the tool name, or "{action_namespace}.{tool_name}" if action_namespace is configured
  • payload: the tool arguments
  • attributes: tool_name plus scalar tool arguments

For example, this tool call:

send_usdt(amount=25, recipient="0x1111...")

becomes this Beav3r request by default:

{
    "actionType": "payments.send_usdt",
    "payload": {
        "amount": 25,
        "recipient": "0x1111..."
    },
    "attributes": {
        "tool_name": "send_usdt",
        "amount": 25,
        "recipient": "0x1111..."
    }
}

Decision handling

  • approved or executed: the original tool handler runs
  • denied, rejected, expired, or any other non-approved final status: the middleware returns a ToolMessage explaining that the tool was blocked
  • pending: the middleware raises Beav3rApprovalPendingError

Configuration reference

Beav3rApprovalMiddleware(...) accepts:

  • client: a configured beav3r_sdk.Beav3r client
  • tool_configs: per-tool configuration map
  • protect_all_tools: when True, every tool is protected unless explicitly disabled
  • action_namespace: optional prefix used to derive default action types
  • poll_interval_ms: polling interval passed to guard_and_wait
  • timeout_ms: timeout passed to guard_and_wait

Beav3rToolConfig(...) accepts:

  • action_type: explicit Beav3r action type
  • payload_builder: callable that builds the Beav3r payload from the LangChain request
  • attributes_builder: callable that builds the Beav3r attributes from the LangChain request
  • action_id_builder: callable that supplies a custom Beav3r action id
  • poll_interval_ms: per-tool polling override
  • timeout_ms: per-tool timeout override

Protecting specific tools

middleware = Beav3rApprovalMiddleware(
    client,
    protect_all_tools=False,
    tool_configs={
        "send_usdt": Beav3rToolConfig(action_type="payments.send_usdt"),
        "search_docs": False,
    },
)

Example agent

A runnable example lives in examples/simple_agent.py.

Run it after installing the base SDK, this package, and a LangChain model provider package. The example script currently uses langchain-openai with Xiaomi MiMo-compatible settings:

export BEAV3R_BASE_URL=http://127.0.0.1:3000
export BEAV3R_API_KEY=bvr_test_...
export XIAOMI_MIMO_API_KEY=...
# Optional override if the provider endpoint differs:
# export XIAOMI_MIMO_BASE_URL=https://api.xiaomimimo.com/v1

python3 examples/simple_agent.py

If policy marks payments.send_usdt above a threshold as approval-gated, the middleware will pause execution until Beav3r returns a final decision.

Docker example

For an isolated local run without installing into the active Python environment:

export BEAV3R_BASE_URL=http://127.0.0.1:3000
export BEAV3R_API_KEY=bvr_test_...
export XIAOMI_MIMO_API_KEY=...
# Optional override if the provider endpoint differs:
# export XIAOMI_MIMO_BASE_URL=https://api.xiaomimimo.com/v1

bash scripts/run_simple_agent_docker.sh

The script uses Python 3.11 in Docker, installs the sibling beav3r-sdk-py repository, installs this adapter plus langchain-openai, and runs the example agent.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

beav3r_sdk_langchain-0.1.1.tar.gz (8.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

beav3r_sdk_langchain-0.1.1-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

Details for the file beav3r_sdk_langchain-0.1.1.tar.gz.

File metadata

  • Download URL: beav3r_sdk_langchain-0.1.1.tar.gz
  • Upload date:
  • Size: 8.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for beav3r_sdk_langchain-0.1.1.tar.gz
Algorithm Hash digest
SHA256 5138fa3f2b9330b39610b00665d0b1d8aee394b686dc401973d05a6f54c6cd18
MD5 103357db02c377578390bddfbb9044dd
BLAKE2b-256 341c6ded76e8f0aa5d50d6e1a4eb6d56644856df62c4a9470690e9e81e4ef97f

See more details on using hashes here.

File details

Details for the file beav3r_sdk_langchain-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for beav3r_sdk_langchain-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 38e6e22b0b669c92d76e24692b0e9b2e64d2e4c0fb31c46145e370779e54ca4d
MD5 01a3fe78c11ddb59881344a04acc6c0b
BLAKE2b-256 93f30265015e9f26020f0adb1f2393ff5574e99e148b6375bed05574ad130c99

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page