# Hooks & Policy Precedence

> The priority-based policy model (Specific > Wildcard) and how to implement custom middleware using pre/post-step hooks.

- Repository: google-antigravity/antigravity-sdk-python
- GitHub: https://github.com/google-antigravity/antigravity-sdk-python
- Human wiki: https://grok-wiki.com/public/wiki/google-antigravity-antigravity-sdk-python-2abd361a7867
- Complete Markdown: https://grok-wiki.com/public/wiki/google-antigravity-antigravity-sdk-python-2abd361a7867/llms-full.txt

## Source Files

- `google/antigravity/hooks/hooks.py`
- `google/antigravity/hooks/hook_runner.py`
- `google/antigravity/hooks/policy.py`
- `examples/getting_started/hooks.py`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:
- [google/antigravity/hooks/hooks.py](google/antigravity/hooks/hooks.py)
- [google/antigravity/hooks/hook_runner.py](google/antigravity/hooks/hook_runner.py)
- [google/antigravity/hooks/policy.py](google/antigravity/hooks/policy.py)
- [examples/getting_started/hooks.py](examples/getting_started/hooks.py)
- [google/antigravity/types.py](google/antigravity/types.py)
</details>

# Hooks & Policy Precedence

The Google Antigravity SDK provides a sophisticated lifecycle management system through **Hooks** and a declarative **Policy** engine. Hooks allow developers to inject custom logic for observability, enforcement, and data transformation at various stages of an agent's execution. The Policy system builds on these hooks to provide a granular, priority-based mechanism for controlling tool usage.

Understanding the precedence model is critical for designing safe, autonomous agents that can navigate complex tool environments while maintaining strict security boundaries.

## Policy Precedence Model

Antigravity employs a "Specificity-First" priority model. Policies are evaluated in discrete buckets, where the most specific rules always override general wildcard rules. Within a specificity level, safety is prioritized (Deny > Ask > Allow).

### Priority Buckets
When multiple policies are registered, they are sorted into six priority levels (0-5), with lower numbers taking absolute precedence. Evaluation short-circuits at the first matching policy in the highest available bucket.

| Priority | Level Name | Target | Decision |
| :--- | :--- | :--- | :--- |
| **0** | Specific Deny | Named Tool | `DENY` |
| **1** | Specific Ask | Named Tool | `ASK_USER` |
| **2** | Specific Allow | Named Tool | `APPROVE` |
| **3** | Wildcard Deny | `*` | `DENY` |
| **4** | Wildcard Ask | `*` | `ASK_USER` |
| **5** | Wildcard Allow | `*` | `APPROVE` |

> [!IMPORTANT]
> Within a single bucket, the **first registered match wins**. This allows for sequential evaluation of complex predicates for the same tool.
> Sources: [google/antigravity/hooks/policy.py:326-347]()

### Predicates and Context
Policies can be constrained by `when` predicates, which receive the tool call arguments and can perform synchronous or asynchronous checks. This enables context-aware security, such as blocking `run_command` only when it contains dangerous strings like `rm -rf`.

```python
# Specific Deny (Level 0) takes priority over Wildcard Allow (Level 5)
policies = [
    policy.deny("run_command", when=lambda args: "sudo" in args.get("CommandLine", "")),
    policy.allow_all() 
]
```
Sources: [google/antigravity/hooks/policy.py:51-65]()

## Hook Architecture

The SDK distinguishes between three fundamental hook types, each serving a different architectural role in the Blueprint of an agent session.

1.  **InspectHook (Observability)**: Read-only and non-blocking. Used for logging, metrics, and UI updates (e.g., `on_session_start`, `post_turn`).
2.  **DecideHook (Enforcement)**: Read-only but **blocking**. Returns a `HookResult` that can stop execution (e.g., `pre_turn`, `pre_tool_call_decide`).
3.  **TransformHook (Modification)**: Modifying and blocking. Allows the SDK to recover from errors or handle interactive flows (e.g., `on_tool_error`, `on_interaction`).

### Hook Lifecycle
Hooks are managed by the `HookRunner`, which maintains isolated registries for each event type and handles context propagation through `HookContext` hierarchies.

```mermaid
sequenceDiagram
    participant A as Agent
    participant HR as HookRunner
    participant H as Hooks/Policies
    participant T as Tool/Model

    A->>HR: dispatch_pre_tool_call(tool_call)
    HR->>H: Evaluate Policies (Levels 0-5)
    H-->>HR: HookResult(allow=True/False)
    
    alt Denied
        HR-->>A: Denial Message
    else Allowed
        HR->>T: Execute Tool
        T-->>HR: ToolResult
        HR->>H: dispatch_post_tool_call(result)
        HR-->>A: Final Result
    end
```
Sources: [google/antigravity/hooks/hook_runner.py:181-204](), [google/antigravity/hooks/hooks.py:95-143]()

## Implementing Custom Middleware

Developers can implement custom middleware by decorating async functions with the appropriate hook decorator. This is a common Page Shape for adding cross-cutting concerns like authentication or sensitive data masking.

### Hook Contexts
Hooks receive a `context` object (e.g., `TurnContext`, `OperationContext`) which allows sharing state between hooks in the same lifecycle scope. Contexts follow a parent-child inheritance model.

```python
@hooks.pre_turn
async def audit_log_prompt(context: hooks.TurnContext, data: str) -> types.HookResult:
    # Access session-level state
    user_id = context.get("user_id")
    print(f"User {user_id} prompted: {data}")
    return types.HookResult(allow=True)
```
Sources: [google/antigravity/hooks/hooks.py:34-87]()

## Policy vs. CapabilitiesConfig

A common design decision is choosing between the Policy system and `CapabilitiesConfig`.

*   **CapabilitiesConfig**: Controls tool **visibility**. If a tool is disabled here, the model never sees it in its tool list, saving tokens and preventing hallucinations.
*   **Policy (Hooks)**: Controls tool **execution**. The model sees the tool but the call is rejected at runtime. Use this for conditional restrictions where the model needs to understand *why* a specific action was refused.

Sources: [google/antigravity/types.py:311-349](), [google/antigravity/hooks/policy.py:33-49]()

In summary, the Antigravity SDK's priority-based policy model (Specific > Wildcard) ensures that security rules are applied predictably, while the extensible hook system provides the necessary flexibility for implementing complex agent middleware and observability.
Sources: [google/antigravity/hooks/policy.py:17-25]()
