Skip to main content

Regent Control — Python SDK

Runtime policy enforcement for AI agent actions. Every action your agent takes — a refund, a wire, a DB write, an API call — is authorized first: allow / deny / escalate, with a short-lived scoped token, the human it's acting for, the intent, and an immutable audit record.

pip install regent-control

Requires Python 3.10+. The only dependency is httpx.

Two ways to integrate

1. Gate-direct — RegentControl (you hold the provider key)

Authorize the action, get a scoped token, perform it, report the outcome.

from regent_control import RegentControl, MandateExceeded, Escalated

control = RegentControl(api_key="rgnt_ctrl_…", agent_id="agent_refund_bot")

decision = control.authorize(
    tool="payments", action="refund.create",
    amount_usd=50, mandate_id="mnd_support_refunds",
    idempotency_key="T-8842:ch_aaa",          # a retry won't double-refund
    user_token=rep_id_token,                  # the rep's OIDC token — verified by the gate
    intent="refund the duplicate charge on ticket 8842",
    facts={"account_status": "active", "refund_to_original": True},
)

if not decision.allowed:
    ...                                        # decision.code / decision.reason
do_refund(scoped_token=decision.token)         # the token authorizes the downstream call
control.complete(decision.decision_id, status="success", downstream_ref=refund_id)

A deny is a normal return value, not an exception. Opt into raising:

decision.raise_for_status()                    # raises MandateExceeded / PolicyDenied / Escalated / …
# or
control.authorize_or_raise(tool="payments", action="refund.create", amount_usd=999)

2. Sidecar-routing — SidecarSession (the agent holds no key)

Point your normal HTTP call at the sidecar; it injects the real vaulted credential and forwards. A policy deny comes back as a typed error.

from regent_control import SidecarSession, MandateExceeded

sc = SidecarSession(base_url="http://localhost:8080",
                    user_token=rep_id_token, intent="refund duplicate charge")
try:
    resp = sc.call("payments", "refunds", method="POST",
                   json={"charge": "ch_aaa", "amount": 50},
                   facts={"account_status": "active", "refund_to_original": True},
                   idempotency_key="T-8842:ch_aaa")
    refund = resp.json()
except MandateExceeded as e:
    ...                                        # e.code, e.reason, e.decision_id

Both clients have async twins: AsyncRegentControl and AsyncSidecarSession.

Wrap a tool in one line — @guarded

from regent_control import RegentControl, guarded

control = RegentControl(api_key="rgnt_ctrl_…", agent_id="agent_refund_bot")

@guarded(control, tool="payments", action="refund.create",
         amount_arg="amount_usd", mandate_id="mnd_support_refunds")
def issue_refund(*, charge: str, amount_usd: float, scoped_token: str = "") -> str:
    return provider.refund(charge, amount_usd, token=scoped_token)

issue_refund(charge="ch_1", amount_usd=50)     # authorized → runs → completed
issue_refund(charge="ch_1", amount_usd=999)    # raises MandateExceeded; never runs

The decorator authorizes before the call, injects the scoped token (if the function declares scoped_token), and reports success/failed to close the audit. Pass per-call context via a control_context={...} keyword.

Verify the scoped token at your service edge — regent_control.verify

The complement to the client: your downstream service validates the gate-issued scoped JWT against Regent's JWKS and enforces the scope itself (least privilege at the edge — no shared static key, no trusting the caller).

pip install "regent-control[verify]"   # adds PyJWT
from regent_control.verify import TokenVerifier, ScopeError

verifier = TokenVerifier(jwks_url="https://control-api.regentprotocol.org/v1/control/.well-known/jwks.json")
scoped = verifier.verify(token, expected_tool="payments", expected_action="refund.create")
# raises TokenError (bad sig / expired / wrong issuer|audience) or ScopeError (wrong scope)
# scoped.agent_id / scoped.decision_id are audit-ready

See examples/verify_service.py for a FastAPI dependency.

Develop locally with zero prod — regent-control dev

regent-control dev --port 8009 --deny-over 50 --escalate-over 500
# point any client at  base_url="http://localhost:8009"

In tests, force a verdict with the in-process mock:

from regent_control import RegentControl, MandateExceeded
from regent_control.dev import run_mock_control

def test_over_limit_is_denied():
    with run_mock_control(deny_over=50) as base_url:
        control = RegentControl(api_key="dev", agent_id="a", base_url=base_url)
        d = control.authorize("stripe", "refund.create", amount_usd=999)
        assert d.code == "MANDATE_LIMIT_EXCEEDED"

