Skip to main content

Trust enforcement adapter for LangChain and LangGraph — powered by CapiscIO

Project description

CapiscIO LangChain Guard

Trust enforcement for LangChain and LangGraph agents.

PyPI version Python 3.10+ License

LangChain Guard is the CapiscIO trust enforcement adapter for LangChain and LangGraph. It verifies caller trust badges, enforces security policies, and emits audit events — all composable via LangChain's LCEL pipe (|) operator with zero configuration.

Installation

pip install langchain-capiscio

Quick Start

Turn any LangChain agent into a trust-verified agent in 2 lines:

from langchain_capiscio import CapiscioGuard

# Reads CAPISCIO_API_KEY from env, connects to registry
secured = CapiscioGuard.connect() | my_chain
result = secured.invoke({"input": "Summarize this ticket"})

CapiscioGuard.connect() reads your environment, connects to the CapiscIO registry, and returns a guard that verifies caller trust badges before every invocation — consistent with CapiscIO.connect() and CapiscioMCPServer.connect() across the ecosystem.

Why LangChain Guard?

LangChain agents orchestrate powerful tools — search, databases, code execution. But LangChain itself doesn't define how to:

  • Authenticate which agent is calling your chain
  • Authorize whether that agent meets your trust requirements
  • Audit what happened for post-incident review

LangChain Guard solves this with:

Feature Description
CapiscioGuard Runnable[dict, dict] — verifies trust badges before downstream execution. Composable with |.
CapiscioTool Wraps a LangChain Tool with trust enforcement at the tool-call boundary.
CapiscioCallbackHandler Audit trail — emits chain/tool lifecycle events to the CapiscIO EventEmitter.
@capiscio_guard Decorator for LangGraph function-based nodes.
verify_badge / resolve_agent_card Convenience @tool-decorated functions for agent-driven trust checks.

Enforcement Modes

Control enforcement behavior per guard instance:

guard = CapiscioGuard.connect(mode="block")    # Fail closed (production default)
guard = CapiscioGuard.connect(mode="monitor")  # Warn but continue
guard = CapiscioGuard.connect(mode="log")      # Log only

LCEL Pipe Composition

CapiscioGuard is a LangChain Runnable — compose it with any chain or agent via the | operator:

Note: The example below uses LangGraph. Install it separately: pip install langgraph

from langchain_capiscio import CapiscioGuard
from langgraph.prebuilt import create_react_agent

agent = create_react_agent(llm, tools)
secured = CapiscioGuard.connect(mode="log") | agent
result = secured.invoke({"input": "What's 42 * 17?"})

Callback Handler

Emit structured audit events (task lifecycle, tool calls) to the CapiscIO dashboard:

from langchain_capiscio import CapiscioCallbackHandler

handler = CapiscioCallbackHandler(emitter=my_event_emitter)
result = chain.invoke(
    {"input": "..."},
    config={"callbacks": [handler]},
)

Events emitted: task_started, task_completed, task_failed, tool_call, tool_result.

LangGraph Integration

from langchain_capiscio import CapiscioGuard, capiscio_guard

# Option 1: Runnable as graph node
graph.add_node("verify", CapiscioGuard.connect())

# Option 2: Decorator
@capiscio_guard(mode="block")
def call_agent(state: dict) -> dict:
    ...

"Let's Encrypt" Style Setup

Zero-config (recommended)

Set environment variables and connect with no arguments:

export CAPISCIO_API_KEY="cap_..."
export CAPISCIO_SERVER_URL="https://dev.registry.capisc.io"  # optional
export CAPISCIO_AGENT_NAME="my-agent"                        # optional
export CAPISCIO_DEV_MODE="true"                              # optional
guard = CapiscioGuard.connect()  # reads env vars, connects eagerly

Explicit configuration

guard = CapiscioGuard.connect(
    api_key="cap_...",
    mode="block",
    name="my-agent",
    server_url="https://dev.registry.capisc.io",
)

Extra connect kwargs

Pass additional keyword arguments through to CapiscIO.connect():

guard = CapiscioGuard.connect(
    mode="log",
    dev_mode=True,
    keys_dir="capiscio_keys/",
    agent_card=my_card_dict,
)

Using Environment Variables

CapiscioGuard.connect() reads environment variables automatically. from_env() is kept as a convenience alias:

guard = CapiscioGuard.connect(mode="log")
Variable Required Description Default
CAPISCIO_API_KEY Yes* Registry API key
CAPISCIO_SERVER_URL No Registry URL override https://registry.capisc.io
CAPISCIO_AGENT_NAME No Agent name for registration
CAPISCIO_DEV_MODE No Enable dev mode (true/1/yes) false
CAPISCIO_AGENT_PRIVATE_KEY_JWK No JSON-encoded Ed25519 private JWK for ephemeral environments

*Required if not passed explicitly via constructor.

Priority: explicit constructor args > connect_kwargs > env vars > SDK defaults.

Deploying to Containers / Serverless

In ephemeral environments (Docker, Lambda, Cloud Run) the local ~/.capiscio/keys/ directory doesn't survive restarts. Without a persisted key, the SDK generates a new keypair on every start, which means a new DID and invalidated badges.

