Skip to content

Error Handling Guide

How to handle errors, exceptions, and policy violations in the Agent Governance Toolkit.

Overview

Every error returned by the Agent Governance Toolkit includes a structured GovernanceError that describes what happened, which policy was involved, and what action was taken. This lets callers implement retry logic, user-facing messaging, and audit logging consistently.

Error Types

PolicyViolationError

Raised when an agent action is denied by a policy rule.

from agent_os.exceptions import PolicyViolationError

try:
    result = evaluator.evaluate({"tool_name": "delete_file"})
except PolicyViolationError as e:
    print(f"Action '{e.action}' on tool '{e.tool_name}' was denied by rule '{e.rule_id}'")
    print(f"Policy: {e.policy_name} v{e.policy_version}")
    print(f"Timestamp: {e.timestamp}")

Attributes:

Attribute Type Description
action str The action that was denied (e.g., "tool_call")
tool_name str Name of the tool the agent tried to call
rule_id str ID of the specific rule that triggered the denial
policy_name str Name of the policy document containing the rule
policy_version str Version of the policy document
timestamp datetime When the violation occurred
agent_id str\|None Identity of the agent that attempted the action
context dict Additional context fields matched by the rule

Manifest validation errors

validate_manifest raises RuntimeError when a manifest fails to parse or validate. There is no dedicated PolicyLoadError type.

from pathlib import Path

from agent_control_specification import validate_manifest

path = Path("policies/my-policy.yaml")
try:
    validate_manifest(path.read_text(encoding="utf-8"))
except RuntimeError as exc:
    # The runtime reports the offending field in the message, prefixed with
    # runtime_error:manifest_invalid.
    print(f"Failed to load {path}: {exc}")

AuditWriteError

Raised when the audit log fails to persist. The governance engine continues operating (fail-open for audit) but records the failure.

from agent_os.exceptions import AuditWriteError

try:
    auditor.record(event)
except AuditWriteError as e:
    logger.warning(f"Audit write failed: {e.backend}, falling back to local buffer")
    # Governance continues — audit is best-effort

TrustScoreError

Raised when trust scoring computation encounters an invalid state.

from agent_os.trust import TrustScoreError

try:
    score = trust_engine.compute_score(agent_id, action_context)
except TrustScoreError as e:
    print(f"Trust computation failed: {e.reason}")
    # Fall back to deny-or-allow default for this agent

Error Handling Patterns

Pattern 1: Validate Before Evaluate

Catch policy load errors at startup to fail fast with a clear message.

from pathlib import Path
from typing import Any

from agent_control_specification import parse_manifest


def load_manifests(paths: list[str]) -> list[dict[str, Any]]:
    manifests = []
    for path in paths:
        try:
            manifests.append(parse_manifest(Path(path).read_text(encoding="utf-8")))
        except (OSError, RuntimeError) as exc:
            raise RuntimeError(f"Manifest load failed for {path!r}: {exc}") from exc
    return manifests

Pattern 2: Graceful Degradation on Audit Failure

Audit writes should not block policy enforcement.

from agent_os.audit import AuditLogger
import logging

audit = AuditLogger(backend="cloud-watch", fail_open=True)

def execute_with_governance(agent, action):
    result = evaluator.evaluate({"tool_name": action.tool_name, "agent_id": agent.id})
    if result.effect == "deny":
        try:
            audit.log_violation(agent.id, action, result.rule)
        except AuditWriteError:
            pass  # fail-open: governance decision stands
        raise PermissionError(f"Action '{action.tool_name}' denied by policy")
    return agent.execute(action)

Pattern 3: Retry on Transient Errors

Use exponential backoff for recoverable errors (network, rate limiting).

import time

def evaluate_with_retry(evaluator, context, max_retries=3, base_delay=0.1):
    last_error = None
    for attempt in range(max_retries):
        try:
            return evaluator.evaluate(context)
        except TransientGovernanceError as e:
            last_error = e
            if attempt < max_retries - 1:
                time.sleep(base_delay * (2 ** attempt))
            continue
    raise last_error

Pattern 4: Per-Agent Fallback Policies

When a trust score cannot be computed, apply a fallback rule specific to the agent tier.

def evaluate_agent_action(agent_id, action, trust_engine, evaluator):
    try:
        return evaluator.evaluate({"tool_name": action, "agent_id": agent_id})
    except TrustScoreError:
        # Tier-based fallback
        tier = agent_tier_map.get(agent_id, "standard")
        fallback_rule = fallback_policies[tier]
        return PolicyResult(effect=fallback_rule, source="trust-fallback")

Structured Error Logging

All governance errors should be logged with consistent structured fields for observability.

import json
import logging

logger = logging.getLogger("governance.errors")

def log_policy_violation(error: PolicyViolationError):
    logger.warning(
        "policy_violation",
        extra={
            "event_type": "policy_violation",
            "agent_id": error.agent_id,
            "action": error.action,
            "tool_name": error.tool_name,
            "rule_id": error.rule_id,
            "policy_name": error.policy_name,
            "policy_version": error.policy_version,
            "context": error.context,
            "timestamp": error.timestamp.isoformat(),
        }
    )

Suppressing Known Violations

In testing or controlled environments, you may need to suppress specific policy violations for known-trusted agents.

from agent_os.policies import suppress_rule

# Suppress the delete_file rule for the ci-test agent
suppress_rule(
    rule_id="block-dangerous-tools",
    agent_id="did:mesh:ci-test-agent",
    reason="E2E test fixture — controlled environment",
    expires_at="2026-12-31T23:59:59Z",
)

Note: Suppressions are audit-logged even when the action is allowed. Do not use suppressions in production unless explicitly required and documented in your runbook.

Error Code Reference

Code Name Description
GOV001 POLICY_NOT_FOUND Referenced policy does not exist
GOV002 RULE_EVALUATION_FAILED Rule condition could not be evaluated
GOV003 TRUST_SCORE_UNAVAILABLE Trust engine returned no score
GOV004 AUDIT_BACKEND_UNAVAILABLE Audit log write failed
GOV005 INVALID_POLICY_DOCUMENT Policy YAML failed schema validation
GOV006 AGENT_IDENTITY_INVALID Agent DID could not be verified

Getting Help