Enforce what your agents can do.
See everything they did.

Scopebound sits inside your agent framework and intercepts every tool call before it executes. OPA policies, scoped JWTs, <5ms enforcement, tamper-evident audit log.

Get in touch See the integration

Works with the frameworks you already use

LangChain · OpenAI Assistants · CrewAI · AutoGen · Semantic Kernel · Claude Agent SDK

The problem

Your agents have no enforcement layer

Every major framework ships with zero enforcement between the LLM's decision and the tool's execution. When an agent decides to call a tool, nothing checks whether it's allowed.

🚫

No policy enforcement

When an agent calls a tool, it executes immediately. There's no check that the agent is allowed to call that tool — trust is implicit.

🔍

No audit trail

You have no tamper-evident record of what your agents actually called. If something goes wrong, you find out in the next reconciliation run.

No drift detection

If a compromised agent starts behaving anomalously — rapid external calls, unusual patterns — nothing detects or stops it.

🔧

Scattered enforcement logic

Teams add guards inside each tool's implementation. That logic is scattered, inconsistent, and doesn't survive framework migrations.


How it works

Enforcement inside the execution loop

Scopebound sits between the LLM's decision and the tool's execution — the only point where enforcement is both reliable and sub-millisecond.

1

LLM decides to call a tool

Your agent runs normally. The LLM produces a tool call decision as part of its reasoning loop.

2

Scopebound intercepts (<5ms)

The @enforce decorator intercepts the call before _run() is invoked. OPA evaluates your Rego policy against the agent's scoped JWT.

3

Allow or deny — with full audit

Allowed calls execute normally. Denied calls raise ScopeboundDenyError before the tool runs. Every decision is written to the tamper-evident audit log.

Without Scopebound

  • Tool calls execute immediately with no policy check
  • No record of what the agent actually called
  • Compromised agents run unchecked until you notice
  • Enforcement logic scattered across every tool
  • Framework migration breaks all your security logic

With Scopebound

  • Every tool call enforced before execution (<5ms)
  • Append-only audit log with SHA-256 hash chain
  • Behavioral drift auto-revokes anomalous sessions
  • One decorator, consistent enforcement everywhere
  • Same SDK across LangChain, AutoGen, CrewAI, and more

Integration

Three lines of code

Add enforcement to any existing agent tool. Nothing else in your codebase changes.

from scopebound import ScopeboundSDK, enforce
from langchain_core.tools import BaseTool

sb = ScopeboundSDK()  # reads SCOPEBOUND_BASE_URL + SCOPEBOUND_API_KEY from env

@enforce(sb, role="invoice-processor")  # ← this is the entire integration
class ReadInvoicesTool(BaseTool):
    name: str = "read_invoices"
    description: str = "Read pending invoices from the database"

    def _run(self, status: str = "pending") -> str:
        # your existing tool logic — unchanged
        ...
from scopebound import ScopeboundSDK
from scopebound.adapters.autogen import enforce_autogen

sb = ScopeboundSDK()

@enforce_autogen(sb, role="invoice-processor")
def read_invoices(limit: int = 10) -> str:
    # on deny, returns structured error dict instead of raising
    ...
from scopebound import ScopeboundSDK
from scopebound.adapters.crewai import CrewEnforcer

sb = ScopeboundSDK()
enforcer = CrewEnforcer(sb, roles={
    "researcher": "read-only-analyst",
    "writer":     "email-sender",
})

@enforcer.enforce_tool(agent_name="researcher")
def search_web(query: str) -> str:
    ...
from scopebound import ScopeboundSDK
from scopebound.adapters.semantic_kernel import enforce_sk

sb = ScopeboundSDK()

class InvoicePlugin:
    @enforce_sk(sb, role="invoice-processor")
    async def read_invoices(self, limit: int = 10) -> str:
        ...  # sync and async both supported
from claude_agent_sdk import ClaudeAgentOptions, query
from scopebound import ScopeboundSDK
from scopebound.exceptions import ScopeboundDenyError

sb = ScopeboundSDK()

def scopebound_hook(tool_name: str, tool_input: dict):
    try:
        sb.enforce(role_id="invoice-processor", tool_name=tool_name)
    except ScopeboundDenyError as e:
        raise PermissionError(f"[{e.deny_code}] {e.reason}")

options = ClaudeAgentOptions(hooks={"PreToolUse": scopebound_hook})
async for message in query("Process pending invoices", options=options):
    print(message)

Features

Everything you need to secure agents in production

Sub-5ms enforcement

OPA/Rego evaluation on the enforce path adds under 5ms. p99 under 10ms in production load.

🔑

Cryptographic agent identity

Every agent session gets a scoped JWT. Role, allowed tools, delegation depth, and TTL baked into the token.

📋

Tamper-evident audit trail

Append-only JSONL log with SHA-256 hash chain. Every allow and deny recorded. Chain violation halts the server.

📊

Behavioral drift detection

Statistical baseline + Isolation Forest. Anomaly score above threshold triggers automatic session revocation.

📝

Policy as code

OPA/Rego policies version-controlled alongside your agent code. Hot-reloads without restart.

🔌

Framework-native

Adapters for LangChain, OpenAI Assistants, CrewAI, AutoGen, Semantic Kernel, and Claude Agent SDK.


Ready to enforce what your agents can do?

contact@scopebound.ai

Or pip install scopebound and explore the SDK.