Skip to main content

Tool governance and auditing framework for LangChain

Project description

LangChain Tool Gate

A lightweight tool gate framework for LangChain applications - manage tool lifecycles with dynamic approval workflows and runtime guardrails.


Overview

LangChain Tool Governance provides a complete solution for managing AI agent tools in LangChain applications. It enables organizations to implement tool approval workflows and enforce runtime permission controls without requiring application restarts.

Core Principles:

  • Risk-Based Governance: Permission levels determine approval requirements (auto-activate, single-approval, dual-approval + quiet period)
  • Dynamic Runtime: Active tools are fetched with TTL caching - changes take effect immediately without restarting the Agent
  • Status-Only Interception: Tool calls are blocked based solely on status (active/inactive), not permission levels

Features

  • Tool Registration: Automatically scan and register tools with comprehensive metadata
  • Approval Workflow: Manage tool lifecycle (pending → active → rejected → deprecated)
  • Risk-Based Approval: Permission levels determine initial status and approval requirements
  • Dynamic Runtime: TTL-cached tool list for real-time updates without Agent restarts
  • Runtime Guardrails: Block inactive tool calls at execution time
  • CLI Management: Command-line interface for tool governance operations
  • External Approval Integration: Support for DingTalk and Feishu approval workflows

Installation

pip install langchain-tool-gate

Quick Start

Step 1: Define Governed Tools

from pydantic import BaseModel, Field
from tool_governance import governed_tool

class CancelOrderInput(BaseModel):
    order_id: str = Field(description="Order ID")

@governed_tool(
    name="cancel_order",
    description="Cancel user's order",
    permission_level="confidential",
    args_schema=CancelOrderInput,
    creator="dev@company.com",
)
def cancel_order(order_id: str) -> str:
    return f"Order {order_id} cancelled"

@governed_tool(
    name="get_weather",
    description="Get weather information",
    permission_level="public",
    creator="dev@company.com",
)
def get_weather(city: str) -> str:
    return f"Weather for {city}"

Step 2: Register Tools

from tool_governance.core.registry import ToolRegistryService

registry = ToolRegistryService(db_url="sqlite:///./tools.db", cache_ttl=60)
result = registry.scan_and_register()
print(result)

Step 3: Approve Tools via CLI

# List pending tools
tool-gov list --status pending

# Approve a tool
tool-gov approve cancel_order --approver team_leader

Step 4: Apply Guardrails to Agent

from tool_governance import apply_guardrails
from langchain.agents import AgentExecutor

executor = AgentExecutor(agent=agent, tools=[cancel_order, get_weather])
executor = apply_guardrails(executor, db_url="sqlite:///./tools.db")

# Only active tools can be called
result = executor.invoke({"input": "Please cancel order ORDER-123"})

Risk-Based Approval Matrix

The framework uses permission levels to determine the initial approval workflow:

Permission Level Initial Status Approval Required Quiet Period Developer Experience
public auto-activated 0 approvals None Push code → 5 min → LLM uses tool
internal pending 1 approval (Leader) None DingTalk/Feishu notification → one click approve
confidential pending 2 approvals 24 hours Two approvals + 24h waiting period
restricted pending 2 approvals 24 hours Same as confidential

Permission Level Guidelines

  • public: Read-only, non-sensitive operations (e.g., get_weather, query_public_data)
  • internal: User-level write operations (e.g., update_profile, submit_form)
  • confidential: High-risk operations (e.g., cancel_order, delete_data, batch_operations)
  • restricted: System-level operations requiring strict controls

CLI Usage

# List tools with filters
tool-gov list --status pending
tool-gov list --status active
tool-gov list --status all

# Approve/reject tools
tool-gov approve <tool_name> --approver <name>
tool-gov reject <tool_name>

# Submit approval to external system (DingTalk/Feishu)
tool-gov submit-approval <tool_name> --platform dingtalk
tool-gov submit-approval <tool_name> --platform feishu

# Sync approval status from external system
tool-gov sync-approval --platform dingtalk
tool-gov sync-approval --platform feishu

# Specify database URL
tool-gov --db-url sqlite:///./my_db.db list

# Start Prometheus metrics server
tool-gov metrics --port 8000 --host 0.0.0.0

