Search

Agent Hooks

Abstract

Agent Hooks is an open specification for structured lifecycle events emitted by AI-powered developer tools, agents, and assistants. It defines a vendor-neutral format for recording what an AI agent did, who initiated it, and why enabling cost transparency, security auditing, policy enforcement, and agent observability across any compliant tool.

1. Motivation

Modern AI coding tools such as Cursor, Windsurf Cascade, Claude Code, Google Gemini CLI, GitHub Copilot, and Codex operate as stateful agents, not stateless APIs. Each tool has independently introduced "hook" event systems that let developers intercept agent actions at key lifecycle points. The capabilities converge, but the naming, schemas, and feature sets diverge:

  • Cursor: beforeShellExecution, afterFileEdit, afterAgentResponse

  • Claude Code: PreToolUse, PostToolUse, SessionStart, PreCompact

  • Windsurf Cascade: PreRunCommand, PostWriteCode, PreMCPToolUse

  • Gemini CLI: BeforeTool, AfterAgent, PreCompress

  • GitHub Copilot: preToolUse, postToolUse, sessionStart

As a result:

  • Users cannot compare cost or execution behavior across tools

  • Platform vendors lack a shared accountability format

  • Third-party tooling (cost, security, compliance) requires custom integration per vendor

  • Token consumption are opaque or delayed

  • No shared vocabulary exists for "what just happened"

Agent Hooks defines a minimal but extensible event surface for AI-native workflows, providing the common language that is missing.

2. Goals

  1. Interoperability: Any compliant tool can emit and consume hook events in one format.

  2. Granularity: Support events from session lifecycle through individual tool invocations.

  3. Attribution: Every event carries identity (who), action (what), and rationale (why).

  4. Extensibility: Vendors can add custom metadata without breaking compatibility.

  5. Human & Machine Readable: Events are JSON and readable without special tooling.

3. Non-Goals

  1. Standardizing Prompts: Agent Hooks does not define prompt formats or agent logic.

  2. Replacing Internal Telemetry: Vendors may keep their own systems; Agent Hooks is the external contract.

  3. Prescribing Behavior: The spec standardizes signals, not how agents should act.

  4. Transport Protocol: Delivery mechanism (stdout, HTTP, gRPC, queues) is out of scope.

  5. UI Requirements: Agent Hooks does not require any specific interface.

4. Terminology

Term

Definition

Hook Event

A single immutable fact emitted by an AI agent during its lifecycle

Actor

The entity initiating or executing an action (human, AI agent, or system)

Session

A bounded interaction window (IDE open→close, CLI invocation, agent run)

Action

An external operation performed by the agent (shell, file I/O, tool call)

Mode

The agent mode the hook event was in when emitted

Model

The AI model used when a hook event was emitted

Compaction

Summarization or removal of conversation history to fit context limits

Actor Types

Type

Code

Description

Hook Event

user

A single immutable fact emitted by an AI agent during its lifecycle

AI Agent

agent

The AI assistant or coding agent

System

system

Platform infrastructure (e.g., auto-compaction, timeout)

Agent Modes

Mode

Description

agent

Autonomous multi-step execution

plan

Planning or strategy sub-agent

execute

Code-writing execution phase

chat

Conversational interaction

edit

Direct file editing context

5. Architecture Overview

Agent Hooks is a data specification, not a product. It defines how to record hook events. Storage and transport mechanisms are implementation-defined.

Each vendor maps its native events to the Agent Hooks schema. Consumers receive a unified stream regardless of which tool emitted the event.

6. Core Specification

6.1 Event Envelope Schema

