# How to Use the Page-Agent Event System for Monitoring: statuschange, historychange, and activity Events

> Learn to monitor your web application with the PageAgent event system. Use statuschange, historychange, and activity events with addEventListener for real-time insights.

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

---

**The Page-Agent event system exposes three DOM-style events—`statuschange`, `historychange`, and `activity`—that you can monitor using standard `addEventListener` calls on any `PageAgent` or `PageAgentCore` instance.**

The `alibaba/page-agent` repository provides a browser automation framework where the core execution logic and UI layer communicate through a robust event architecture. By tapping into the **Page-Agent event system**, you can build real-time monitoring dashboards, audit logs, or custom UI components without modifying the agent's internal Re-Act loop. This system uses the standard `EventTarget` API, allowing multiple independent listeners to subscribe to state changes, history mutations, and transient activities.

## The Three Core Monitoring Events

The event system centers on three distinct event types, each serving a specific monitoring purpose. These events are dispatched from the `PageAgentCore` class and bubble up through the `PageAgent` UI wrapper.

### statuschange

The `statuschange` event fires whenever the agent transitions between lifecycle states: `idle`, `running`, `completed`, or `error`. According to the source code in [`packages/core/src/PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/PageAgentCore.ts), this event is emitted by the private `#emitStatusChange()` method immediately after the internal `#status` field updates.

This event carries no custom payload—just a standard `Event` object. Use it to drive global state indicators, such as showing a "thinking" spinner when the status shifts to `running` or displaying a success banner when it reaches `completed`.

### historychange

The `historychange` event triggers after any mutation to the agent's internal `history` array (typed as `HistoricalEvent[]`). In [`PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/PageAgentCore.ts), the `#emitHistoryChange()` method dispatches this event following operations like pushing a new step, flushing an observation, or recording a retry.

Like `statuschange`, this emits a plain `Event` object without additional data. Access the `agent.history` property in your handler to inspect the full sequence of steps. This event is ideal for persisting execution logs to a remote analytics service or refreshing a timeline view in a debug panel.

### activity

The `activity` event provides granular, transient feedback about the current operation, such as "clicking element #3" or "retry (2/3)". This is dispatched by `#emitActivity()` in [`PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/PageAgentCore.ts) and carries a `CustomEvent<AgentActivity>` payload where the `detail` field contains the activity record.

Use this event for real-time status bars that display tool execution progress, wait times, or error recovery attempts. The `Panel` class in [`packages/ui/src/panel/Panel.ts`](https://github.com/alibaba/page-agent/blob/main/packages/ui/src/panel/Panel.ts) uses this pattern to update the on-page UI header and status indicators.

## Event Emission Points in the Source Code

Understanding where these events originate helps you predict when they fire during the agent lifecycle.

In [`packages/core/src/PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/PageAgentCore.ts):
- **Lines 52-56**: `#emitStatusChange()` updates `#status` and dispatches `statuschange`
- **Lines 57-60**: `#emitHistoryChange()` mutates `this.history` and dispatches `historychange`
- **Lines 66-68**: `#emitActivity()` creates a `CustomEvent` with `AgentActivity` detail and dispatches `activity`

The `Panel` component in [`packages/ui/src/panel/Panel.ts`](https://github.com/alibaba/page-agent/blob/main/packages/ui/src/panel/Panel.ts) (lines 83-88) demonstrates production usage by registering listeners for all three events to synchronize the DOM with the agent state. Similarly, browser extension implementations in [`packages/extension/src/agent/useAgent.ts`](https://github.com/alibaba/page-agent/blob/main/packages/extension/src/agent/useAgent.ts) (lines 94-100) forward these events to background scripts for cross-tab monitoring.

## Practical Implementation Examples

### Basic Listener Setup

Attach listeners immediately after instantiating the agent. This example shows all three event types in a standard TypeScript setup:

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

const agent = new PageAgent({ pageController })

// Monitor lifecycle state
agent.addEventListener('statuschange', () => {
  console.log('Agent status:', agent.status)
})

// Monitor history mutations
agent.addEventListener('historychange', () => {
  const lastEntry = agent.history[agent.history.length - 1]
  console.log('History updated:', lastEntry.type, lastEntry)
})

// Monitor transient activities
agent.addEventListener('activity', (e) => {
  const activity = (e as CustomEvent<any>).detail
  console.log(`Activity: ${activity.type}`, activity)
})

```

### Centralized Monitoring Service

For production monitoring, create a dedicated module that streams events to a log file or remote endpoint:

```typescript
import { PageAgent } from '@page-agent/page-agent'
import { createWriteStream } from 'fs'

export function attachMonitoring(agent: PageAgent) {
  const logStream = createWriteStream('agent-audit.log', { flags: 'a' })

  agent.addEventListener('statuschange', () => {
    logStream.write(`[${new Date().toISOString()}] STATUS ${agent.status}\n`)
  })

  agent.addEventListener('historychange', () => {
    const last = agent.history[agent.history.length - 1]
    logStream.write(
      `[${new Date().toISOString()}] HISTORY ${last.type} ${JSON.stringify(last)}\n`
    )
  })

  agent.addEventListener('activity', (e) => {
    const a = (e as CustomEvent<any>).detail
    logStream.write(`[${new Date().toISOString()}] ACTIVITY ${a.type} ${a.tool || ''}\n`)
  })
}

```

### React Component Integration

Sync a React UI with the agent using `useEffect` to manage listener subscriptions:

```tsx
import { useEffect, useState } from 'react'
import { PageAgent } from '@page-agent/page-agent'

export const AgentMonitor: React.FC<{ agent: PageAgent }> = ({ agent }) => {
  const [status, setStatus] = useState(agent.status)
  const [currentActivity, setCurrentActivity] = useState<string>('idle')

  useEffect(() => {
    const handleStatus = () => setStatus(agent.status)
    const handleActivity = (e: Event) => {
      const detail = (e as CustomEvent<any>).detail
      setCurrentActivity(`${detail.type}${detail.tool ? ` (${detail.tool})` : ''}`)
    }

    agent.addEventListener('statuschange', handleStatus)
    agent.addEventListener('activity', handleActivity)

    return () => {
      agent.removeEventListener('statuschange', handleStatus)
      agent.removeEventListener('activity', handleActivity)
    }
  }, [agent])

  return (
    <div className="monitor-bar">
      <strong>Status:</strong> {status} | <strong>Activity:</strong> {currentActivity}
    </div>
  )
}

```

## Summary

- **Three event types** drive the Page-Agent event system: `statuschange` for lifecycle states, `historychange` for step mutations, and `activity` for transient operations.
- **EventTarget API** compatibility means you use standard `addEventListener` and `removeEventListener` methods on any agent instance.
- **Source locations**: Events emit from [`PageAgentCore.ts`](https://github.com/alibaba/page-agent/blob/main/PageAgentCore.ts) via private methods `#emitStatusChange()`, `#emitHistoryChange()`, and `#emitActivity()`.
- **UI integration**: The reference implementation in [`Panel.ts`](https://github.com/alibaba/page-agent/blob/main/Panel.ts) demonstrates how to transform these events into DOM updates.
- **Monitoring use cases**: Attach listeners for audit logging, real-time dashboards, or browser extension messaging without altering core agent logic.

## Frequently Asked Questions

### What data does the activity event payload contain?

The `activity` event dispatches a `CustomEvent` where the `detail` property contains an `AgentActivity` object. This object includes fields like `type` (e.g., "thinking", "executing", "retrying"), `tool` (the tool name when executing), and retry counters. The exact TypeScript definitions are available in [`packages/core/src/types.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/types.ts).

### Can I attach multiple listeners to the same event?

Yes. Because `PageAgentCore` extends the standard `EventTarget` interface, you can register any number of listeners for `statuschange`, `historychange`, or `activity`. Each listener executes independently when the event fires, making it safe to combine monitoring services with UI updates.

### How do I stop monitoring when the agent completes?

Call `agent.removeEventListener(eventName, handler)` for each subscribed event, passing the same handler reference used in `addEventListener`. In React components, return the cleanup function from `useEffect` to ensure listeners detach when the component unmounts or the agent instance changes.

### Does the event system work with PageAgentCore directly, or only the UI wrapper?

The event system works with both. `PageAgent` is a UI-enhanced wrapper around `PageAgentCore`, but both classes inherit from `EventTarget`. You can attach listeners to a bare `PageAgentCore` instance if you are running headless monitoring without the DOM panel, as shown in the Node.js service example.