API Reference

governed_tool Decorator

Register a tool with governance metadata.

@governed_tool(
    name: Optional[str] = None,
    description: Optional[str] = None,
    permission_level: str = "default",
    args_schema: Optional[BaseModel] = None,
    creator: str = "system",
)
def my_tool():
    pass

apply_guardrails Function

Apply runtime guardrails to an AgentExecutor - blocks inactive tool calls.

executor = apply_guardrails(
    executor: AgentExecutor,
    db_url: str = "sqlite:///./tools.db",
)

ToolRegistryService Class

Manage tool registration and lifecycle with TTL caching.

registry = ToolRegistryService(
    db_url: str = "sqlite:///./tools.db",
    cache_ttl: int = 60,  # Cache expiration in seconds
)

registry.scan_and_register()          # Scan and register tools
registry.get_active_tools()           # Get active tools (with TTL cache)
registry.approve_tool(name, approver) # Approve a tool
registry.reject_tool(name)            # Reject a tool
registry.invalidate_cache()           # Manually invalidate cache

External Approval Integration

Submit and sync approvals with DingTalk or Feishu:

from tool_governance.core.approval import create_approval_client

client = create_approval_client(
    platform="dingtalk",
    app_key="your_app_key",
    app_secret="your_app_secret",
    process_code="your_process_code",
)

# Submit approval
result = registry.submit_approval("cancel_order", client)

# Sync approval status
results = registry.sync_approval_status(client)

Approval Status Sync Flow

1. submit_approval → Submit to DingTalk/Feishu, save approval_id
2. Approver operates in DingTalk/Feishu (approve/reject)
3. sync_approval_status → Query external status, update local status
   - "approved": Activate based on approval count and quiet period
   - "rejected": Mark as REJECTED
4. Auto invalidate_cache() on status change, Agent picks up changes immediately

Dynamic Runtime Architecture

The framework enables online maintenance without restarting the Agent:

┌─────────────────────────────────────────────────────────────────┐
│                      Agent Runtime                              │
│                                                                 │
│   AgentExecutor.invoke()                                        │
│         │                                                       │
│         ▼                                                       │
│   apply_guardrails()                                            │
│         │                                                       │
│         ▼                                                       │
│   get_active_tools() ──┬── Cache Hit (TTL < 60s) ──► Return     │
│                        │                                        │
│                        ▼                                        │
│                   Database Query ──► Update Cache ──► Return    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
                              ▲
                              │ Cache Invalidation
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Approval Actions                            │
│                                                                 │
│   approve_tool() → invalidate_cache()                           │
│   reject_tool()  → invalidate_cache()                           │
│   sync_approval_status() → invalidate_cache()                   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Key Benefits:

  • No Restart Required: Cache invalidation ensures changes take effect immediately
  • Performance: TTL caching reduces database queries during high-frequency tool calls
  • Flexibility: Adjust cache_ttl based on your update frequency requirements

Database Configuration

SQLite (Default)

registry = ToolRegistryService(db_url="sqlite:///./tools.db")

PostgreSQL

registry = ToolRegistryService(db_url="postgresql://user:password@host:5432/dbname")

Database Schema

Table: tool_registry

Column Type Description
id INTEGER Primary key
name VARCHAR(100) Tool name (unique)
description TEXT Tool description
schema_json TEXT Tool schema as JSON
permission_level VARCHAR(50) Permission level (public/internal/confidential/restricted/default)
status VARCHAR(20) Tool status (active/pending/rejected/deprecated)
created_by VARCHAR(100) Creator email
created_at DATETIME Creation timestamp
approved_at DATETIME Approval timestamp (nullable)
approval_count INTEGER Current approval count
approval_required INTEGER Required approvals
approval_id VARCHAR(200) External approval ID (nullable)
approval_platform VARCHAR(50) Approval platform (dingtalk/feishu)
approvers TEXT JSON list of approvers
quiet_period_until DATETIME Quiet period end time (nullable)

Monitoring & Metrics

Prometheus Integration

The framework exposes Prometheus metrics for monitoring tool governance activity.

Start Metrics Server

# Using CLI options
tool-gov metrics --port 9090 --host 127.0.0.1

