Spend guard

Alerts tell you a runaway happened. The guard stops the next one from starting.

Everything else in AgentPing observes your agents without touching them. The guard is the one exception, and you opt into it: a single call at the top of a scheduled or autonomous script that asks "am I clear to run?" before the expensive work begins. AgentPing checks your rules against your real cumulative spend and answers. If a rule has tripped, or you have paused the agent from the dashboard, the run does not start.

Guard is available on the Team and Business plans. On other plans the call always allows the run, so adding it early is safe; see What happens on other plans.

Add the check

One call, at the top, before the expensive work begins.

from agentping import guard

guard.check(customer_ref="acme-corp", agent="nightly-summariser", function="run")

Set your rules

Rules live in Settings, Guard. Each rule sets a threshold on total spend, spend within a window, or a run count, keyed on any combination of customer, agent, and function. When your script calls the guard, the server evaluates every rule whose dimensions match what you sent.

The figure compared against your threshold is the cumulative spend AgentPing has already priced and stored, the same number your dashboard shows. There is no counter to maintain in your own code and no local state to drift out of sync.

The same settings page has a pause switch per agent. Flip it and the next checkpoint refuses to run, from anywhere, without a deploy.

Hard and soft modes

By default the guard is hard: a blocked check raises an exception (Paused in Python, TypeScript, and Laravel; a *Paused error in Go), so the script stops right there. The exception carries the full verdict, including which rule tripped.

import agentping, sys

try:
    agentping.guard.check(agent="nightly-summariser")
except agentping.Paused as e:
    print("blocked by", e.verdict.blocked_by, e.verdict.rules)
    sys.exit(0)

In soft mode the call never raises; it returns the verdict and you decide what to do with it.

v = agentping.guard.check(agent="nightly-summariser", mode="soft")
if v.blocked:
    sys.exit(0)

If AgentPing is unreachable

You choose what happens when the check cannot reach us:

  • The default is fail closed (on_unreachable="block"): if AgentPing cannot be reached, the script does not run. For a safety gate this is the conservative choice; a guard that waves runs through when it cannot check anything is not much of a guard.
  • Set on_unreachable="allow" to fail open: the run proceeds when the gate is unreachable.

Fail closed ties your scheduled runs to AgentPing's availability, so it is a real trade. Pick it for the agents where an unchecked run is worse than a skipped one, and fail open for the ones that must run regardless.

If the check is rate limited rather than unreachable, the SDK retries once and then allows the run, even under on_unreachable="block". A busy moment on our side never blocks a legitimate agent.

Checkpoints, and how many to place

A guard call protects the point where you place it. One call at the top of the script stops the next scheduled run from starting after a rule trips; it cannot stop a run that already passed the check and then got stuck in a loop.

For tighter control, place the same call at more than one point: the top of a loop, between phases of a long job.

for batch in batches:
    agentping.guard.check(agent="nightly-summariser", function="batch")
    process(batch)

Each call is one more place a tripped rule or a dashboard pause takes effect. A rule trip and the pause switch both apply at the next checkpoint, not mid-run, so the more checkpoints you place, the sooner a stop lands.

Thresholds are in USD

Spend is stored and compared in USD, with no currency conversion, so set your thresholds in USD too: a cap of $650, not £500. Your threshold always compares against the same number the dashboard shows, unaffected by exchange-rate movement.

What happens on other plans

On plans without Guard, the call is a no-op that always allows, never a block, so a fail-closed script is never killed for being on the wrong plan. The SDK logs one clear warning that the script is running unguarded, and the dashboard flags it. You will never be blocked for being on the wrong plan, and you will never be told you are protected when you are not.