Every hook event MUST include the following envelope:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://agent-hooks.dev/schemas/v1/event.json",
  "title": "Agent Hooks Event",
  "type": "object",
  "required": ["spec_version", "event_id", "event_type", "timestamp", "source", "session_id"],  "properties": {
    "spec_version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
      "description": "Agent Hooks specification version (e.g., '0.1.0')"
    },
    "event_id": {
      "type": "string",
      "format": "uuid",
      "description": "Unique identifier for this event"
    },
    "event_type": {
      "type": "string",
      "description": "Unified event type using dot-separated Category.Subcategory format"
    },
    "timestamp": {
      "type": "string",
      "format": "date-time",
      "description": "RFC 3339 timestamp when event occurred"
    },
    "source": {
      "$ref": "#/$defs/source",
      "description": "The tool that emitted this event"
    },
    "session_id": {
      "type": "string",
      "description": "Identifier tying events to the same session"
    },
    "parent_session_id": {
      "type": "string",
      "description": "Parent session ID for nested or sub-agent sessions"
    },
    "user": {
      "$ref": "#/$defs/user",
      "description": "The human who initiated the agent session"
    },
    "actor": {
      "$ref": "#/$defs/actor",
      "description": "The entity that triggered this specific event"
    },
    "agent_mode": {
      "type": "string",
      "enum": ["agent", "plan", "execute", "chat", "edit"],
      "description": "The mode the agent was operating in"    },
    "data": {
      "type": "object",
      "description": "Event-type-specific payload"
    },
    "risk": {
      "$ref": "#/$defs/risk",
      "description": "Risk assessment for this event"
    },
    "metadata": {
      "type": "object",
      "description": "Vendor-specific or implementation-specific data"
    }
  },
  "$defs": {
    "source": {
      "type": "object",
      "required": ["tool"],
      "properties": {
        "tool": {
          "type": "string",
          "description": "Tool name (e.g., 'cursor', 'claude-code', 'gemini-cli', 'copilot', 'windsurf')"
        },
        "version": {
          "type": "string",
          "description": "Tool version"
        }
      }
    },
    "user": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "User identifier (email, username, or UUID)"
        },
        "name": {
          "type": "string"
        }
      }
    },
    "actor": {
      "type": "object",
      "required": ["type"],      "properties": {
        "type": {
          "type": "string",
          "enum": ["user", "ai_agent", "system"]
        },
        "id": {
          "type": "string",
          "description": "Actor identifier"
        },
        "name": {
          "type": "string"
        }
      }
    },
    "risk": {
      "type": "object",
      "properties": {
        "score": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100,
          "description": "Numeric risk score (0 = no risk, 100 = critical)"
        },
        "level": {
          "type": "string",
          "enum": ["low", "medium", "high", "critical"],
          "description": "Categorical risk label"
        },
        "factors": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Tags explaining why the risk was scored (e.g., 'SECRET_PATTERN', 'DESTRUCTIVE_OP')"
        }
      }
    },
    "action": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Standardized action name (e.g., 'shell', 'read_file', 'write_file', 'mcp:<tool>')"
        },
        "input": {          "type": "object",
          "description": "Structured parameters for the action"
        },
        "result": {
          "type": "object",
          "properties": {
            "success": { "type": "boolean" },
            "exit_code": { "type": "integer" },
            "error_message": { "type": "string" },
            "output": { "type": "string", "description": "Truncated or summarized output" }
          }
        }
      }
    },
    "decision": {
      "type": "object",
      "properties": {
        "outcome": {
          "type": "string",
          "enum": ["allow", "deny", "ask"],
          "description": "Hook decision outcome"
        },
        "reason": {
          "type": "string",
          "description": "Human-readable reason for the decision"
        }
      }
    },
    "context": {
      "type": "object",
      "properties": {
        "trigger": {
          "type": "string",
          "enum": ["auto", "manual", "system"],
          "description": "What triggered the context operation"
        },
        "tokens_used": {
          "type": "integer",
          "description": "Current token count in use"
        },
        "tokens_limit": {
          "type": "integer",
          "description": "Maximum token limit before compaction triggers"
        },        "percentage_used": {
          "type": "number",
          "minimum": 0,
          "maximum": 100,
          "description": "Percentage of context window consumed (tokens_used / tokens_limit * 100)"
        },
        "tokens_before": {
          "type": "integer",
          "description": "Token count before compaction"
        },
        "tokens_after": {
          "type": "integer",
          "description": "Token count after compaction"
        },
        "tokens_removed": {
          "type": "integer"
        }
      }
    },
    "model": {
      "type": "object",
      "properties": {
        "model_id": {
          "type": "string",
          "description": "Model identifier following provider/model convention (e.g., 'anthropic/claude-sonnet-4-20250514')"
        },
        "input_tokens": { "type": "integer" },
        "output_tokens": { "type": "integer" },
        "latency_ms": { "type": "integer" },
        "retry_count": { "type": "integer" }
      }
    }
  }
}
6.2 Minimal Valid Event
{
  "spec_version": "0.1.0",
  "event_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_type": "Session.Start",
  "timestamp": "2026-02-08T19:22:11.123Z",
  "source": {
    "tool": "cursor",
    "version": "2.3.41"
  },
  "session_id": "sess_01HX"
}
6.3 Event Naming Convention

