# How to Configure Lifecycle Hooks in Page Agent: beforeStep, afterStep, and Task Completion

> Master Page Agent lifecycle hooks like beforeStep and afterStep. Extend agent functionality with custom logic for enhanced task management and control. Learn configuration now.

- Repository: [Alibaba/page-agent](https://github.com/alibaba/page-agent)
- Tags: how-to-guide
- Published: 2026-03-09

---

**Page Agent exposes an experimental lifecycle-hook API through the `AgentConfig` object that lets you execute custom logic at five key moments: before the task starts, before each step, after each step, when the task ends (success or failure), and during disposal.**

The `alibaba/page-agent` repository provides an experimental lifecycle system that enables developers to inject custom behavior throughout a task's execution. You configure these hooks—including **`onBeforeStep`**, **`onAfterStep`**, and **`onAfterTask`** (which handles both success and error states)—once in the constructor configuration object. This guide covers the hook signatures, implementation locations, and practical patterns for telemetry, error handling, and resource management.

## Available Lifecycle Hooks in Page Agent

Page Agent defines five lifecycle hooks in [`packages/core/src/types.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/types.ts) (lines 70–105). Each hook receives the agent instance and context-specific parameters:

- **`onBeforeTask`** – Runs immediately before the task begins (after optional tool filtering). Receives `(agent: PageAgentCore) => Promise<void> | void`. Use this to initialize state or start UI heartbeats.
- **`onBeforeStep`** – Executes at the start of every step before the observation phase. Receives `(agent: PageAgentCore, stepCount: number) => Promise<void> | void`. Ideal for ensuring the page is fully loaded or injecting scripts.
- **`onAfterStep`** – Fires after a step completes and its result is pushed to `agent.history`. Receives `(agent: PageAgentCore, history: HistoricalEvent[]) => Promise<void> | void`. Use for persisting step data or updating progress bars.
- **`onAfterTask`** – Called when the task ends regardless of outcome. Receives `(agent: PageAgentCore, result: ExecutionResult) => Promise<void> | void`. This is where you handle success/failure logic and cleanup.
- **`onDispose`** – Invoked when `agent.dispose()` is called or the page unloads. Receives `(agent: PageAgentCore, reason?: string) => void`. Use to release listeners and stop timers.

## Configuring Hooks in AgentConfig

All hooks are defined **once** inside the `AgentConfig` object passed to the `PageAgent` or `PageAgentCore` constructor. The core invokes these hooks at specific points in [`packages/core/src/PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/PageAgentCore.ts) (lines 206–236 for step hooks, and around lines 309, 327, and 342 for task completion).

```typescript
import { PageAgent } from 'page-agent'

const agent = new PageAgent({
  // ... LLM credentials and other config
  onBeforeStep: (agent, step) => {
    console.log(`▶️ Starting step #${step}`)
  },
  onAfterStep: (agent, history) => {
    const lastEvent = history[history.length - 1]
    console.log('✅ Step completed:', lastEvent)
  },
  onAfterTask: async (agent, result) => {
    console.log('🏁 Task finished:', result.success ? 'Success' : 'Failure')
  }
})

```

## Handling Success and Errors with onAfterTask

Unlike separate `onError` and `onSuccess` hooks, Page Agent consolidates final-state handling into **`onAfterTask`**, which receives an `ExecutionResult` object defined in the core types:

```typescript
export interface ExecutionResult {
  success: boolean      // true if the "done" action reported success
  data: string          // final text or error message
  history: HistoricalEvent[]
}

```

When an exception occurs during a step, the core catches it, pushes an `error` event to history, and still guarantees `onAfterTask` fires with `success: false`. This design provides a single, reliable cleanup and reporting location.

```typescript
const agent = new PageAgent({
  onAfterTask: async (agent, result) => {
    if (result.success) {
      console.log('✅ Task succeeded:', result.data)
      // Show success toast, store payload
    } else {
      console.error('❌ Task failed:', result.data)
      // Report to monitoring service
      await fetch('https://example.com/api/agent-error', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ error: result.data, history: result.history })
      })
    }
  }
})

