Skip to main content

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 a RuntimeError; wrap the team call in with governed_run_errors(): (from the same module) to get the typed rk.BudgetExceeded back. 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.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for riskkernel 0.9.0
File Size Uploaded
riskkernel-0.9.0.tar.gz 30.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for riskkernel 0.9.0
File Interpreter ABI Platform
riskkernel-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 58.5 kB

Release files / riskkernel-0.9.0.tar.gz

Download URL riskkernel-0.9.0.tar.gz
Size 30.9 kB
Tags Source
SHA-256 checksum
How to use checksums
c3189e77e8dd9622d53af011faa02bf0633148156ca7e8fa7e440df2bfcf750b
BLAKE2b-256 checksum
How to use checksums
1aaef381155ea039877dc8f3a1c493a525521fa155d0e03977931b39562b0e9e
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 20, 2026.

Transparency log

Release files / riskkernel-0.9.0-py3-none-any.whl

Download URL riskkernel-0.9.0-py3-none-any.whl
Size 27.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d399ee348f12c8315bfe85e68e1cf521b7e4e7b1e7c1cfc679ad5837b9d23165
BLAKE2b-256 checksum
How to use checksums
ac488c9566ba7049e23d1c1d290a145f9712cf88a928035397e73fdca2adeb91
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 20, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.0 This release

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page