Event types use a dot-separated Category.Subcategory format. This avoids the fragmentation where beforeShellExecution (Cursor), PreRunCommand (Windsurf), preToolUse (Copilot), PreToolUse (Claude), and BeforeTool (Gemini) all describe the same concept.

Pattern

Meaning

Session.*

Session lifecycle

Prompt.*

User input events

Agent.*

Agent reasoning, planning, responses

Action.*

Tool/command execution

Model.*

LLM inference calls

Context.*

Context management (compaction)

Retry.*

Retry and loop detection

Policy.*

Safety and policy enforcement

7. Event Taxonomy

7.1 Session Lifecycle

Event Type

Description

Session.Start

New AI interaction begins

Session.End

Session ends normally

Session.Abort

Session terminated unexpectedly

Session.Start fields:

{
  "event_type": "Session.Start",
  "data": {
    "start_reason": "new | resume | restart"
  }
}

Session.End fields:

{
  "event_type": "Session.End",
  "data": {
    "end_reason": "exit | completed | error | manual_reset | idle_timeout",
    "usage": {
      "total_tokens": 48210,
      "total_actions": 14,
      "duration_ms": 342000
    }
  }
}
7.2 User Input

Event Type

Description

Prompt.Submitted

User submits a prompt or task

data SHOULD contain sanitized content. Raw prompt text is OPTIONAL and subject to the implementation's privacy policy.

{
  "event_type": "Prompt.Submitted",
  "data": {
    "prompt_hash": "sha256:a1b2c3...",
    "prompt_length": 342,
    "is_followup": false
  }
}
7.3 Agent Reasoning & Planning

Event Type

Description

Agent.Plan.Start

Agent begins multi-step planning

Agent.Plan.End

Planning phase completes

Agent.Decision

Branching or selection made

Agent.Response

Agent produces final answer for the turn

data SHOULD contain summaries, not raw chain-of-thought.

{
  "event_type": "Agent.Plan.Start",
  "data": {
    "plan_type": "plan | explore | default",
    "step_count": 5
  }
}

{
  "event_type": "Agent.Response",
  "data": {
    "response_length": 1240,
    "response_hash": "sha256:d4e5f6...",
    "final": true
  }
}
7.4 Model Invocation

Event Type

Description

Model.Requested

LLM call initiated

Model.Responded

LLM response received

Model.Failed

LLM error

{
  "event_type": "Model.Responded",
  "data": {
    "model_id": "anthropic/claude-sonnet-4-20250514",
    "input_tokens": 4123,
    "output_tokens": 987,
    "latency_ms": 1840,
    "retry_count": 0
  }
}
7.5 Action Execution

Event Type

Description

Action.Before

Tool/command execution about to begin

Action.After

Tool/command execution completed

These are the most critical events for security gating and observability.

Action.Before with decision:

{
  "event_type": "Action.Before",
  "data": {
    "action": {
      "name": "shell",
      "input": {
        "command": "rm -rf /tmp/build"
      }
    },
    "decision": {
      "outcome": "deny",
      "reason": "Destructive command blocked by hook"
    }
  },
  "risk": {
    "score": 95,
    "level": "critical",
    "factors": ["DESTRUCTIVE_OP"]
  }
}

Action.After with result:

{
  "event_type": "Action.After",
  "data": {
    "action": {
      "name": "shell",
      "input": {
        "command": "ls -la /tmp"
      },
      "result": {
        "success": true,
        "exit_code": 0,
        "output": "[truncated]"
      }
    }
  },
  "risk": {
    "score": 5,
    "level": "low"
  }
}

Standard action names:

Action Name

Description

shell

Shell command execution

read_file

File read operation

write_file

File write or edit

mcp:<tool>

MCP tool invocation

web_search

Web search or fetch

code_edit

Inline code modification

7.6 Context Management

Event Type

Description

Context.UntilCompaction

Reports current context usage as a percentage of the compaction threshold

Context.Compaction

Context about to be compacted/summarized

Context.UntilCompaction tracks how close a session is to triggering compaction. Implementations SHOULD emit this event periodically or after each model invocation so consumers can monitor context pressure and anticipate compaction.

