Documentation
¶
Overview ¶
Package hooks provides an extensibility mechanism for agent lifecycle events. It allows external executables to observe and intercept tool calls, user messages, and agent lifecycle events for audit logging, security controls, and monitoring.
Index ¶
- Constants
- type AfterToolCallPayload
- type AfterToolCallResult
- type AgentStopPayload
- type AgentStopResult
- type BasePayload
- type BeforeToolCallPayload
- type BeforeToolCallResult
- type Discovery
- type DiscoveryOption
- type Hook
- type HookDirConfig
- type HookManager
- func (m HookManager) AllHooks() []*Hook
- func (m HookManager) Execute(ctx context.Context, hookType HookType, payload any) ([]byte, error)
- func (m HookManager) ExecuteAfterToolCall(ctx context.Context, payload AfterToolCallPayload) (*AfterToolCallResult, error)
- func (m HookManager) ExecuteAgentStop(ctx context.Context, payload AgentStopPayload) (*AgentStopResult, error)
- func (m HookManager) ExecuteBeforeToolCall(ctx context.Context, payload BeforeToolCallPayload) (*BeforeToolCallResult, error)
- func (m HookManager) ExecuteTurnEnd(ctx context.Context, payload TurnEndPayload) (*TurnEndResult, error)
- func (m HookManager) ExecuteUserMessageSend(ctx context.Context, payload UserMessageSendPayload) (*UserMessageSendResult, error)
- func (m HookManager) GetHookByName(name string) *Hook
- func (m HookManager) GetHooks(hookType HookType) []*Hook
- func (m HookManager) HasHooks(hookType HookType) bool
- func (m *HookManager) SetTimeout(timeout time.Duration)
- type HookType
- type InvokedBy
- type Trigger
- func (t *Trigger) SetConversationID(id string)
- func (t Trigger) TriggerAfterToolCall(ctx context.Context, toolName, toolInput, toolUserID string, ...) *tooltypes.StructuredToolResult
- func (t Trigger) TriggerAgentStop(ctx context.Context, messages []llmtypes.Message) []string
- func (t Trigger) TriggerBeforeToolCall(ctx context.Context, toolName, toolInput, toolUserID string) (bool, string, string)
- func (t Trigger) TriggerTurnEnd(ctx context.Context, response string, turnNumber int)
- func (t Trigger) TriggerUserMessageSend(ctx context.Context, message string) (bool, string)
- type TurnEndPayload
- type TurnEndResult
- type UserMessageSendPayload
- type UserMessageSendResult
Constants ¶
const DefaultTimeout = 30 * time.Second
DefaultTimeout is the default execution timeout for hooks
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AfterToolCallPayload ¶
type AfterToolCallPayload struct {
BasePayload
ToolName string `json:"tool_name"`
ToolInput json.RawMessage `json:"tool_input"`
ToolOutput tooltypes.StructuredToolResult `json:"tool_output"`
ToolUserID string `json:"tool_user_id"`
}
AfterToolCallPayload is sent to after_tool_call hooks
type AfterToolCallResult ¶
type AfterToolCallResult struct {
Output *tooltypes.StructuredToolResult `json:"output,omitempty"`
}
AfterToolCallResult is returned by after_tool_call hooks
type AgentStopPayload ¶
type AgentStopPayload struct {
BasePayload
Messages []llmtypes.Message `json:"messages"`
}
AgentStopPayload is sent to agent_stop hooks
type AgentStopResult ¶
type AgentStopResult struct {
// FollowUpMessages contains optional messages to append to the conversation.
// This enables LLM-based hooks to provide feedback, ask clarifying questions,
// or request additional actions based on the agent's work.
FollowUpMessages []string `json:"follow_up_messages,omitempty"`
}
AgentStopResult is returned by agent_stop hooks
type BasePayload ¶
type BasePayload struct {
Event HookType `json:"event"`
ConvID string `json:"conv_id"`
CWD string `json:"cwd"`
InvokedBy InvokedBy `json:"invoked_by"`
RecipeName string `json:"recipe_name,omitempty"` // Active recipe name, empty if none
}
BasePayload contains fields common to all hook payloads
type BeforeToolCallPayload ¶
type BeforeToolCallPayload struct {
BasePayload
ToolName string `json:"tool_name"`
ToolInput json.RawMessage `json:"tool_input"`
ToolUserID string `json:"tool_user_id"`
}
BeforeToolCallPayload is sent to before_tool_call hooks
type BeforeToolCallResult ¶
type BeforeToolCallResult struct {
Blocked bool `json:"blocked"`
Reason string `json:"reason,omitempty"`
Input json.RawMessage `json:"input,omitempty"`
}
BeforeToolCallResult is returned by before_tool_call hooks
type Discovery ¶
type Discovery struct {
// contains filtered or unexported fields
}
Discovery handles hook discovery from configured directories
func NewDiscovery ¶
func NewDiscovery(opts ...DiscoveryOption) (*Discovery, error)
NewDiscovery creates a new hook discovery instance
func (*Discovery) DiscoverHooks ¶
DiscoverHooks finds all available hooks from configured directories. Hooks from plugin directories are prefixed with "org/repo/" format. Hooks are discovered in precedence order, with higher precedence hooks shadowing lower ones.
type DiscoveryOption ¶
DiscoveryOption is a function that configures a Discovery
func WithDefaultDirs ¶
func WithDefaultDirs() DiscoveryOption
WithDefaultDirs initializes with default hook directories including plugin directories. This provides the full precedence order: repo-local standalone > repo-local plugins > global standalone > global plugins
func WithHookDirConfigs ¶
func WithHookDirConfigs(configs ...HookDirConfig) DiscoveryOption
WithHookDirConfigs sets custom hook directories with prefix support (for testing).
func WithHookDirs ¶
func WithHookDirs(dirs ...string) DiscoveryOption
WithHookDirs sets custom hook directories (for testing). All directories are treated as standalone (no prefix).
type Hook ¶
type Hook struct {
Name string // Filename of the executable
Path string // Full path to the executable
HookType HookType // Type returned by "hook" command
}
Hook represents a discovered hook executable
type HookDirConfig ¶
type HookDirConfig struct {
Dir string // Directory path
Prefix string // Prefix for hook names (e.g., "org/repo/" for plugins)
}
HookDirConfig represents a directory to scan for hooks with optional prefix
type HookManager ¶
type HookManager struct {
// contains filtered or unexported fields
}
HookManager manages hook discovery and execution
func NewHookManager ¶
func NewHookManager(opts ...DiscoveryOption) (HookManager, error)
NewHookManager creates a new HookManager with discovered hooks Returns an empty manager (no-op) if discovery fails
func (HookManager) AllHooks ¶
func (m HookManager) AllHooks() []*Hook
AllHooks returns all discovered hooks regardless of type.
func (HookManager) Execute ¶
Execute runs all hooks of a given type with the provided payload. Returns the result bytes from the last successful hook execution.
func (HookManager) ExecuteAfterToolCall ¶
func (m HookManager) ExecuteAfterToolCall(ctx context.Context, payload AfterToolCallPayload) (*AfterToolCallResult, error)
ExecuteAfterToolCall runs after_tool_call hooks and returns typed result. Empty or nil output with exit code 0 is treated as "no modification".
func (HookManager) ExecuteAgentStop ¶
func (m HookManager) ExecuteAgentStop(ctx context.Context, payload AgentStopPayload) (*AgentStopResult, error)
ExecuteAgentStop runs agent_stop hooks and returns typed result. Empty or nil output with exit code 0 is treated as "no follow-up". Accumulates follow_up_messages from all hooks.
func (HookManager) ExecuteBeforeToolCall ¶
func (m HookManager) ExecuteBeforeToolCall(ctx context.Context, payload BeforeToolCallPayload) (*BeforeToolCallResult, error)
ExecuteBeforeToolCall runs before_tool_call hooks and returns typed result. Empty or nil output with exit code 0 is treated as "no action" (not blocked, no modification). Uses deny-fast semantics: if any hook blocks, execution stops immediately.
func (HookManager) ExecuteTurnEnd ¶
func (m HookManager) ExecuteTurnEnd(ctx context.Context, payload TurnEndPayload) (*TurnEndResult, error)
ExecuteTurnEnd runs turn_end hooks. Empty or nil output with exit code 0 is treated as "no action".
func (HookManager) ExecuteUserMessageSend ¶
func (m HookManager) ExecuteUserMessageSend(ctx context.Context, payload UserMessageSendPayload) (*UserMessageSendResult, error)
ExecuteUserMessageSend runs user_message_send hooks and returns typed result. Empty or nil output with exit code 0 is treated as "no action" (not blocked). Uses deny-fast semantics: if any hook blocks, execution stops immediately.
func (HookManager) GetHookByName ¶
func (m HookManager) GetHookByName(name string) *Hook
GetHookByName returns a hook by its name, searching across all hook types. Returns nil if the hook is not found.
func (HookManager) GetHooks ¶
func (m HookManager) GetHooks(hookType HookType) []*Hook
GetHooks returns all hooks registered for the given type
func (HookManager) HasHooks ¶
func (m HookManager) HasHooks(hookType HookType) bool
HasHooks returns true if there are any hooks registered for the given type
func (*HookManager) SetTimeout ¶
func (m *HookManager) SetTimeout(timeout time.Duration)
SetTimeout sets the execution timeout for hooks
type HookType ¶
type HookType string
HookType represents the type of lifecycle hook
const ( HookTypeBeforeToolCall HookType = "before_tool_call" HookTypeAfterToolCall HookType = "after_tool_call" HookTypeUserMessageSend HookType = "user_message_send" HookTypeAgentStop HookType = "agent_stop" HookTypeTurnEnd HookType = "turn_end" )
Hook type constants define the lifecycle events that can be hooked
type InvokedBy ¶
type InvokedBy string
InvokedBy indicates whether the hook was triggered by main agent or subagent
type Trigger ¶
type Trigger struct {
Manager HookManager
ConversationID string
IsSubAgent bool
WorkingDir string
RecipeName string // Active recipe name, empty if none
}
Trigger provides methods to invoke lifecycle hooks. It encapsulates the common hook triggering logic shared across LLM providers. A zero-value Trigger is safe to use and acts as a no-op.
func NewTrigger ¶
func NewTrigger(manager HookManager, conversationID string, isSubAgent bool, args ...string) Trigger
func (*Trigger) SetConversationID ¶
SetConversationID updates the conversation ID for the trigger. This is useful when the conversation ID is set after thread creation.
func (Trigger) TriggerAfterToolCall ¶
func (t Trigger) TriggerAfterToolCall(ctx context.Context, toolName, toolInput, toolUserID string, toolOutput tooltypes.StructuredToolResult) *tooltypes.StructuredToolResult
TriggerAfterToolCall invokes after_tool_call hooks. Returns modified output or nil to use original. A zero-value Trigger returns nil.
func (Trigger) TriggerAgentStop ¶
TriggerAgentStop invokes agent_stop hooks. Returns follow-up messages that can be appended to the conversation. A zero-value Trigger returns nil.
func (Trigger) TriggerBeforeToolCall ¶
func (t Trigger) TriggerBeforeToolCall(ctx context.Context, toolName, toolInput, toolUserID string) (bool, string, string)
TriggerBeforeToolCall invokes before_tool_call hooks. Returns (blocked, reason, input) - input is the potentially modified tool input. A zero-value Trigger returns (false, "", toolInput).
func (Trigger) TriggerTurnEnd ¶
TriggerTurnEnd invokes turn_end hooks. A zero-value Trigger is a no-op.
type TurnEndPayload ¶
type TurnEndPayload struct {
BasePayload
Response string `json:"response"` // The assistant's response text
TurnNumber int `json:"turn_number"` // Which turn in the conversation (1-indexed)
}
TurnEndPayload is sent when an assistant turn completes
type UserMessageSendPayload ¶
type UserMessageSendPayload struct {
BasePayload
Message string `json:"message"`
}
UserMessageSendPayload is sent to user_message_send hooks
type UserMessageSendResult ¶
type UserMessageSendResult struct {
Blocked bool `json:"blocked"`
Reason string `json:"reason,omitempty"`
}
UserMessageSendResult is returned by user_message_send hooks