Coding agents — regent-control hook (Claude Code)

Claude Code runs shell hooks around every tool call. regent-control hook is those hooks: the money tool calls your agent makes (mcp__stripe__*, mcp__get4agent__buy, a curl to a payment API…) go through the Regent gate before they run, and every completed one leaves a signed receipt you can verify offline.

pip install regent-control
regent-control hook install claude-code --agent-id agt_… --key-file ~/.regent/control-key.txt
regent-control hook status

That writes three hooks into ~/.claude/settings.json (PreToolUse, PostToolUse, PostToolUseFailure, matcher mcp__.*) and a rule file at ~/.regent/hook.json:

{
  "mode": "observe",
  "agent_id": "agt_…",
  "mandate_id": "man_…",
  "rules": [
    {"match": "^mcp__stripe__.*", "amount": "amount", "divisor": 100, "currency": "currency", "payee": "customer"},
    {"match": "^mcp__get4agent__buy$", "amount": ["price", "amount"], "payee": "seller"},
    {"match": "^Bash$", "input_match": {"command": "api\\.stripe\\.com"}, "tool": "stripe", "action": "charge",
     "amount": "amount_cents", "divisor": 100, "currency": "const:USD"}
  ]
}
  • A tool call that matches no rule never touches the network.
  • observe (default): the gate decides and records, nothing is blocked; the verdict is shown to the agent as context. enforce: a deny or an escalation blocks the call with the gate's reason, and an unreachable gate fails closed (fail_open: true to change that).
  • An allow never bypasses Claude Code's own permission prompt — the gate adds a mandate check and evidence on top of the user's consent, it does not replace it.
  • PostToolUse closes the decision and saves the receipt to ~/.regent/receipts/<decision_id>.jwt; verify it with regent-verify (pip install regent-receipt-verify).
  • regent-control hook uninstall removes the hooks; the key is read from REGENT_CONTROL_KEY or the --key-file, never written into settings.json.

The same gate, from OpenClaw: the @regent-protocol/openclaw-regent plugin registers a before_tool_call hook with the identical rules (see plugins/openclaw-regent in this repo).

Typed errors

Exception Decision code Meaning
IdentityNotResolved IDENTITY_NOT_RESOLVED the agent id didn't resolve
AgentNotActive AGENT_NOT_ACTIVE the agent is suspended/revoked
PolicyDenied POLICY_DENIED a policy rule forbade it
ToolNotAllowed TOOL_NOT_ALLOWED the tool isn't in the agent's catalog
MandateNotFound MANDATE_NOT_FOUND a money action with no mandate
MandateExceeded MANDATE_LIMIT_EXCEEDED over the spend cap
RiskThresholdExceeded RISK_THRESHOLD_EXCEEDED risk score too high
VelocityExceeded VELOCITY_EXCEEDED too many decisions for this agent in the window; back off
DuplicateRequest DUPLICATE_REQUEST an identical money request was just allowed; pass an idempotency_key for a deliberate repeat
Escalated ESCALATION_REQUIRED needs a human approval (carries .escalation)

ControlError (transport/auth/5xx) and ControlNetworkError (never reached the plane) are always raised; everything above subclasses ControlDenied.

Request signing (optional)

Pass sign_requests=True to HMAC-sign the request body with the per-agent secret HMAC-SHA256(api_key, agent_id) (X-Agent-Signature). Identical to @regent/control-sdk (TypeScript), so an agent moves between the two unchanged.

Examples

Metadata

Release files for regent-control 0.2.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 regent-control 0.2.0
File Size Uploaded
regent_control-0.2.0.tar.gz 36.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for regent-control 0.2.0
File Interpreter ABI Platform
regent_control-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 71.3 kB

Release files / regent_control-0.2.0.tar.gz

Download URL regent_control-0.2.0.tar.gz
Size 36.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5176c8e1fa790f071239431b59cb0c4b5b5c12ef0f3eb6bd739b4f1331778045
BLAKE2b-256 checksum
How to use checksums
632004b81e8c9145b9f3d7908c47a03a80f75a03ecc60eac29130cfc94909eda
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 Oct 5, 2026.

Transparency log

Release files / regent_control-0.2.0-py3-none-any.whl

Download URL regent_control-0.2.0-py3-none-any.whl
Size 34.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c01055436d360a1c21f992c7db7e43d9d272daea735583ae7f30f763ee0b6d1
BLAKE2b-256 checksum
How to use checksums
9fe98e0cf024d4a4ec573787ab4e5e8ead87b60ec1ec2bfe0eb647492f6c9611
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 Oct 5, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.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