{
  "event_type": "Context.UntilCompaction",
  "data": {
    "tokens_used": 96000,
    "tokens_limit": 128000,
    "percentage_used": 75.0,
    "tokens_remaining": 32000
  }
}

Context.Compaction fires when compaction is about to occur:

{
  "event_type": "Context.Compaction",
  "data": {
    "trigger": "auto",
    "tokens_before": 128000,
    "tokens_after": 64000,
    "tokens_removed": 64000,
    "strategy": "summarize"
  }
}
7.7 Notifications & Errors

Event Type

Description

Agent.Notification

Agent issues a notification or permission prompt

Agent.Error

Unexpected error in the agent loop

{
  "event_type": "Agent.Notification",
  "data": {
    "type": "ToolPermission | IdleTimeout | ErrorAlert",
    "message": "Shell command requires approval",
    "details": {}
  }
}

{
  "event_type": "Agent.Error",
  "data": {
    "error_type": "ToolFailed | ModelError | HookError | UnhandledException",
    "error_message": "Command timed out after 30s",
    "origin_event": "Action.Before"
  }
}

8. Vendor Alignment

The following table maps each vendor's native event names to the unified Agent Hooks types:

Agent Hooks Event

Cursor

Windsurf Cascade

Claude Code

Gemini CLI

GitHub Copilot

Session.Start

(implicit)

(on worktree setup)

SessionStart

SessionStart

SessionStart

Session.End

stop

(implicit)

SessionEnd

SessionEnd

SessionEnd

Prompt.Submitted

beforeSubmitPrompt

PreUserPrompt

UserPromptSubmit

(via BeforeAgent)

userPromptSubmitted

Agent.Plan.Start

(n/a)

(n/a)

SubagentStart

(Plan)

BeforeAgent

(n/a)

Agent.Response

afterAgentResponse

PostCascadeResponse

Stop

AfterAgent

(implicit)

Model.Requested

(n/a)

(n/a)

(n/a)

BeforeModel

(n/a)

Model.Responded

afterAgentThought

(n/a)

(n/a)

AfterModel

(n/a)

Action.Before

beforeShellExecution, beforeReadFile, beforeMCPExecution

PreRunCommand, PreReadCode, PreWriteCode, PreMCPToolUse

PreToolUse

BeforeTool

preToolUse

Action.After

afterShellExecution, afterFileEdit, afterMCPExecution

PostRunCommand, PostWriteCode, PostReadCode

PostToolUse, PostToolUseFailure

AfterTool

postToolUse

Context.UntilCompaction

(none)

(none)

(none)

(none)

(none)

Context.Compaction

(none)

(none)

PreCompact

PreCompress

(none)

Agent.Notification

(none)

(none)

Notification, PermissionRequest

Notification

(none)

Agent.Error

(none)

(none)

PostToolUseFailure

(none)

errorOccurred

(n/a) indicates the vendor does not expose a discrete event for this concept. The behavior may be implicit or combined with another event.

9. Security Considerations

  • Events SHOULD be cryptographically signed if transmitted externally.

  • Raw prompt content SHOULD be redacted or hashed. The prompt_hash is preferred over pprompt_text.

  • PII MUST NOT be included by default. User identity fields should use organizational identifiers, not personal data, where possible.

  • Tool outputs MAY be summarized or truncated. Full stdout/stderr SHOULD NOT be included unless the consumer opts in.

  • Event transport SHOULD use TLS when transmitted over a network.

  • Implementations SHOULD provide a means to capture all events without enumerating each hook type (e.g., AGENT_HOOKS_LOG=<filepath> or event: "*" wildcard configuration).

10. Extensibility

10.1 Specification Versioning
  • prompt_hash follows semver.

  • Minor version: additive changes (new optional fields, new event types).

  • Major version: breaking changes to required fields.

  • Event types are additive; new types do not require a version bump.

10.2 Vendor Metadata

Vendors MAY add custom fields under themetadata object using reverse-domain notation to avoid key collisions:

{
  "metadata": {
    "dev.cursor": {
      "workspace_id": "ws-abc123",
      "tab_context": true
    },
    "com.anthropic": {
      "constitution_version": "2.1"
    }
  }
}
10.3 Vendor Metadata

Tools MAY emit event types beyond the core taxonomy. Custom types SHOULD use a vendor prefix:

vendor.cursor.TabFileEdit

vendor.gemini.ModelStream

Consumers MUST ignore unknown event types or fields.

