Skip to main content
The decorator API is the recommended way to use the SDK. init() once at process startup, then decorate any function with @rubric.tool — every call routes through your policy bundle automatically. For multi-agent processes or tests where you need explicit lifecycle control, use the Governance class directly. The two coexist; the singleton wraps a Governance under the hood.

init()

Bootstraps the process-wide Governance singleton. Idempotent — call it once at startup and forget it. All arguments fall back to the same env vars as Governance.bootstrap(). Registers an atexit hook that flushes audit events on normal process exit. Hard kills (SIGKILL, OOM) skip the hook — by design. Returns the underlying Governance instance if you need it (rarely).

@tool

The decorator runs evaluate() before invoking the function. If the policy denies the call:
  • The underlying function is not invoked.
  • A GovernanceDeniedError is raised. It’s a PermissionError subclass; catch either.
The function’s positional arguments land in the audit event’s metadata.args; keyword arguments in metadata.kwargs. Match those in your policies:

session()

Context manager that sets the session id for any @rubric.tool calls inside the block. Falls back to default_session_id (default "default") outside any scope. ContextVars under the hood — propagates across await points within the same task. Safe in async code and threadpools.

trace()

Context manager that binds a TraceContext for tool calls in scope. Every governed call uploads the running transcript so the dashboard’s drawer has the conversation behind each audit row.

evaluate()

For ad-hoc evaluations outside a @rubric.tool-decorated function:
Module-level shim around gov.evaluate(). Reads the singleton, the session ContextVar, and the trace ContextVar — pass explicit overrides only if you need to.

shutdown()

Stops the singleton and flushes in-flight audit events. Called automatically by the atexit hook on normal exit. Safe to call manually for explicit cleanup (tests, child-process forks).

Errors

When NOT to use the singleton

  • Multiple agents in one process. Use Governance.bootstrap() directly with a fresh instance per agent. The singleton supports exactly one identity at a time.
  • Tests. Pass an explicit Governance(token_store=...) so each test starts fresh.
  • Library code. A library shouldn’t claim the process-wide singleton on its consumer’s behalf. Accept a Governance instance via dependency injection instead.
For the 99% case (one agent per process, application code), the decorator API is the right choice.