Configure in code
Configure via YAML (callguard.yaml)
Agent Sentinel will search for callguard.yaml in:
./callguard.yaml./.agent-sentinel/callguard.yaml$AGENT_SENTINEL_HOME/callguard.yaml
What happens on violation?
Policy checks run before your function executes:- Denied action / allowlist mismatch / rate limit →
PolicyViolationError - Budget exceeded →
BudgetExceededError - No policy loaded and the action writes →
NoPolicyForWriteError(see Enforcement modes)
Tracking current spend
Enforcement modes
The enforcement mode decides what happens when the policy layer cannot vouch for an action: no policy has been loaded, a remote sync has never produced a usable local cache, or policy evaluation itself raises an unexpected error.Declare impact on each action
@guarded_action takes impact, one of "read", "low", "medium" (the
default) or "high". Declare read-only tools as "read" or "low" so they keep
working before a policy is loaded:
Choosing a mode
Precedence is: explicit argument, thenAGENT_SENTINEL_ENFORCEMENT, then the
default.
fail_closed=True resolves to "fail_closed" and fail_closed=False to
"fail_open". Neither selects fail_closed_writes; leave the argument unset to
get the default. An unrecognised AGENT_SENTINEL_ENFORCEMENT value raises
ValueError rather than falling back to a permissive mode.
What strict fail_closed also covers
Under fail_closed every path that could otherwise fail open blocks instead:
- A kill-switch check that cannot complete (platform unreachable, non-200
response, or
httpxmissing) raisesKillSwitchUnavailableError, a subclass ofAgentKilledErrorwith reason codeKILL_SWITCH_UNAVAILABLE. - An unexpected exception inside policy evaluation is wrapped in
PolicyViolationErrorwith reason codeEVALUATION_ERROR. - A remote budget reservation that cannot complete raises
NetworkError(see Cost tracking).
These three checks only block under strict
fail_closed. Under the default
fail_closed_writes they log a warning and allow the action. Use fail_closed
if an unreachable platform must stop your agent.configure(fail_closed=True) on its own does not install a policy. A remote
sync that succeeds but returns no policies also leaves the engine unconfigured,
so fail_closed and fail_closed_writes keep blocking until real rules
arrive.