10.4 Wildcard Hook Enablement

Implementations SHOULD provide a mechanism to capture all events in a single configuration statement. This ensures ease of adoption such so a security engineer can enable full telemetry in one step:

tool-native configuration:

{
  "hooks": {
    "event": "*",
    "output": "/var/log/agent-hooks.jsonl"
  }
}

11. Relationship to Existing Standards

Standard

Relationship

Agent Trace

Complementary. Agent Trace attributes code lines to AI or human contributors. Agent Hooks records the events and decisions that produced those contributions. A trace_record_idfield MAY link an Agent Hooks event to an Agent Trace record.

CloudEvents

Inspiration for the transport-neutral envelope structure. Agent Hooks events can be wrapped in CloudEvents for delivery.

MCP (Model Context Protocol)

Complementary. MCP describes agent capabilities and tool interfaces. Agent Hooks describes the events emitted when those capabilities are exercised.

12. Reference Implementation

A reference implementation demonstrating Agent Hooks integration with multiple AI coding tools is maintained in the Intentra CLI. The implementation includes:

  • Event normalizers for Cursor, Claude Code, Gemini CLI, Copilot, and Windsurf Cascade

  • Hook event handlers that map native events to the Agent Hooks schema

  • Scan aggregation that groups events into prompt-response cycles

  • Risk scoring based on the baseline guidelines in this spec

The reference normalizer interface:

type Normalizer interface {
    NormalizeEventType(nativeType string) NormalizedEventType
    Tool() string
}

Each tool's normalizer registers itself and maps native event names to Agent Hooks types. The normalized events are then forwarded to consumers (logging, dashboards, policy engines) in the unified JSON format.

13. Appendix

A. Complete Event Type Reference

Event Type

Category

Advisory Only

Description

Session.Start

Lifecycle

Yes

Session initiated

Session.End

Lifecycle

Yes

Session terminated

Session.Abort

Lifecycle

Yes

Session terminated unexpectedly

Prompt.Submitted

Input

No (can deny)

User submits prompt

Agent.Plan.Start

Reasoning

Yes

Planning phase begins

Agent.Plan.End

Reasoning

Yes

Planning phase completes

Agent.Decision

Reasoning

Yes

Agent makes a branching decision

Agent.Response

Reasoning

Yes

Agent produces final turn answer

Model.Requested

Model

Yes

LLM call initiated

Model.Responded

Model

Yes

LLM response received

Model.Failed

Model

Yes

LLM error occurred

Action.Before

Execution

No (can deny)

Tool/command about to execute

Action.After

Execution

Yes

Tool/command completed

Retry.Triggered

Retry

Yes

Retry initiated

Retry.Loop.Detected

Retry

Yes

Probable retry loop

Retry.Loop.Aborted

Retry

Yes

Loop forcibly stopped

Context.UntilCompaction

Context

Yes

Current context usage percentage

Context.Compaction

Context

Yes

Context about to be compacted

Policy.Violation

Safety

Yes

Policy breach detected

Policy.Blocked

Safety

Yes

Action prevented

Policy.Override

Safety

Yes

Human override granted

Agent.Notification

System

Yes

Notification or permission prompt

Agent.Error

System

Yes

Unexpected error

