Skip to content

Installing & Using the pycaber(auto) SDK ​

Caber takes inspiration from OpenTelemetry and OpenLit by providing drop in installation and automatic instrumentation for Python AI applications, LLM SDKs, vector databases, and multi agent frameworks, while combining observability with synchronous in band policy enforcement, subdocument WRL Chunker characterization, and Principal identity propagation.

Caber Auto Instrumentation and Policy Enforcement Matrix
Figure 1: Caber Auto Instrumentation Pipeline Across LLM Providers, Vector Stores, Agent Frameworks, and Enterprise Connectors
## 1. Installation & Prerequisites

System Prerequisites ​

  • Python: Python 3.10, 3.11, 3.12, or 3.13
  • Rust Toolchain (only required when building from source via Maturin): rustc >= 1.80
  • Virtual Environment: Always install inside your project's .venv virtual environment.

Option A: Install Prebuilt Wheel with Auto Instrumentation Extras ​

bash
.venv/bin/pip install "pycaber[auto]"

Installing pycaber[auto] includes:

  • The compiled Rust native extension (pycaber._core) containing caber_core, the WRL Chunker, the RoaringIndexEngine (rbix), the Regorus policy evaluator, and the ONNX gliner_ner engine.
  • The OpenTelemetry and OpenLit compatible wrapt monkey patching hooks (opentelemetry-api, opentelemetry-sdk, wrapt).
  • The caber-run zero code CLI wrapper.

2. Three Activation Modes ​

pycaber(auto) supports three activation patterns depending on whether you can modify application entry points or want zero code injection at container launch.

Mode 1: Single Line Import (import pycaber.auto) ​

Add import pycaber.auto as the very first import in your application entry point before importing openai, anthropic, langchain, or mcp:

python
import pycaber.auto  # Automatically reads CSI_CONFIG_FILE and patches installed AI libraries
from openai import OpenAI

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Summarize the Q3 M&A valuation memo."}],
)
print(response.choices[0].message.content)

Mode 2: Zero Code CLI Wrapper (caber-run) ​

If you cannot modify application source code, prefix your launch command with caber-run. It injects a sitecustomize.py bootstrap hook into PYTHONPATH that initializes pycaber before main.py or uvicorn starts:

bash
CSI_CONFIG_FILE=/etc/caber/config.json \
  .venv/bin/caber-run .venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000

Mode 3: Explicit Programmatic Initialization (pycaber.init()) ​

For fine grained control over enforcement modes, Principal context callbacks, custom Rego policy directories, or configuration overrides, call pycaber.init() or pycaber.configure() explicitly:

python
import pycaber

pycaber.init(
    application_name="finance_research_assistant",
    environment="production",
    config_path="/etc/caber/config.json",
    enforcement_mode="enforce",          # Options: "enforce", "redact", "audit_only", "disabled"
    metapolicy="freshness_filtered_override",
    enable_wrl_characterization=True,
    enable_gliner_ner=True,
    propagate_obo_identity=True,
)

3. Binding Principal Identity & Delegation Context ​

To ensure every downstream LLM prompt, RAG query, and MCP tool execution is evaluated against the human user who initiated the request, bind the Principal context at request ingress using pycaber.principal_context:

python
import pycaber
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.post("/chat")
async def chat_endpoint(request: Request, payload: dict):
    user_jwt = request.headers.get("Authorization", "").removeprefix("Bearer ")

    try:
        with pycaber.principal_context(
            principal_id=payload["user_email"],
            jwt_token=user_jwt,
            roles=payload.get("roles", ["Analyst"]),
            department=payload.get("department", "Research"),
            agent_id="agent://chat-orchestrator-v1",
        ):
            # All LLM calls, vector retrievals, subagent handoffs, and MCP tools inside
            # this block automatically carry W3C traceparent + signed caber-obo-token
            answer = await run_agent_workflow(payload["question"])
            return {"answer": answer}
    except pycaber.PolicyViolationError as exc:
        raise HTTPException(
            status_code=403,
            detail={
                "error": "Blocked by Caber Policy Engine",
                "verdict": exc.decision_receipt.verdict,
                "metapolicy": exc.decision_receipt.metapolicy,
                "matched_doc_ids": exc.decision_receipt.matched_doc_ids,
                "stale_sources_detected": exc.decision_receipt.stale_doc_ids,
                "trace_id": exc.decision_receipt.trace_id,
            },
        )

4. What Happens Automatically on Every Patched Call ​