Key Persistence via Environment Variable

On first run the SDK generates a keypair and logs a capture hint:

╔══════════════════════════════════════════════════════════════════╗
║  New agent identity generated — save key for persistence         ║
╚══════════════════════════════════════════════════════════════════╝

  Add to your secrets manager / .env:

    CAPISCIO_AGENT_PRIVATE_KEY_JWK='{"kty":"OKP","crv":"Ed25519","d":"...","x":"...","kid":"did:key:z6Mk..."}'

Copy that value into your secrets manager and set it as an environment variable. On subsequent starts the SDK recovers the same DID without generating a new identity.

Key resolution priority: env var → local file → generate new.

# docker-compose.yml
services:
  langchain-agent:
    image: my-langchain-agent
    environment:
      CAPISCIO_API_KEY: ${CAPISCIO_API_KEY}
      CAPISCIO_AGENT_PRIVATE_KEY_JWK: ${AGENT_KEY_JWK}  # from secrets manager
      CAPISCIO_DEV_MODE: "false"
# No code changes needed — CapiscioGuard.connect() reads env vars automatically
secured = CapiscioGuard.connect(mode="block") | my_agent

Warning: Never bake private keys into container images. Inject them at runtime via environment variables or mounted secrets.

See the Ephemeral Deployment Guide for secrets manager examples and volume-mount alternatives.

Badge Token Extraction

CapiscioGuard extracts the caller's badge token from (in priority order):

  1. Context variable — set by A2A server middleware via set_capiscio_context()
  2. RunnableConfigconfig={"configurable": {"capiscio_badge": token}}
  3. Input dict{"capiscio_badge": token, ...}

For A2A server integrations, set the context at the HTTP perimeter:

from langchain_capiscio import CapiscioRequestContext, set_capiscio_context

set_capiscio_context(CapiscioRequestContext(
    badge_token=badge_jwt,
    caller_did="did:web:caller.example.com",
))

Trust Levels

Level Name Description
0 Self-Signed (SS) No external validation, did:key issuer
1 Registered (REG) Account registration with CapiscIO Registry
2 Domain Validated (DV) Domain ownership verified via DNS/HTTP challenge
3 Organization Validated (OV) Organization existence verified (DUNS, legal entity)
4 Extended Validated (EV) Manual review + legal agreement with CapiscIO

API Reference

Guard

  • CapiscioGuard.connect(api_key, *, mode, name, server_url, dev_mode, **kwargs) — Connect to registry and return a ready-to-use guard (recommended)
  • CapiscioGuard.from_env(mode, **kwargs) — Alias for connect() (reads env vars)
  • CapiscioGuard(*, identity, config, mode, api_key, name, server_url, connect_kwargs) — Low-level constructor (keyword-only, lazy init on first invoke)
  • CapiscioGuard.invoke(input, config) — Verify badge and pass through to downstream
  • CapiscioGuard.ainvoke(input, config) — Async version

Callbacks

  • CapiscioCallbackHandler(emitter, identity) — Emit chain/tool lifecycle events to CapiscIO

Tool Enforcement

  • CapiscioTool(tool, *, identity=None, config=None, mode="block", api_key=None) — Wrap a LangChain Tool with trust enforcement
  • verify_badge@tool-decorated function for agent-driven badge verification
  • resolve_agent_card@tool-decorated function for agent card resolution

LangGraph

  • @capiscio_guard(mode, identity, config, api_key) — Decorator for LangGraph function-based nodes

Context

  • set_capiscio_context(ctx) — Set request context (badge token, caller DID) for the current invocation
  • get_capiscio_context() — Retrieve current request context
  • CapiscioRequestContext — Dataclass holding badge token and caller DID

Documentation

Development

# Clone repository
git clone https://github.com/capiscio/langchain-capiscio.git
cd langchain-capiscio

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest -v

# Run tests with coverage
pytest --cov=langchain_capiscio --cov-report=html

License

Apache License 2.0

Contributing

Contributions welcome! Please open an issue or pull request on GitHub.

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_capiscio-0.2.0.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

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

langchain_capiscio-0.2.0-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

Details for the file langchain_capiscio-0.2.0.tar.gz.

File metadata

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

File hashes

Hashes for langchain_capiscio-0.2.0.tar.gz
Algorithm Hash digest
SHA256 10e85f226f5e79ea6fca7048224c6cbddb8889788db8cb7b6ab1201c2c6985ec
MD5 6473c603b4e8b7eb96315d139dfd5412
BLAKE2b-256 12e15037f1dcbf1d88fdd8d1b4ab14b1c915f981320271405fed5d85d9a18edd

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_capiscio-0.2.0.tar.gz:

Publisher: publish.yml on capiscio/langchain-capiscio

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_capiscio-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for langchain_capiscio-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 423910fd317586ffec0ff9645b7d9508e3a9beb79c3d567660e463a6d9c3d958
MD5 2b610300168814308d5faf8283abea08
BLAKE2b-256 32db3a64221c1ab8f8df33f13369f07a55e209ba76c0a15de6d1385972663d92

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_capiscio-0.2.0-py3-none-any.whl:

Publisher: publish.yml on capiscio/langchain-capiscio

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