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.0.tar.gz (8.3 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.0-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: beav3r_sdk_langchain-0.1.0.tar.gz
  • Upload date:
  • Size: 8.3 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.0.tar.gz
Algorithm Hash digest
SHA256 530eb4801645ff461be13208505ccd817aa971388fd4a4a6a95f5c05fd0f102b
MD5 b2cee37f0fbb977904ec4ac64cb6e7f8
BLAKE2b-256 8e37dd23814ac2e31323f105192287ead7f615e7b60c3ac0952e57306acd911a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for beav3r_sdk_langchain-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 28c67ec0fea215a55ff0b7e42e6619173543da3cc6ec86e5fbf4bbbab621dbf7
MD5 3bdf45fc24ddb2ed5f8fd33df7fcd93c
BLAKE2b-256 eeb7d88b41312b1d9e516069d5f8a1730b555e986a74632d31d90496d7bf0267

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