Skip to main content

Deterministic, config-driven guardrails for LLM agent tool calls

Project description

obex

Deterministic, config-driven guardrails for LLM agent tool calls. Zero-LLM enforcement. Compliance audit trail built in.

Named after the Latin word for bolt or barrier. The bolt on the gate that no LLM can argue past.

Why

LLM agents can now call tools autonomously — execute SQL, send emails, make API calls. Existing guardrail frameworks either use LLM calls in the enforcement path (non-deterministic, slow, expensive) or require writing Python code that compliance teams can't review.

Obex is different:

  • YAML config — rules live in config files that compliance teams can review, version, and audit without reading Python
  • Zero-LLM enforcement — every decision is deterministic and reproducible. No AI in the guardrail path.
  • Compliance-first — OPA-inspired audit trail as a first-class feature, not an afterthought
  • Framework-agnostic — works standalone or with LangGraph, CrewAI, or any agent framework
Feature Obex NeMo Guardrails LangChain Middleware OpenAI Agents SDK
Config-driven (YAML) Yes Colang DSL Python code Python decorators
Zero-LLM enforcement Yes No (LLM in loop) Yes Yes
Audit trail Built-in Logging only No No
Framework-agnostic Yes LangChain LangChain only OpenAI only
Dependencies Zero (stdlib) Heavy LangChain OpenAI SDK

Quick Start

pip install obex[yaml]
from obex import Engine, ToolCall

engine = Engine.from_yaml("rules.yaml")

# Evaluate a tool call
result = engine.evaluate(
    ToolCall(name="execute_sql", args={"query": "DROP TABLE users"})
)
print(result.decision)  # Decision.BLOCK
print(result.reason)    # "Pattern matched in field 'query': DROP TABLE"

YAML Config

version: "1.0"
policy_version: "1.0.0"

rules:
  # Block dangerous SQL patterns
  - name: block_sql_injection
    type: regex_block
    applies_to: ["execute_sql", "run_query"]
    params:
      fields: ["query"]
      patterns:
        - "(?i)(DROP|DELETE|TRUNCATE)\\s+TABLE"

  # Require confirmation IDs on sensitive operations
  - name: require_confirmation
    type: regex_require
    applies_to: ["send_email", "transfer_funds"]
    params:
      fields: ["confirmation_id"]
      pattern: "^CONF-[A-Z0-9]{8}$"

  # Scan all tool calls for PII leakage
  - name: detect_pii
    type: pii_detect
    applies_to: ["*"]
    params:
      detectors: [email, phone_intl, hk_id, credit_card]
      action: block

  # Role-based tool access
  - name: tool_entitlement
    type: entitlement
    applies_to: ["*"]
    params:
      roles:
        analyst: ["search", "get_data", "summarize"]
        admin: ["*"]
      default: block

Rule Types

Type Purpose Key Params
regex_block Block if field matches pattern fields, patterns
regex_require Block if required field is missing/invalid fields, pattern
pii_detect Scan args for PII (email, phone, HKID, etc.) detectors, action
entitlement Role-based tool access control roles, default

Audit Trail

Every evaluation produces a structured JSON record (JSONL format, OPA-inspired):

from obex import AuditLogger, Engine

logger = AuditLogger("audit.jsonl")
engine = Engine.from_yaml("rules.yaml", audit_logger=logger.log)

Each record includes: decision_id, timestamp, policy_version, tool_name, tool_args (redacted), decision, rules_evaluated, blocking_rule, human_override, trace_id.

Audit Reports

Generate compliance-ready summaries from audit logs:

from obex import AuditReporter

reporter = AuditReporter("audit.jsonl")
report = reporter.generate()
print(report.to_text())
========================================
OBEX AUDIT REPORT
========================================
Period: 2026-02-28 10:00 to 2026-02-28 16:00
Policy versions: 1.0.0

Total evaluations: 500
       Allow:    450 (90.0%)
       Block:     50 (10.0%)

Top blocked tools:
  1. execute_sql                    — 25 blocks
  2. send_email                     — 15 blocks

Top triggered rules:
  1. block_sql_injection            — 20 triggers
  2. detect_pii                     — 18 triggers

Human override rate: 4.0% (2 of 50 blocks overridden)
========================================

LangGraph Integration

pip install obex[langgraph]
from langgraph.prebuilt import ToolNode
from obex import Engine
from obex.adapters.langgraph import guarded_tool_node

tools = [search, calculator]
engine = Engine.from_yaml("rules.yaml")
safe_tools = guarded_tool_node(ToolNode(tools), engine)

builder.add_node("tools", safe_tools)

Blocked tool calls return a ToolMessage with the block reason — the LLM sees why its call was rejected and can adjust.

Programmatic Use (No YAML)

from obex import Engine, ToolCall
from obex._types import RuleConfig, RuleType

engine = Engine(rules=[
    RuleConfig(
        name="block_drops",
        rule_type=RuleType.REGEX_BLOCK,
        params={"fields": ["query"], "patterns": [r"(?i)DROP\s+TABLE"]},
        applies_to=["execute_sql"],
    ),
])

result = engine.evaluate(ToolCall(name="execute_sql", args={"query": "SELECT 1"}))
assert result.decision.value == "allow"

Zero dependencies — the core engine runs on stdlib alone.

Design Philosophy

  • Hooks > prompts for mechanical rules. If a rule is regex-matchable, enforce it in code, not in the system prompt.
  • Fail closed. If a rule errors, the tool call is blocked.
  • No LLM in the enforcement path. Every decision is deterministic and reproducible.
  • Config is reviewable. Compliance teams review YAML, not Python.
  • Audit schema inspired by OPA. Decision logs follow established policy-engine conventions.

License

MIT

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

obex-0.1.0.tar.gz (88.5 kB view details)

Uploaded Source

Built Distribution

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

obex-0.1.0-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: obex-0.1.0.tar.gz
  • Upload date:
  • Size: 88.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for obex-0.1.0.tar.gz
Algorithm Hash digest
SHA256 434ba063e976c7d70a8d1564f5a5c86e18eb5becb2e87aa6f2ca007709cf55dd
MD5 62325db8257fee6be9f9a746f6cda723
BLAKE2b-256 7f7311d64e3a5f409897d222ea4202aa061e33c121df212b151956009990305c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: obex-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for obex-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8450c4f45aaee357eae986a1178f0d8c8aa43caf2b3330bccfa120f4340ff0cb
MD5 f91036f166737ee19e295cf87962a336
BLAKE2b-256 cb24e8922c0ad8ee087d8133c8ca18d626eeddfdecfc20bb3eb84916483dad88

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