riskkernel (Python SDK)
The Python SDK for RiskKernel — Surface 2, deep control over a governed agent run.
It is a thin client over the self-hosted RiskKernel daemon. Every deterministic decision — budgets, loop/time halts, approval policy — happens in the Go core. The SDK just makes governed runs ergonomic from Python. Core install is stdlib-only (no third-party dependencies).
pip install riskkernel
Quickstart
import riskkernel as rk
rt = rk.Runtime(base_url="http://localhost:7070") # your daemon
with rt.governed_run(name="research",
budget=rt.budget(dollars=1.00, loops=20, seconds=300)) as run:
# Route your LLM client through the governing proxy so every model call is
# metered, priced, and budget-enforced under this run:
cfg = run.proxy_config()
# cfg["base_url"] -> http://localhost:7070/v1
# cfg["headers"] -> {"X-RiskKernel-Run-Id": "<run id>"}
for _ in range(100):
run.step() # raises rk.BudgetExceeded when loops/time run out
# ... your agent reasoning + tool calls ...
run.checkpoint("after-step", {"messages": messages})
When the governor halts the run (token / dollar / loop / time budget), the next
run.step() — or a proxied model call — raises rk.BudgetExceeded.
Resume after a crash
The daemon reloads non-terminal runs on restart with the budget and usage they had
already spent, so a SIGKILL'd run keeps enforcing without re-spending. Reattach to
it by id with resume_run and pick your work back up from the last checkpoint:
with rt.resume_run(run_id) as run: # attaches; never creates or cancels
cp = run.latest_checkpoint() # the state you saved before the crash
start = cp["payload"]["cursor"] if cp else 0
for i in range(start, total): # skip the steps you already paid for
run.step() # counts against the SAME budget
# ... your work ...
run.checkpoint("step", {"cursor": i + 1})
The run resumes against whatever budget it had left, so it can't overspend by
restarting — run.step() still raises rk.BudgetExceeded at the original ceiling.
Human-in-the-loop tools
Gate side-effecting tools on human approval (the daemon's policy decides what needs it; the call blocks until a human resolves it via CLI / web / webhook):
from riskkernel import governed_tool, ApprovalGate
@governed_tool(side_effect="write")
def write_file(path, content):
... # only runs if approved; else rk.ApprovalDenied
# or explicitly:
gate = ApprovalGate(run)
if gate.allow("mcp://shell", side_effect="exec", arguments={"cmd": cmd}):
run_shell(cmd)
Framework adapters
Lazy-imported, so you only pay for what you use:
# LangChain / LangGraph — enforces loop/time budgets per LLM call
from riskkernel.adapters.langchain import RiskKernelCallbackHandler
llm.invoke(prompt, config={"callbacks": [RiskKernelCallbackHandler(run)]})
# LlamaIndex — a CallbackHandler that enforces loop/time budgets per LLM call
from llama_index.core import Settings
from llama_index.core.callbacks import CallbackManager
from riskkernel.adapters.llama_index import RiskKernelCallbackHandler
Settings.callback_manager = CallbackManager([RiskKernelCallbackHandler(run)])
# Claude Agent SDK — PreToolUse approval hook
from riskkernel.adapters.claude_agent import make_pre_tool_use_hook
hook = make_pre_tool_use_hook(run, side_effect_for={"Bash": "exec", "Write": "write"})
# OpenAI Agents SDK — RunHooks (steps + tool approval)
from riskkernel.adapters.openai_agents import RiskKernelRunHooks
hooks = RiskKernelRunHooks(run, gate_tools=True)
# CrewAI — a step_callback (one governed step per agent step; halts the crew at budget)
from riskkernel.adapters.crewai import RiskKernelStepCallback
crew = Crew(agents=[...], tasks=[...], step_callback=RiskKernelStepCallback(run))
# AutoGen (v0.4+) — wrap the model client; one governed step per model call
from riskkernel.adapters.autogen import GovernedChatCompletionClient
client = GovernedChatCompletionClient(model_client, run) # drop-in for the real client
agent = AssistantAgent("assistant", model_client=client) # halts the agent at budget
# PydanticAI — wrap your model (one governed step per model request; halts the agent at budget)
from pydantic_ai import Agent
from riskkernel.adapters.pydantic_ai import govern
agent = Agent(govern("anthropic:claude-sonnet-4-5", run, gate_tools=True))
AutoGen halts the run either way, but a team (
RoundRobinGroupChat, …) re-raises the halt as aRuntimeError; wrap the team call inwith governed_run_errors():(from the same module) to get the typedrk.BudgetExceededback. A single agent run propagates it typed already.
Configuration
Runtime(base_url=..., token=...), or the env vars RISKKERNEL_BASE_URL and
RISKKERNEL_API_TOKEN (used by the decorator/convenience API and default_runtime()).
License
Apache-2.0.
Metadata
Release files for riskkernel 0.7.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 | |
|---|---|---|---|
| riskkernel-0.7.0.tar.gz | 30.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| riskkernel-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 58.5 kB
Release files / riskkernel-0.7.0.tar.gz
| Download URL | riskkernel-0.7.0.tar.gz |
|---|---|
| Size | 30.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0bedd0d8ca28030fc14b167a9f68b4ff09ee80c9b0b35c167e7e0dc6f14e097c
|
|
BLAKE2b-256 checksum How to use checksums |
7c0d90a2abddeff50f6e35f0a071357679230e71c3433165ee4a3e753b449065
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 14, 2026.
Transparency logRelease files / riskkernel-0.7.0-py3-none-any.whl
| Download URL | riskkernel-0.7.0-py3-none-any.whl |
|---|---|
| Size | 27.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b3bf01bf7cb8b57527abd21a53c2b468421daa43a82b23c107872139a956f557
|
|
BLAKE2b-256 checksum How to use checksums |
33b333a6997908d1ba51622a08704973ac430e7abea65bc87945a1717af62af6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 14, 2026.
Transparency log