Skip to main content
Lifecycle hooks let you customize agent behavior at key execution points. Use hooks for logging, validation, or modifying inputs/outputs.

What are lifecycle hooks?

Hooks are functions that run at specific stages of agent execution:
  • on_start - Before agent execution begins
  • on_end - After agent execution completes
  • on_agent_step_start - Before each agent reasoning step
  • on_agent_step_end - After each agent reasoning step
  • on_tool_start - Before each tool execution
  • on_tool_end - After each tool execution

Defining hooks

Create hooks using the @hook decorator:
from polos import hook, WorkflowContext, HookContext, HookResult

@hook
def log_hook(ctx: WorkflowContext, hook_context: HookContext) -> HookResult:
    """Log execution details."""
    print(f"Workflow: {hook_context.workflow_id}")
    print(f"Payload: {hook_context.current_payload}")
    
    return HookResult.continue_with()
Hook signature:
  • ctx - WorkflowContext with execution metadata
  • hook_context - HookContext with current execution state
  • Returns - HookResult indicating what action to take

Hook results

Hooks return HookResult with three options:

1. Continue without changes

@hook
def simple_hook(ctx: WorkflowContext, hook_context: HookContext) -> HookResult:
    # Just observe, don't modify
    print("Hook executed")
    return HookResult.continue_with()

2. Continue with modifications

import re

@hook
def redact_pii_hook(ctx: WorkflowContext, hook_context: HookContext) -> HookResult:
    """Redact sensitive information from payloads."""
    if not hook_context.current_payload:
        return HookResult.continue_with()
    
    modified = hook_context.current_payload.copy()
    
    # Redact emails
    if isinstance(modified, dict):
        for key, value in modified.items():
            if isinstance(value, str):
                modified[key] = re.sub(
                    r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
                    '[EMAIL_REDACTED]',
                    value
                )
    
    return HookResult.continue_with(modified_payload=modified)

3. Fail and stop execution

@hook
def validation_hook(ctx: WorkflowContext, hook_context: HookContext) -> HookResult:
    """Validate payload before execution."""
    payload = hook_context.current_payload
    
    if not payload or not payload.get("required_field"):
        return HookResult.fail("Missing required field")
    
    return HookResult.continue_with()

Using hooks

Attach hooks to agents:
from polos import Agent

tracked_agent = Agent(
    id="tracked-agent",
    provider="openai",
    model="gpt-4o",
    system_prompt="You are a helpful assistant.",
    tools=[search, send_email],
    
    # Workflow hooks
    on_start=[log_hook, validate_input_hook],
    on_end=[log_hook, save_results_hook],
    
    # Step hooks
    on_agent_step_start=[log_step_hook],
    on_agent_step_end=[validate_step_hook],
    
    # Tool hooks
    on_tool_start=[log_tool_call_hook],
    on_tool_end=[audit_tool_result_hook]
)

Hook context

Hooks receive HookContext with execution state:
@hook
def inspect_context_hook(ctx: WorkflowContext, hook_context: HookContext) -> HookResult:
    # Workflow information
    workflow_id = hook_context.workflow_id
    
    # User context
    user_id = hook_context.user_id
    session_id = hook_context.session_id
    
    # Execution state
    current_payload = hook_context.current_payload
    current_output = hook_context.current_output
    current_tool = hook_context.current_tool
    
    # Agent configuration
    agent_config = hook_context.agent_config
    
    # Step history
    steps = hook_context.steps  # List of completed steps
    
    return HookResult.continue_with()

Multiple hooks

Hooks run in order. If any hook fails, execution stops:
agent = Agent(
    id="multi-hook-agent",
    provider="openai",
    model="gpt-4o",
    on_start=[
        validate_input_hook,     # Runs first
        redact_pii_hook,         # Runs second (on validated input)
        add_metadata_hook        # Runs third (on redacted input)
    ]
)
If validate_input_hook fails, redact_pii_hook and add_metadata_hook never run.

Hook execution flow

Complete agent execution with hooks: