Execlave Python SDK
Official Python SDK for the Execlave AI Governance Platform. Provides pre-execution policy enforcement, tracing, agent registration, PII scrubbing, kill-switch support, and OpenTelemetry export.
Framework integrations — drop in one callback/processor/helper for LangChain, OpenAI Agents SDK, CrewAI, LlamaIndex, AutoGen, OpenAI Chat Completions, or the Model Context Protocol. See the full docs or get an API key.
Installation
pip install execlave-sdk
With OpenTelemetry support:
pip install execlave-sdk[otel]
Quick Start
The canonical request lifecycle is register → enforce → call LLM → trace. enforce_policy is what blocks bad requests; tracing alone only logs them after the fact.
from execlave import Execlave, PolicyBlockedError, AgentPausedError
exe = Execlave(
api_key="exe_prod_your_key_here", # or set EXECLAVE_API_KEY env var
base_url="https://api.execlave.com",
environment="production",
)
# Register the agent once on startup (idempotent)
agent = exe.register_agent(
agent_id="my-assistant",
name="Customer Support Bot",
description="Handles tier-1 support queries",
type="chatbot",
platform="custom",
tags=["support", "production"],
)
def answer(question: str) -> str:
trace = exe.start_trace(agent_id="my-assistant")
trace.set_input(question)
try:
# Pre-execution policy enforcement. Synchronously checks every
# policy you've configured for this agent. Raises PolicyBlockedError
# if any policy with enforcement_mode='block' fires.
exe.enforce_policy(agent_id="my-assistant", input=question)
except PolicyBlockedError as e:
trace.finish(status="error", error_type="PolicyBlockedError", error_message=str(e))
return "Request blocked by security policy."
except AgentPausedError:
trace.finish(status="error", error_type="AgentPausedError")
return "Service temporarily unavailable."
response = llm.invoke(question) # your LLM call
trace.set_output(response).set_model("gpt-4").finish()
return response
print(answer("How do I reset my password?"))
Agent Registration
Register agents to monitor them from the Execlave dashboard:
agent = exe.register_agent(
agent_id="order-processor",
name="Order Processor",
description="Processes and validates customer orders",
type="autonomous", # chatbot | copilot | autonomous | workflow
platform="custom", # custom | openai | anthropic | langchain | ...
tags=["orders", "production"],
autonomy_level="act_with_approval", # optional — observe | advise | act_with_approval | autonomous
)
# Check agent status (active / paused / etc.)
print(agent.status)
Tiered autonomy & registry versions (AMP)
autonomy_level (optional) maps the agent onto a tiered-governance template that
auto-applies a curated policy bundle. To build a version history in the agent
registry, call report_agent_metadata from your deploy pipeline on each release —
it records a version snapshot (label, git commit, deploy time):
exe.report_agent_metadata(
agent_id="order-processor",
version_label="v2.1.0",
git_commit="9f3c1ab",
activate=True, # mark this the active version (default False)
notes="rolled out canary → 100%",
)
Both are additive and backwards-compatible — agents that omit them are unaffected.
Policy Enforcement
enforce_policy is a synchronous check against the policies you've configured in the dashboard. Call it before every LLM or tool invocation. Behavior depends on each policy's enforcement_mode:
| Mode | What enforce_policy does |
|---|---|
block |
Raises PolicyBlockedError (with the violations list) |
monitor / warn |
Returns {"allowed": True, "warnings": [...]} — caller proceeds |
require_approval |
Blocks the call while polling for human approval (returns when granted) |
from execlave import PolicyBlockedError
try:
result = exe.enforce_policy(
agent_id="my-assistant",
input=user_message,
environment="production", # optional
metadata={"user_id": "u123"}, # optional
estimated_cost=0.02, # optional — for cost_limit policies
tools=["search", "email"], # optional — for access_control policies
)
# result["allowed"] is True. Check result.get("warnings") for non-blocking signals.
except PolicyBlockedError as e:
for v in e.violations:
print(v["policyType"], v["message"])
Important: A policy must be configured with
enforcement_mode = blockin the dashboard to actually block. Policies inmonitororwarnmode produce warnings on the result but never raise.
Tracing
Decorator
The simplest way to trace function calls:
@exe.trace
def process_order(order_data: dict) -> dict:
result = llm.invoke(json.dumps(order_data))
return json.loads(result)
@exe.traceonly records the call — it does not run policy enforcement. To block bad inputs, callexe.enforce_policy(...)inside the function body before invoking the LLM.
Context Manager
For more control over trace metadata:
with exe.start_trace(agent_id="my-assistant", session_id="sess_abc") as trace:
trace.set_input({"question": "What is the refund policy?"})
result = llm.invoke("What is the refund policy?")
trace.set_output({"answer": result})
trace.set_model("gpt-4o")
trace.set_tokens(input=150, output=320)
trace.set_cost(0.0045)
Manual Trace
trace = exe.start_trace(agent_id="my-assistant")
trace.set_input(user_query)
try:
response = llm.invoke(user_query)
trace.set_output(response)
trace.finish(status="success")
except Exception as e:
trace.finish(status="error", error_message=str(e), error_type=type(e).__name__)
raise
Trace Fields
| Method | Description |
|---|---|
set_input(data) |
Input data (auto-serialized) |
set_output(data) |
Output data (auto-serialized) |
set_model(name) |
Model name (e.g., "gpt-4o") |
set_tokens(input, output) |
Token counts |
set_cost(amount) |
Cost in USD |
set_duration(ms) |
Override auto-calculated duration (ms) |
add_metadata(dict) |
Merge additional metadata |
add_tags(list) |
Append tags (deduplicated) |
finish(status, error_message, error_type) |
Finalize trace and submit to the flush queue |
status values: "success" (default), "error", "timeout". All setter methods are chainable.
Privacy & PII Scrubbing
Built-in client-side PII scrubbing before data leaves your infrastructure:
exe = Execlave(
api_key="exe_prod_xxx",
privacy={
"enabled": True, # turn the feature on
"scrub_fields": ["input", "output"], # fields to scan
"hash_pii": True, # include short SHA-256 hashes in metadata
},
)
Detected PII types: email addresses, SSNs, credit card numbers, US phone numbers, IP addresses, API keys.
Client-side Injection Scoring
When enable_injection_scan=True (the default), the SDK runs a regex-based prompt-injection check on the trace's input and annotates the trace with the detected risk level and matched patterns:
exe = Execlave(
api_key="exe_prod_xxx",
enable_injection_scan=True,
)
The scan attaches a metadata.injection_scan block to the trace (with risk_level and patterns_matched) so detections show up in the dashboard.
This option does not block LLM calls — it is a tagging/telemetry feature. To actually prevent execution when injection is detected, configure an
injection_scanpolicy withenforcement_mode = blockin the dashboard and callexe.enforce_policy(...)before your LLM call. See Policy Enforcement.
Detected patterns include "ignore previous instructions", jailbreak attempts, system-prompt extraction, and other common prefixes.
Kill Switch / Pause Support
Execlave supports remote agent pausing via the dashboard. Once paused, every new trace or enforce call raises AgentPausedError:
from execlave import AgentPausedError
try:
result = answer("Process this order")
except AgentPausedError:
return "Service temporarily unavailable — agent paused by admin."
The SDK polls for status changes in the background (configurable interval) and connects via Socket.IO when available for sub-second propagation.
OpenTelemetry Integration
Export Execlave traces as OpenTelemetry spans for unified observability:
from execlave import Execlave
exe = Execlave(
api_key="exe_prod_xxx",
mode="otlp",
otlp_endpoint="http://localhost:4318", # your OTel collector
)
Requires the otel extra: pip install execlave-sdk[otel].
Configuration
Constructor Options
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
EXECLAVE_API_KEY env |
Your Execlave API key |
base_url |
str |
https://api.execlave.com |
Execlave API URL |
environment |
str |
"production" |
Environment tag |
async_mode |
bool |
True |
Non-blocking trace ingestion |
mode |
str |
"native" |
"native" or "otlp" |
otlp_endpoint |
str |
None |
OTel collector endpoint (required when mode="otlp") |
batch_size |
int |
100 |
Traces per flush batch |
flush_interval_seconds |
int |
10 |
Seconds between background flushes |
debug |
bool |
False |
Enable debug logging |
privacy |
dict |
{} |
PII scrubbing config (see Privacy section) |
enable_control_channel |
bool |
True |
Enable kill-switch polling + WebSocket |
enable_injection_scan |
bool |
True |
Tag traces with client-side injection signals (no block) |
enforcement_on_outage |
str |
"fail_open" |
"fail_open" allows requests when API is down; "fail_closed" raises EnforcementUnavailableError |
on_enforcement_bypassed |
Callable[[dict], None] |
None |
Called once for every call that ran without a server enforcement decision (network error, 5xx, circuit breaker open, or plan limit under fail-open). |
report_bypasses_to_platform |
bool |
True |
Also record each ungoverned window (coalesced per agent and reason) in your organisation's audit log as enforcement.bypassed. Set False to keep only the local callback. Requires 1.8.0+ and a platform that supports it. |
policy_cache_ttl_seconds |
int |
60 |
TTL for cached policy decisions |
Environment Variables
| Variable | Description |
|---|---|
EXECLAVE_API_KEY |
API key (alternative to constructor) |
EXECLAVE_BASE_URL |
Base URL (alternative to constructor) |
Error Handling
from execlave import (
ExeclaveError,
ExeclaveAuthError,
PolicyBlockedError,
ValidatorDeniedError,
AgentPausedError,
EnforcementUnavailableError,
)
try:
exe.enforce_policy(agent_id="my-assistant", input=user_message)
# ... LLM call + tracing ...
except ValidatorDeniedError as e:
# A Custom Validator (BYOV) denied the call. Subclass of PolicyBlockedError,
# so the broader `except PolicyBlockedError` below would also catch it —
# list this first only if you need validator-specific handling.
return "Blocked by a custom validator."
except PolicyBlockedError as e:
# A block-mode policy fired. e.violations is a list of dicts with policyType, message, severity.
return "Blocked by security policy."
except AgentPausedError:
# Agent paused via kill switch.
return "Service temporarily unavailable."
except EnforcementUnavailableError:
# Only raised when enforcement_on_outage='fail_closed' AND the API
# is unreachable for 3+ consecutive attempts (circuit breaker open).
return "Governance system unavailable."
except ExeclaveAuthError:
raise # Misconfigured API key — fail loud.
except ExeclaveError as e:
print(f"SDK error: {e}")
raise
Async Trace Buffer
The SDK uses a non-blocking circular buffer (max 10,000 traces) with a background flush thread. Traces are batched and sent to the Execlave API automatically.
# Manual flush (e.g., before shutdown)
exe.flush()
# Graceful shutdown — flushes remaining traces and joins background threads
exe.shutdown()
Development
# Clone the repo
git clone https://github.com/execlave/sdk-python.git
cd execlave/sdk-python
# Install dev dependencies
pip install -e ".[test]"
# Run tests
pytest # 130 tests
pytest --cov=execlave # With coverage
# Type checking
mypy execlave/
Legal
By using this SDK, you agree to the Execlave Terms of Service.
License
MIT — see LICENSE for details.
Metadata
Release files for execlave-sdk 1.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| execlave_sdk-1.8.0.tar.gz | 68.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| execlave_sdk-1.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 145.0 kB
Release files / execlave_sdk-1.8.0.tar.gz
| Download URL | execlave_sdk-1.8.0.tar.gz |
|---|---|
| Size | 68.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a79027aa5a46371736da806bd4b3fa1e2f95979c6c7fd5a4fc6ac5d586555254
|
|
BLAKE2b-256 checksum How to use checksums |
6ca37366855e7738c2390c1e0b64d9f01fde39ba93687c3f69475f0d0c533142
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / execlave_sdk-1.8.0-py3-none-any.whl
| Download URL | execlave_sdk-1.8.0-py3-none-any.whl |
|---|---|
| Size | 76.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c13f388461be634336cc916ba9e3870cae44746aaf30bac996a327350e94af66
|
|
BLAKE2b-256 checksum How to use checksums |
5fde18df7542a68f47e4e79e895cda95ef671d411af883f3d939655c62b3a84c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency log