Skip to main content

Error Handling

Governance decisions surface as Python exceptions raised inside your agent's tool calls. The SDK raises typed exceptions that you can catch and handle in your own code.

All governance exceptions are re-exported from openbox_langgraph and available directly from openbox_deepagent.

Governance Exceptions

ExceptionRaised whenDescription
GovernanceBlockedErrorPolicy verdict is BLOCKA single tool call was blocked. The agent can continue.
GovernanceHaltErrorPolicy verdict is HALT, or approval rejected/expiredThe entire agent session is terminated.
GuardrailsValidationErrorGuardrails detect PII, toxic content, or policy violationThe model call or tool input was rejected before execution.
ApprovalRejectedErrorA human rejected an approval requestAutomatically converted to GovernanceHaltError by the middleware.
ApprovalExpiredErrorApproval timed out without a decisionAutomatically converted to GovernanceHaltError by the middleware.
ApprovalRejectedError and ApprovalExpiredError

These two exceptions are caught and re-raised as GovernanceHaltError by the middleware. You will never see them directly unless you inspect the __cause__ of a GovernanceHaltError. Handle GovernanceHaltError to cover all approval failure cases.

Import

from openbox_deepagent import (
GovernanceBlockedError,
GovernanceHaltError,
GuardrailsValidationError,
)

Handling Patterns

Wrapping ainvoke()

The simplest approach — catch governance errors at the top level:

from openbox_deepagent import GovernanceBlockedError, GovernanceHaltError, GuardrailsValidationError

try:
result = await agent.ainvoke(
{"messages": [{"role": "user", "content": "Research AI safety"}]},
config={"configurable": {"thread_id": "session-001"}},
)
except GovernanceHaltError as e:
# Session terminated — HALT verdict, or approval rejected/expired
logger.error(f"Agent session halted: {str(e)}")
# Clean up session state, notify the user, etc.
return {"status": "halted", "reason": str(e)}

except GovernanceBlockedError as e:
# A tool was blocked but the session is still live
# Typically surfaces here only if the agent re-raises it
logger.warning(f"Tool blocked: {str(e)}")
return {"status": "blocked", "reason": str(e)}

except GuardrailsValidationError as e:
# PII or content policy violation in a model call or tool input
logger.warning(f"Guardrails triggered: {str(e)}")
return {"status": "guardrails", "detail": str(e)}

Per-Tool Error Handling

If you wrap individual tool calls (e.g. in a custom tool executor), handle errors at that level:

from openbox_deepagent import GovernanceBlockedError

async def safe_tool_call(tool_fn, *args, **kwargs):
try:
return await tool_fn(*args, **kwargs)
except GovernanceBlockedError as e:
logger.warning(f"Tool blocked by governance: {str(e)}")
# Return a safe fallback instead of raising
return f"[Tool blocked: {str(e)}]"

Configuration Exceptions

These are raised during create_openbox_middleware() initialization — not during agent execution. Handle them where you set up your agent:

ExceptionCause
OpenBoxErrorBase class for all SDK configuration errors
OpenBoxAuthErrorInvalid or missing API key
OpenBoxNetworkErrorCannot reach OpenBox Core at startup
OpenBoxInsecureURLErrorHTTP URL used for a non-localhost address
from openbox_deepagent import (
OpenBoxError,
OpenBoxAuthError,
OpenBoxNetworkError,
OpenBoxInsecureURLError,
)

try:
middleware = create_openbox_middleware(
api_url=os.getenv("OPENBOX_URL"),
api_key=os.getenv("OPENBOX_API_KEY"),
)
except OpenBoxAuthError:
logger.error("Invalid OPENBOX_API_KEY — check your credentials")
raise
except OpenBoxInsecureURLError:
logger.error("OPENBOX_URL must use HTTPS for non-localhost URLs")
raise
except OpenBoxNetworkError:
logger.error("Cannot reach OpenBox Core — check OPENBOX_URL and network")
raise

Best Practices

  1. Catch GovernanceHaltError at the session level — it means the agent should not continue running
  2. Treat GovernanceBlockedError as recoverable — a single blocked tool does not end the session
  3. Log with context — include the full exception message to correlate with the Dashboard event log
  4. Don't catch and ignore — governance exceptions are intentional; suppressing them defeats the purpose
  5. Handle GuardrailsValidationError separately — it fires before execution, so no side effects have occurred

Debugging

Enable verbose SDK logging to see governance decisions as they happen:

OPENBOX_DEBUG=1 python agent.py

This logs every middleware hook invocation, governance request, and decision verdict to stderr.

You can also inspect the full event trace in the OpenBox Dashboard under Agents → your agent → DetailsEvent Log Timeline.

Next Steps

  1. Event Types — Understand the semantic event types that trigger governance decisions
  2. Approvals — Review and process HITL requests in the dashboard
  3. Policies — Write Rego policies that produce these decisions