GuardConfig Reference¶
GuardConfig is the single configuration object for @guard. All fields are optional with sensible defaults.
Field Reference¶
Validation Fields¶
validate_input: bool = False¶
Validate function arguments against Python type hints before the function runs.
@guard(validate_input=True)
def add(a: int, b: int) -> int:
return a + b
add(a="two", b=3) # Raises ValidationError
Works with: int, float, str, bool, list, dict, tuple, Pydantic models, TypedDict, Optional[X], Union[X, Y].
validate_output: bool = False¶
Validate the function's return value against its declared return type.
@guard(validate_output=True)
def get_user(id: int) -> dict:
return [1, 2, 3] # Raises ValidationError — expected dict, got list
detect_hallucination: bool = False¶
Run multi-signal hallucination detection on every call result.
When enabled, the guard checks execution time, schema compliance, and response patterns. Detected hallucinations raise HallucinationError (by default).
Resilience Fields¶
max_retries: int = 0¶
Number of automatic retry attempts on failure. 0 means no retries.
Uses exponential backoff: delays of 1s, 2s, 4s, ... up to max_delay with jitter.
For fine-grained control, use retry (see below).
retry: RetryConfig | None = None¶
Fine-grained retry configuration. Overrides max_retries when set.
from agentguard.core.types import RetryConfig
GuardConfig(retry=RetryConfig(
max_retries=5,
initial_delay=0.5, # seconds
max_delay=30.0, # seconds
backoff_factor=2.0, # multiplier per attempt
jitter=True, # randomise delay
retryable_exceptions=(ConnectionError, TimeoutError),
))
retryable_exceptions: only these exception types trigger a retry. If empty, any exception triggers a retry.
timeout: float | None = None¶
Maximum execution time in seconds. Raises TimeoutError when exceeded.
Sync functions: enforced via a background thread (blocking timeout).
Async functions: enforced via asyncio.wait_for.
timeout_config: TimeoutConfig | None = None¶
Fine-grained timeout configuration. Overrides timeout when set.
from agentguard.core.types import TimeoutConfig, GuardAction
GuardConfig(timeout_config=TimeoutConfig(
timeout_seconds=10.0,
on_timeout=GuardAction.WARN, # Don't raise — just warn
))
Budget Fields¶
budget: BudgetConfig | None = None¶
Cost and call-count budget enforcement.
from agentguard.core.types import BudgetConfig, GuardAction
GuardConfig(budget=BudgetConfig(
max_cost_per_call=0.10, # Max $0.10 per single call
max_cost_per_session=5.00, # Max $5.00 total for session
max_calls_per_session=100, # Max 100 calls per session
alert_threshold=0.80, # Warn at 80% usage
on_exceed=GuardAction.BLOCK, # Block when exceeded
cost_per_call=0.001, # Explicit fallback if dynamic pricing unavailable
use_dynamic_llm_costs=True, # Track real LLM cost from provider responses
model_pricing_overrides={"my-model": (1.0, 3.0)},
record_llm_spend=True,
))
Convenience: TokenBudget(max_cost_per_session=5.00).config.
model_pricing_overrides values are (input_dollars_per_1m, output_dollars_per_1m). When present, override pricing is used before LiteLLM. cost_ledger can be set to an implementation such as InMemoryCostLedger to retain spend events for reporting beyond the in-memory budget counters.
Rate Limiting Fields¶
rate_limit: RateLimitConfig | None = None¶
Token bucket rate limiter.
from agentguard.core.types import RateLimitConfig, GuardAction
GuardConfig(rate_limit=RateLimitConfig(
calls_per_second=2.0,
calls_per_minute=60.0,
calls_per_hour=500.0,
burst=5,
on_limit=GuardAction.BLOCK,
shared_key=None,
))
Convenience: RateLimiter(calls_per_minute=60).config.
shared_key=None shares by tool name, shared_key="" creates a per-instance
bucket, and any non-empty string creates a custom shared group.
Circuit Breaker Fields¶
circuit_breaker: CircuitBreakerConfig | None = None¶
Circuit breaker configuration.
from agentguard.core.types import CircuitBreakerConfig, GuardAction
GuardConfig(circuit_breaker=CircuitBreakerConfig(
failure_threshold=5, # Open after 5 consecutive failures
recovery_timeout=60.0, # Wait 60s before probing
success_threshold=1, # 1 success in HALF_OPEN to close
on_open=GuardAction.BLOCK, # Block when OPEN
))
Convenience: CircuitBreaker(failure_threshold=5, recovery_timeout=60).config.
Tracing Fields¶
record: bool = False¶
Write every call to the configured trace store.
trace_dir: str = "./traces"¶
Directory used for legacy JSONL traces or as the parent directory for the default SQLite database.
trace_backend: str = "sqlite"¶
Trace persistence backend. Use "sqlite" for the production default or "jsonl" for legacy file-backed traces.
trace_db_path: str | None = None¶
Explicit SQLite database path. When unset, agentguard stores traces in trace_dir/agentguard_traces.db.
session_id: str | None = None¶
Identifier for grouping related calls in a trace session. If None, a default session identifier is used.
Hook Fields¶
before_call: Callable[[ToolCall], None] | None = None¶
Called immediately before the tool function runs. Receives the ToolCall record.
def log_call(call: ToolCall) -> None:
logger.info(f"→ {call.tool_name}({call.kwargs})")
GuardConfig(before_call=log_call)
Raising an exception in before_call aborts the tool call.
after_call: Callable[[ToolCall, ToolResult], None] | None = None¶
Called immediately after the tool function completes (success or failure). Receives both the ToolCall and the ToolResult.
def update_metrics(call: ToolCall, result: ToolResult) -> None:
metrics.record(call.tool_name, result.execution_time_ms, result.status)
GuardConfig(after_call=update_metrics)
Validator Fields¶
custom_validators: list[Callable] = []¶
List of custom validator callables. Each must return a ValidationResult.
def no_dangerous_sql(call: ToolCall) -> ValidationResult:
if "DROP" in call.kwargs.get("sql", "").upper():
return ValidationResult(valid=False, kind=ValidatorKind.CUSTOM, message="Dangerous SQL")
return ValidationResult(valid=True, kind=ValidatorKind.CUSTOM)
GuardConfig(custom_validators=[no_dangerous_sql])
Complete Example¶
from agentguard import GuardConfig
from agentguard.core.types import (
RetryConfig,
TimeoutConfig,
BudgetConfig,
RateLimitConfig,
CircuitBreakerConfig,
GuardAction,
)
config = GuardConfig(
# Validation
validate_input=True,
validate_output=True,
detect_hallucination=True,
# Retries
retry=RetryConfig(
max_retries=3,
initial_delay=1.0,
max_delay=30.0,
backoff_factor=2.0,
jitter=True,
retryable_exceptions=(ConnectionError,),
),
# Timeout
timeout=30.0,
# Budget
budget=BudgetConfig(
max_cost_per_session=5.00,
max_calls_per_session=100,
alert_threshold=0.80,
),
# Rate limit
rate_limit=RateLimitConfig(
calls_per_minute=60,
burst=5,
),
# Circuit breaker
circuit_breaker=CircuitBreakerConfig(
failure_threshold=5,
recovery_timeout=60,
),
# Tracing
record=True,
trace_dir="./production_traces",
session_id="session_001",
)