When pycaber(auto) intercepts an instrumented function call, it executes four deterministic steps in band:

  1. Pre Call Ingress Hook (Prompt & Tool Input Characterization):
    • Extracts prompt messages, retrieved RAG chunks, or tool arguments.
    • Calls caber_core::characterizer using the WRL Chunker (98.7% indexed coverage down to 40 bytes) and RoaringIndexEngine (rbix) to identify every enterprise document fragment present in the input.
    • Queries freshness cluster status (CANONICAL vs STALE_REPLICA) and evaluates per source Rego policies plus the active Metapolicy against the active PrincipalContext.
    • Depending on enforcement_mode:
      • "enforce": Raises pycaber.PolicyViolationError immediately if the composite verdict is DENY, preventing the prompt from ever leaving the host to an external LLM API.
      • "redact": Surgically masks unauthorized 40 byte WRL Chunker spans and GLiNER2 PII/PHI spans in place before forwarding the sanitized prompt to the LLM.
      • "audit_only": Logs the violation receipt and continues execution.
  2. Outbound Context Propagation:
    • Injects W3C traceparent and the cryptographically signed caber-obo-token (caber.principal.id, caber.agent.chain, caber.delegation.scope) into outbound HTTP headers, gRPC metadata, MCP _meta envelopes, or subprocess environment variables.
  3. Post Call Egress Hook (Completion & Tool Output Verification):
    • Characterizes the LLM response or tool output with the WRL Chunker to detect memorized or leaked restricted content and records DERIVED_FROM_FRAGMENT edges in the Neo4j Provenance Origin Tree.
    • Applies egress metapolicy obligations (span redaction, watermarking, or blocking) before returning the result to the caller.
  4. Telemetry & Audit Emission:
    • Emits OpenTelemetry GenAI spans (gen_ai.chat, gen_ai.embeddings, db.vector.query, gen_ai.execute_tool) enriched with caber.wrl.matches, caber.freshness.status, caber.metapolicy.verdict, and caber.principal.id to OpenSearch and CaberUserConsole.

5. Supported Auto Instrumentation Ecosystem ​

Caber takes inspiration from OpenTelemetry and OpenLit to provide automatic instrumentation across the AI stack:

CategorySupported Libraries & Providers
LLM ProvidersOpenAI (openai), Anthropic (anthropic), Google Gemini / Vertex AI (google-genai, vertexai), AWS Bedrock (boto3 bedrock-runtime), Azure OpenAI, Cohere, Mistral, Ollama, vLLM, LiteLLM, Groq, HuggingFace TGI
Agent FrameworksLangChain, LangGraph, LlamaIndex, CrewAI, Microsoft AutoGen, OpenAI Agents SDK, DSPy, Haystack, Semantic Kernel, PydanticAI, Smolagents
Vector DatabasesMilvus / PyMilvus, Qdrant, Pinecone, Weaviate, ChromaDB, PGVector (psycopg), OpenSearch / Elasticsearch kNN, MongoDB Atlas Vector Search, LanceDB
Tool, API & Process ProtocolsAnthropic Model Context Protocol (mcp stdio & SSE), httpx, requests, aiohttp, grpcio, subprocess (bash/shell tool execution), Python builtin file I/O (open / pathlib provenance hooks)

6. Direct Python SDK API (pycaber.CaberEngine) ​

In addition to automatic instrumentation, applications can call the Rust engine directly from Python for explicit document indexing, text characterization, or policy verification:

python
from pycaber import CaberEngine

engine = CaberEngine(config_path="/etc/caber/config.json")

# 1. Index a document with the WRL Chunker into RBIX
index_stats = engine.index_document(
    doc_id="doc://finance/2026-q3-board-deck.pdf",
    text=raw_document_text,
    metadata={
        "classification": "confidential",
        "department": "Finance",
        "policy_id": "policy://finance-confidential",
        "modified_at": "2026-10-15T14:20:00Z",
    },
)

# 2. Characterize arbitrary text or RAG context down to 40 byte spans
matches = engine.characterize(
    text=candidate_prompt_or_completion,
    min_chunk_bytes=40,
)
for m in matches:
    print(m.doc_id, m.byte_span, m.freshness_status, m.similarity_score)

# 3. Evaluate two stage policy + metapolicy for a Principal
receipt = engine.evaluate_governance(
    text=candidate_prompt_or_completion,
    principal_id="alice@corp.com",
    roles=["Finance_Analyst"],
    metapolicy="freshness_filtered_override",
)
print(receipt.verdict, receipt.redacted_text)