Skip to main content

Client runtime

actguard.Client is the runtime entry point. The active run state is stored in context and is required for runtime-scoped guards.
import actguard

client = actguard.Client.from_env()

with client.run(user_id="alice", run_id="req-123"):
    ...

Budget scopes

client.budget_guard(...) creates a budget scope attached to the active run.
with client.run(user_id="alice", run_id="req-123"):
    with client.budget_guard(name="root", usd_limit=0.10) as root:
        ...
        with client.budget_guard(name="search_tool", usd_limit=0.03) as search:
            ...
Key behavior:
  • Root and nested scopes are supported
  • Usage is exposed on guard.tokens_used and guard.usd_used
  • Exceeding configured USD limits raises BudgetExceededError
  • With gateway_url + api_key configured, root scope reserve/settle uses /api/v1/reserve and /api/v1/settle

budget_guard vs tool decorators

  • budget_guard enforces spend constraints before and during provider execution by creating reserve/settle-backed scope state for the run
  • Tool decorators (rate_limit, circuit_breaker, max_attempts, timeout, idempotent, prove, enforce, tool) apply invocation guards and emit guard/tool observability events
In short:
  • budget_guard is budget enforcement
  • Tool decorators are invocation controls + observability

Tool runtime context

These decorators require an active client.run(...):
  • max_attempts
  • idempotent
Without a run context, they raise MissingRuntimeContextError.

Chain-of-custody session

prove and enforce use session-scoped facts.
import actguard

with actguard.session("req-42", {"user_id": "u1"}):
    ...
Without an active session, both raise GuardError(code="NO_SESSION").

Event taxonomy

SDK event filtering modes:
  • off
  • significant
  • verbose
Current significant event set:
  • run.start
  • run.end
  • llm.usage
  • guard.blocked
  • guard.intervention
  • budget.limit_exceeded
  • budget.blocked
  • tool.invoke
  • tool.failure
Notes:
  • tool.invoke events are emitted only when ACTGUARD_EMIT_ALL_TOOL_RUNS is enabled (1, true, yes, or on)
  • tool.failure emits automatically for non-guard tool failures
  • The SDK does not emit lifecycle events like budget.reserved / budget.settled; those are gateway-side telemetry events
  • Event envelopes use snake_case wire keys

Optional standalone usage

You can run the Python SDK in a lighter mode for per-run budgeting and tool guards without full management-plane setup.
  • client.run(...) + tool decorators work without gateway management APIs
  • client.budget_guard(...) can still run locally, but reserve/settle-backed enforcement requires gateway config (gateway_url + api_key)

Patching model providers

Entering client.budget_guard(...) triggers provider patching through integration modules:
  • OpenAI
  • Anthropic
  • Google GenAI
The patching is idempotent and only affects active budget scopes.