```

## Practical Code Examples

### Logging Step Progress

This basic configuration logs the start and end of each step, useful for debugging and telemetry. The hook definitions are located in [`packages/core/src/types.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/types.ts) (lines 78–91), and the invocation happens in [`packages/core/src/PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/PageAgentCore.ts) (lines 31–38).

```typescript
import { PageAgent } from 'page-agent'

const agent = new PageAgent({
  onBeforeStep: (agent, stepCount) => {
    console.log(`[${new Date().toISOString()}] Starting step ${stepCount}`)
  },
  onAfterStep: (agent, history) => {
    const lastAction = history[history.length - 1]
    console.log(`Step result: ${lastAction.type}`)
  }
})

```

### Ensuring Page Load Before Each Step

For browser extension scenarios using `MultiPageAgent`, use `onBeforeStep` to guarantee the active tab is loaded before the agent observes the page. This pattern appears in [`packages/extension/src/agent/MultiPageAgent.ts`](https://github.com/alibaba/page-agent/blob/main/packages/extension/src/agent/MultiPageAgent.ts) (lines 77–80).

```typescript
import { MultiPageAgent } from 'page-agent/extension'

const agent = new MultiPageAgent({
  // ...
  onBeforeStep: async (agent) => {
    // tabsController is available in the extension context
    await tabsController.waitUntilTabLoaded(tabsController.currentTabId!)
  }
})

```

### Custom Error Reporting

Because `onAfterTask` always runs, you can centralize error reporting logic here without worrying about uncaught exceptions bypassing your handler.

```typescript
const agent = new PageAgent({
  onAfterTask: async (agent, result) => {
    if (!result.success) {
      await fetch('/api/agent-errors', {
        method: 'POST',
        body: JSON.stringify({
          message: result.data,
          sessionHistory: result.history,
          timestamp: Date.now()
        })
      })
    }
  }
})

```

### Resource Cleanup on Disposal

Use **`onDispose`** to stop background processes when the agent shuts down. The signature is defined in [`packages/core/src/types.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/types.ts) (lines 108–114), with usage examples in [`packages/extension/src/agent/MultiPageAgent.ts`](https://github.com/alibaba/page-agent/blob/main/packages/extension/src/agent/MultiPageAgent.ts) (lines 82–90).

```typescript
let heartbeatInterval: NodeJS.Timeout

const agent = new PageAgent({
  onBeforeTask: () => {
    heartbeatInterval = setInterval(() => console.log('Agent heartbeat'), 5000)
  },
  onDispose: (agent, reason) => {
    if (heartbeatInterval) clearInterval(heartbeatInterval)
    chrome.storage.local.set({ isAgentRunning: false })
    console.log('Agent disposed. Reason:', reason ?? 'None provided')
  }
})

```

## Core Implementation Details

The hook system is implemented across three key files:

1. **[`packages/core/src/types.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/types.ts)** – Declares the `AgentConfig` interface and all hook signatures (lines 70–105, 108–114).
2. **[`packages/core/src/PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/PageAgentCore.ts)** – Contains the execution loop that invokes hooks. `onBeforeStep` and `onAfterStep` are called around the step execution logic (lines 206–236), while `onAfterTask` is invoked at task completion points (lines 309, 327, 342).
3. **[`packages/extension/src/agent/MultiPageAgent.ts`](https://github.com/alibaba/page-agent/blob/main/packages/extension/src/agent/MultiPageAgent.ts)** – Demonstrates real-world hook usage in a browser extension context, specifically showing tab synchronization and disposal cleanup (lines 77–90).

## Summary

- **Lifecycle hooks** are configured once in the `AgentConfig` object passed to `PageAgent` or `PageAgentCore`.
- **Five hooks** are available: `onBeforeTask`, `onBeforeStep`, `onAfterStep`, `onAfterTask`, and `onDispose`.
- **Error and success handling** is unified under `onAfterTask`, which receives an `ExecutionResult` containing a `success` boolean and the final history.
- **Hook invocation** is guaranteed even when steps throw exceptions, ensuring reliable cleanup and reporting logic.
- **Source locations**: Type definitions live in [`packages/core/src/types.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/types.ts), while invocation logic resides in [`packages/core/src/PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/PageAgentCore.ts).

## Frequently Asked Questions

### What happened to separate onError and onSuccess hooks?

Page Agent does not expose separate `onError` or `onSuccess` hooks. Instead, the **`onAfterTask`** hook receives an `ExecutionResult` object with a `success` boolean. You branch on this property to handle success or failure in one location, ensuring your cleanup code always runs regardless of outcome.

### Can I use async functions in lifecycle hooks?

Yes. All lifecycle hooks except `onDispose` support async functions returning `Promise<void>`. The agent awaits these promises at the appropriate execution points (e.g., before starting a step or after task completion). The `onDispose` hook is synchronous and intended for immediate cleanup.

### How do I ensure my hook runs before every step in a multi-page browser extension?

Use the **`onBeforeStep`** hook in `MultiPageAgent` to synchronize tab state. As shown in [`packages/extension/src/agent/MultiPageAgent.ts`](https://github.com/alibaba/page-agent/blob/main/packages/extension/src/agent/MultiPageAgent.ts) (lines 77–80), you can call `tabsController.waitUntilTabLoaded()` inside `onBeforeStep` to guarantee the active tab is ready before the agent performs observations.

### Where are the hook signatures defined in the source code?

The TypeScript interfaces for all lifecycle hooks are defined in **[`packages/core/src/types.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/types.ts)** between lines 70 and 114. The `AgentConfig` interface aggregates these optional hooks, and the `ExecutionResult` interface (used by `onAfterTask`) is declared nearby.