Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .cspell-repo-terms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,11 @@ sybil
davidequarracino
Marp
Slidev
classmethod
Docstrings
isort
mypy
Pydantic
pytest
pyupgrade
xfail
14 changes: 14 additions & 0 deletions agent-governance-python/agent-os/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ ruff format .
- Event types: `GovernanceEventType.POLICY_CHECK`, `.POLICY_VIOLATION`, `.TOOL_CALL_BLOCKED`, `.CHECKPOINT_CREATED`
- Tests go in `tests/` (unit) or `modules/*/tests/` (module-specific)

## Policy Check Result (additive)

Policy checks should prefer the additive `*_execute_check` methods when new code needs structured denial data, while preserving the legacy tuple-returning methods for compatibility. Raise the canonical `PolicyViolationError.from_check_result(result)` for new typed flows; hosts should surface `str(e)` and use `e.check_result.category` for dispatch instead of substring-matching internal details.

```python
from agent_os.policies.decision import ViolationCategory
from agent_os.exceptions import PolicyViolationError

result = kernel.pre_execute_check(ctx, input_data)
if not result.allowed:
raise PolicyViolationError.from_check_result(result)
# Hosts: surface str(e); switch on e.check_result.category for typed dispatch.
```

## Boundaries

- **Never modify** `tests/test_mcp_server.py` (known pre-existing failure, excluded from CI)
Expand Down
24 changes: 24 additions & 0 deletions agent-governance-python/agent-os/src/agent_os/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
for structured error handling and logging.
"""

from __future__ import annotations

from datetime import datetime, timezone
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from agent_os.policies.decision import PolicyCheckResult


class AgentOSError(Exception):
Expand Down Expand Up @@ -43,6 +49,24 @@ class PolicyViolationError(PolicyError):

def __init__(self, message, error_code=None, details=None):
super().__init__(message, error_code or "POLICY_VIOLATION", details)
self.check_result = None

@classmethod
def from_check_result(cls, result: PolicyCheckResult) -> PolicyViolationError:
"""Create a policy violation error from a structured check result."""

details = {
"category": result.category.value if result.category else None,
"matched_rule": result.matched_rule,
"detail": result.detail,
"scope": result.scope,
"operation": result.operation,
"tool_name": result.tool_name,
**result.audit_entry,
}
e = cls(result.public_message, "POLICY_VIOLATION", details)
e.check_result = result
return e


class PolicyDeniedError(PolicyError):
Expand Down
Loading
Loading