STEERPLANE

The @guard Decorator

Wrap any function to enforce cost, step, loop, and policy guardrails in-process.

The @guard decorator is the simplest way to put an agent under SteerPlane control. It wraps the function that runs your agent and routes every step through the guardrail pipeline — without changing the agent logic itself.

from steerplane import guard

@guard(
    agent_name="support_bot",
    max_cost_usd=10.00,
    max_steps=50,
    denied_actions=["delete_*", "drop_*"],
    enforcement="alert",
    alert_threshold=0.8,
    alert_timeout_sec=1800,
)
def run_support_agent():
    agent.run()

Parameters

ParameterTypeDescription
agent_namestrHuman-readable name shown in the dashboard and logs.
max_cost_usdfloatPer-run cost ceiling in USD. Overshoot is bounded to one step.
max_stepsintMaximum number of execution steps before termination.
denied_actionslist[str]Glob patterns for actions to block (e.g. delete_*).
enforcement"kill" | "alert"How to react to a breach. See enforcement modes.
alert_thresholdfloatFraction of a limit (0–1) at which alert mode pauses for approval.
alert_timeout_secintHow long to wait for human approval before terminating.

Context-manager API

For finer control — logging individual steps, custom action names, or nested runs — use the SteerPlane context manager instead of the decorator:

from steerplane import SteerPlane

sp = SteerPlane(agent_id="support_bot")

with sp.run(max_cost_usd=10, max_steps=50) as run:
    run.log_step("search_web", tokens=1200, cost=0.004)
    run.log_step("summarize", tokens=800, cost=0.002)

Both APIs enforce the same guarantees: loop detection, cost ceilings, step limits, and policy rules.

Loops and policy violations always hard-terminate the run, regardless of the enforcement setting — they are a non-overridable safety invariant.

Getting the active run

Inside a guarded function (or anywhere in its call stack), get_active_run() returns the currently running RunManager — useful in helper functions that don't have direct access to the run object created by sp.run(...).

from steerplane import get_active_run

def helper():
    run = get_active_run()
    if run:
        run.log_step("helper_call", tokens=50)

Exceptions reference

Every guardrail raises a subclass of SteerPlaneError when it fires:

ExceptionRaised when
LoopDetectedErrorA repeating action pattern is detected by the loop detector.
CostLimitExceededCumulative run cost exceeds max_cost_usd.
StepLimitExceededThe number of steps exceeds max_steps.
PolicyViolationErrorAn action is blocked by the policy engine (deny list, missing from allow list, rate limit, or denied approval).
RunTerminatedErrorA run is forcefully terminated (e.g. manually via the CLI or dashboard).
APIConnectionErrorThe SDK cannot reach the SteerPlane control-plane API (only relevant when not running fully offline).
SteerPlaneErrorBase class for all of the above — catch this to handle any guardrail violation generically.
from steerplane import SteerPlaneError, CostLimitExceeded, LoopDetectedError

try:
    run_support_agent()
except CostLimitExceeded as e:
    print(f"Stopped at ${e.current_cost:.2f} (limit ${e.max_cost:.2f})")
except LoopDetectedError as e:
    print(f"Loop pattern {e.pattern} in last {e.window_size} actions")
except SteerPlaneError as e:
    print(f"Guardrail violation: {e}")

Works offline

If the SteerPlane control plane is unreachable, the decorator keeps enforcing locally (loop detection, cost, step, and policy rules), and alert mode automatically degrades to kill mode. See graceful degradation.

On this page