Python SDK
Full reference for the SidClaw Python SDK — sync and async clients, framework wrappers, MCP proxy, and webhooks.
Python SDK
The SidClaw Python SDK (sidclaw) provides both synchronous and asynchronous clients for governing AI agent actions.
Installation
pip install sidclawWith framework extras:
pip install sidclaw[langchain] # LangChain support
pip install sidclaw[mcp] # MCP governance proxyClient Initialization
Synchronous Client
from sidclaw import SidClaw
client = SidClaw(
api_key="ai_...",
agent_id="ag_abc123",
# base_url="https://api.sidclaw.com", # default
# max_retries=2, # default
# timeout=30.0, # default, seconds
)The sync client supports context managers:
with SidClaw(api_key="ai_...", agent_id="ag_abc123") as client:
result = client.evaluate({"operation": "read", "target_integration": "database"})Asynchronous Client
from sidclaw import AsyncSidClaw
client = AsyncSidClaw(
api_key="ai_...",
agent_id="ag_abc123",
)The async client also supports context managers:
async with AsyncSidClaw(api_key="ai_...", agent_id="ag_abc123") as client:
result = await client.evaluate({"operation": "read", "target_integration": "database"})Core Methods
evaluate()
Evaluate an action against the policy engine.
from sidclaw import SidClaw, EvaluateParams
client = SidClaw(api_key="ai_...", agent_id="ag_abc123")
result = client.evaluate(EvaluateParams(
operation="send_email",
target_integration="email_service",
resource_scope="customer_emails",
data_classification="confidential",
context={"recipient": "[email protected]"},
))
print(result.decision) # "allow" | "approval_required" | "deny"
print(result.trace_id) # "tr_..."
print(result.approval_request_id) # "ar_..." (if approval_required)
print(result.reason) # human-readable reason
print(result.policy_rule_id) # matched policy rule IDAsync:
result = await async_client.evaluate(EvaluateParams(...))wait_for_approval()
Poll until a human reviewer approves or denies an action.
from sidclaw import ApprovalTimeoutError, ApprovalExpiredError
try:
status = client.wait_for_approval(
result.approval_request_id,
options={"timeout": 300, "poll_interval": 2},
)
print(status.status) # "approved" | "denied"
print(status.decision_note) # reviewer's note
except ApprovalTimeoutError:
print("No reviewer responded in time")
except ApprovalExpiredError:
print("Approval request expired on server")Async:
status = await async_client.wait_for_approval(result.approval_request_id)record_outcome()
Record what happened after an action executed.
client.record_outcome("tr_...", {"status": "success"})
# Or with error details:
client.record_outcome("tr_...", {
"status": "error",
"metadata": {"error": "Connection refused"},
})with_governance() Decorator
Wrap any function with automatic policy evaluation, approval handling, and outcome recording:
from sidclaw import SidClaw
from sidclaw.middleware.generic import with_governance, GovernanceConfig
client = SidClaw(api_key="ai_...", agent_id="ag_abc123")
@with_governance(client, GovernanceConfig(
operation="send_email",
target_integration="email_service",
data_classification="confidential",
))
def send_email(to: str, subject: str, body: str):
email_service.send(to=to, subject=subject, body=body)
# Now governed — call normally:
send_email("[email protected]", "Follow-up", "Hello...")Async version:
from sidclaw import AsyncSidClaw
from sidclaw.middleware.generic import async_with_governance, GovernanceConfig
async_client = AsyncSidClaw(api_key="ai_...", agent_id="ag_abc123")
@async_with_governance(async_client, GovernanceConfig(
operation="send_email",
target_integration="email_service",
data_classification="confidential",
))
async def send_email(to: str, subject: str, body: str):
await email_service.send(to=to, subject=subject, body=body)Framework Wrappers
LangChain
from sidclaw import SidClaw
from sidclaw.middleware.langchain import govern_tools
client = SidClaw(api_key="ai_...", agent_id="ag_abc123")
# Wrap all tools at once
governed_tools = govern_tools(my_tools, client=client)
# Or wrap individually with options
from sidclaw.middleware.langchain import govern_tool
governed = govern_tool(
my_tool,
client=client,
target_integration="database",
data_classification="confidential",
)See LangChain Integration for full details.
OpenAI Agents
from sidclaw.middleware.openai_agents import govern_function_tool
governed = govern_function_tool(
my_tool,
client=client,
target_integration="external-api",
)See OpenAI Agents Integration for full details.
CrewAI
from sidclaw.middleware.crewai import govern_crewai_tool
governed = govern_crewai_tool(
my_tool,
client=client,
target_integration="production",
)See CrewAI Integration for full details.
Pydantic AI
from sidclaw.middleware.pydantic_ai import GovernanceDependency
gov = GovernanceDependency(async_client)
@agent.tool
async def my_tool(ctx: RunContext[Deps]) -> str:
await gov.check("my_tool", target_integration="my-service")
return do_something()See Pydantic AI Integration for full details.
MCP Governance Proxy
Wrap any MCP tool server with governance:
from sidclaw.mcp import GovernanceMCPServer, GovernanceMCPServerConfig
server = GovernanceMCPServer(GovernanceMCPServerConfig(
api_key="ai_...",
agent_id="ag_abc123",
upstream_command="npx",
upstream_args=["-y", "@modelcontextprotocol/server-postgres", "postgresql://..."],
))
await server.start()Or use the CLI:
pip install sidclaw[mcp]
sidclaw-mcp-proxy \
--api-key ai_... \
--agent-id ag_abc123 \
--upstream-command npx \
--upstream-args "-y @modelcontextprotocol/server-postgres postgresql://..."See MCP Integration for full details.
Webhook Verification
Verify incoming webhook signatures:
from sidclaw import verify_webhook_signature
is_valid = verify_webhook_signature(
payload=request.body,
signature=request.headers["x-sidclaw-signature"],
secret="whsec_...",
)Error Handling
All errors inherit from SidClawError:
from sidclaw import (
SidClawError, # base
APIError, # HTTP errors (status_code, code, request_id)
ActionDeniedError, # 403 — policy denied (reason, trace_id, policy_rule_id)
ApprovalTimeoutError, # client-side timeout waiting for approval
ApprovalExpiredError, # 410 — server expired the request
RateLimitError, # 429 — rate limit (retry_after)
AuthenticationError, # 401 — invalid API key
PlanLimitError, # 402 — plan limit reached (limit_name, current, max)
)
try:
result = client.evaluate(params)
except ActionDeniedError as e:
print(f"Denied: {e.reason}, trace: {e.trace_id}")
except RateLimitError as e:
print(f"Rate limited, retry after {e.retry_after}s")
except AuthenticationError:
print("Invalid API key")
except PlanLimitError as e:
print(f"Limit reached: {e.limit_name} ({e.current}/{e.max})")Type Reference
The SDK uses Pydantic models for all request/response types:
from sidclaw import (
EvaluateParams, # operation, target_integration, resource_scope, data_classification, context
EvaluateResponse, # decision, trace_id, approval_request_id, reason, policy_rule_id
RecordOutcomeParams, # status, metadata
ApprovalStatusResponse, # status, decision_note
WaitForApprovalOptions, # timeout, poll_interval
DataClassification, # "public" | "internal" | "confidential" | "restricted"
PolicyEffect, # "allow" | "approval_required" | "deny"
ApprovalStatus, # "pending" | "approved" | "denied" | "expired"
RiskClassification, # "low" | "medium" | "high" | "critical"
)