B. Full Example: Action Blocked
{
  "spec_version": "0.1.0",
  "event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "event_type": "Action.Before",
  "timestamp": "2026-02-08T22:15:30.123Z",
  "source": {
    "tool": "cursor",
    "version": "2.3.41"
  },
  "session_id": "sess-789",
  "user": {
    "id": "dev1@example.com"
  },
  "actor": {
    "type": "ai_agent",
    "id": "cursor-agent-1",
    "name": "Cursor Agent"
  },
  "agent_mode": "agent",
  "data": {
    "action": {
      "name": "shell",
      "input": {
        "command": "rm -rf /tmp/build"
      }
    },
    "decision": {
      "outcome": "deny",
      "reason": "Destructive command blocked by hook"
    }
  },
  "risk": {
    "score": 95,
    "level": "critical",
    "factors": ["DESTRUCTIVE_OP"]
  }
}
C. Full Example: Successful Shell Command
{
  "spec_version": "0.1.0",
  "event_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "event_type": "Action.After",
  "timestamp": "2026-02-08T22:15:31.200Z",
  "source": {
    "tool": "cursor",
    "version": "2.3.41"
  },
  "session_id": "sess-789",
  "user": {
    "id": "dev1@example.com"
  },
  "actor": {
    "type": "ai_agent",
    "id": "cursor-agent-1"
  },
  "agent_mode": "agent",
  "data": {
    "action": {
      "name": "shell",
      "input": {
        "command": "ls -la /tmp"
      },
      "result": {
        "success": true,
        "exit_code": 0,
        "output": "[truncated list of files]"
      }
    }
  },
  "risk": {
    "score": 5,
    "level": "low"
  }
}
D. Full Example: Context Until Compaction
{
  "spec_version": "0.1.0",
  "event_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
  "event_type": "Context.UntilCompaction",
  "timestamp": "2026-02-08T23:30:00.000Z",
  "source": {
    "tool": "claude-code",
    "version": "1.0.12"
  },
  "session_id": "sess-456",
  "user": {
    "id": "alice@example.com"
  },
  "actor": {
    "type": "system"
  },
  "data": {
    "tokens_used": 96000,
    "tokens_limit": 128000,
    "percentage_used": 75.0,
    "tokens_remaining": 32000
  }
}
E. Full Example: Context Compaction
{
  "spec_version": "0.1.0",
  "event_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "event_type": "Context.Compaction",
  "timestamp": "2026-02-08T23:45:00.000Z",
  "source": {
    "tool": "claude-code",
    "version": "1.0.12"
  },
  "session_id": "sess-456",
  "user": {
    "id": "alice@example.com"
  },
  "actor": {
    "type": "system"
  },
  "data": {
    "trigger": "auto",
    "tokens_before": 128000,
    "tokens_after": 64000,
    "tokens_removed": 64000,
    "strategy": "summarize"
  }
}
F. Full Example: Retry Loop Detected
{
  "spec_version": "0.1.0",
  "event_id": "d4e5f6a7-b8c9-0123-defa-234567890123",
  "event_type": "Retry.Loop.Detected",
  "timestamp": "2026-02-08T22:30:15.000Z",
  "source": {
    "tool": "gemini-cli",
    "version": "0.26.1"
  },
  "session_id": "sess-321",
  "user": {
    "id": "bob@example.com"
  },
  "actor": {
    "type": "ai_agent"
  },
  "data": {
    "iteration_count": 7,
    "action_name": "shell",
    "tokens_consumed": 12400,
    "elapsed_ms": 45000
  },
  "risk": {
    "score": 80,
    "level": "high",
    "factors": ["COST_ANOMALY", "RETRY_LOOP"]
  }
}
G. MIME Type

Type

MIME Type

Hook Event

application/vnd.agent-hooks.event+json

Event Stream

application/vnd.agent-hooks.stream+jsonl

H. Delivery Mechanisms

Agent Hooks events MAY be delivered via any of:

  • Local stdout / file (JSONL format)

  • HTTP webhooks (POST per event or batched)

  • gRPC streams

  • OpenTelemetry exporters

  • Message queues (Kafka, SQS, etc.)

Transport selection is out of scope for this specification.

I. Open Questions
J. FAQ

How does Agent Hooks relate to Agent Trace?
Agent Trace records which lines of code were written by AI. Agent Hooks records the events and decisions that produced those lines. Together they provide end-to-end attribution: Agent Trace shows the "what was written" and Agent Hooks shows the "how and why it was written."

Do vendors need to change their internal hook systems?
No. Agent Hooks is an output format specification. Vendors map their native events to the schema at the point of export. Internal systems remain unchanged.

How should I store the events?
This spec intentionally does not define storage. Events can be written to local files, streamed to cloud logging, stored in databases, or forwarded to SIEMs.

Can I add custom events?
Yes. Use vendor-prefixed event types (e.g., vendor.cursor.TabFileEdit). Consumers MUST ignore unknown event types.

What about privacy?
Raw prompts and tool outputs are not required. Use hashes (prompt_hash, content_hash) and summaries by default. Full content inclusion is opt-in per implementation.

License

This specification is released under CC BY 4.0.

Contributing

This specification is accepting feedback and contributions. Early adopters are encouraged to implement read-only event emission first.

Want to join contributors? Email contact@atbabers.com with your LinkedIn Profile

Partners helping shape Agent Hooks:

  • Intentra

  • (Open for contributions from Cursor, Anthropic, Google, GitHub, Windsurf, and the broader community)

©2026 Asante Babers