# Using environment variables
export TOOL_GOVERNANCE_METRICS_PORT=9090
export TOOL_GOVERNANCE_METRICS_HOST=127.0.0.1
tool-gov metrics

# Default values (port: 8000, host: 0.0.0.0)
tool-gov metrics

Configuration

The metrics server can be configured via:

  1. CLI arguments (highest priority)

    • --port: Metrics server port
    • --host: Metrics server host
  2. Environment variables

    • TOOL_GOVERNANCE_METRICS_PORT: Port (default: 8000)
    • TOOL_GOVERNANCE_METRICS_HOST: Host (default: 0.0.0.0)
  3. Default values (lowest priority)

    • Port: 8000
    • Host: 0.0.0.0

Metrics Endpoint

http://localhost:8000/metrics

Available Metrics

Metric Type Description Labels
toolgovernance_tool_registered_total Counter Total tools registered permission_level
toolgovernance_tool_activated_total Counter Total tools activated permission_level
toolgovernance_tool_rejected_total Counter Total tools rejected permission_level
toolgovernance_tool_approvals_total Counter Total approvals tool_name
toolgovernance_tool_active_count Gauge Active tools count permission_level
toolgovernance_tool_status_count Gauge Tools count by status status
toolgovernance_approval_pending_seconds Histogram Pending duration before approval permission_level
toolgovernance_cache_hits_total Counter Cache hits None
toolgovernance_cache_misses_total Counter Cache misses None
toolgovernance_cache_invalidations_total Counter Cache invalidations None

Grafana Dashboard Suggestions

Create panels for:

  • Tool Status Distribution: Pie chart of toolgovernance_tool_status_count
  • Active Tools by Permission Level: Bar chart of toolgovernance_tool_active_count
  • Approval Rate: Rate of toolgovernance_tool_approvals_total
  • Approval Latency: Histogram of toolgovernance_approval_pending_seconds
  • Cache Hit Ratio: toolgovernance_cache_hits_total / (hits + misses)

Prometheus Scrape Config

scrape_configs:
  - job_name: 'tool-governance'
    static_configs:
      - targets: ['localhost:8000']
    metrics_path: /metrics

Configuration

Environment Variables

# DingTalk Approval
export DINGTALK_APP_KEY=your_app_key
export DINGTALK_APP_SECRET=your_app_secret
export DINGTALK_PROCESS_CODE=your_process_code

# Feishu Approval
export FEISHU_APP_ID=your_app_id
export FEISHU_APP_SECRET=your_app_secret
export FEISHU_APPROVAL_CODE=your_approval_code

# Prometheus Metrics
export TOOL_GOVERNANCE_METRICS_PORT=8000
export TOOL_GOVERNANCE_METRICS_HOST=0.0.0.0

Testing

pip install pytest
pytest tests/ -v

License

MIT License

Contributing

Contributions are welcome! Please submit a pull request or create an issue.

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

langchain_tool_gate-1.0.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

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

langchain_tool_gate-1.0.0-py3-none-any.whl (19.9 kB view details)

Uploaded Python 3

File details

Details for the file langchain_tool_gate-1.0.0.tar.gz.

File metadata

  • Download URL: langchain_tool_gate-1.0.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for langchain_tool_gate-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3631dd287d3d59e6376721e63bbc3f3e1460a693748fcf0424576692228b8722
MD5 1a1a81f8cca153af481cdf49817b4b51
BLAKE2b-256 3d976fb60501f3a0c7d2fdff29f84f2071da2861cf87afe45762fdf4b0508d2b

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_tool_gate-1.0.0.tar.gz:

Publisher: release.yml on yusishuma/langchain-tool-gate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file langchain_tool_gate-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for langchain_tool_gate-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d6fe2a43f42677c54930713c06c62f845830365d179769c4ae51b4d95a9bba8f
MD5 8d353cf398f29dea4088fd29b5b1fabf
BLAKE2b-256 1664cad67b8ed0f59cbadc1962c8fda3b5be8ddbd37f4b3c7f78a67dbc03bb6f

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_tool_gate-1.0.0-py3-none-any.whl:

Publisher: release.yml on yusishuma/langchain-tool-gate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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