---
description: "Subscribes to everything the visual layer observes, in order: tool starts, field fills, parks, results, errors, cancels, and the cursor yielding to or resuming after the person."
---

# `onAgentEvent`

Subscribes to everything the visual layer observes, in order: tool starts, field fills, parks, results, errors, cancels, and the cursor yielding to or resuming after the person. Reach for it to build your own status UI, logging or tests; the devtools and the chat do the same instead of reading internals.

## Import

```ts
import { onAgentEvent } from "@webmcp-agents/core";
import type { AgentEvent } from "@webmcp-agents/core";
```

## Example

A banner that shows what the agent is waiting for and hides when the call ends.

```ts title="agent-banner.ts"
import { onAgentEvent } from "@webmcp-agents/core";

// A banner that says what the agent is waiting for.
const banner = document.createElement("p");
banner.hidden = true;
document.body.append(banner);

export const stopBanner = onAgentEvent((e) => {
  switch (e.type) {
    case "park": // e.g. Click "Place order" to confirm
      banner.textContent = e.prompt;
      banner.hidden = false;
      break;
    case "result":
    case "error":
    case "cancel":
      banner.hidden = true;
      break;
  }
});

// Later: stopBanner();
```

## Options

`onAgentEvent(listener)` takes one argument.

| Name | Type | Default | Description |
|---|---|---|---|
| `listener` | `(e: AgentEvent) => void` | required | Called for every event, in order, as it happens. Switch on `e.type`; the variants are listed below. |

### `AgentEvent`

One object per event, discriminated by `type`.

| `type` | Other fields | When |
|---|---|---|
| `start` | `tool: string`, `at: number`, `args?: unknown` | A tool run started (the first lifecycle signal seen). `at` is `performance.now()`. `args` is what the agent passed, when known (tools from `defineWebTool` and `useWebTool`; declarative forms only show `fill`s). A call whose input fails its schema still starts and answers with the error, without the cursor moving. |
| `fill` | `tool: string`, `field: string`, `value: string \| boolean` | The agent's value went into a field, once the cursor has typed it. `field` is the parameter's name for a tool (the control's `name` for a declarative form); the value is a boolean for a checkbox. A custom widget the cursor only visited emits none. |
| `park` | `tool: string`, `prompt: string` | The tool is waiting for the person: the browser paused on a submit button, a tool is waiting for their click on its control, or the page asked them something (see [`waitingForUser`](/docs/reference/core/waiting-for-user)). `prompt` says what to do. |
| `result` | `tool: string`, `result: unknown`, `ms: number` | The tool answered the agent. `ms` is measured from the run's start. |
| `error` | `tool: string`, `error: string`, `ms: number` | The tool failed; `error` is the text the agent got. |
| `cancel` | `tool: string` | The call was cancelled. |
| `yield` | `reason: "pointer" \| "keyboard" \| "wheel" \| "touch"` | The person started interacting and the cursor got out of the way. |
| `resume` | none | The person has been quiet long enough for the cursor to show again. |

## Returns

An unsubscribe function: `() => void`. Call it to stop listening.

## Notes

- A listener that throws never breaks a tool run: the error is caught and logged with `console.error`.
- The `log` option of [`installAgentVisuals`](/docs/reference/core/install-agent-visuals) receives the same entries.
- Listeners are module-level: subscribing works whether or not the visuals are installed, but most events come from the visual layer. `park` is also emitted by [`waitingForUser`](/docs/reference/core/waiting-for-user) and by confirm-gated tools.
- There is no replay: a listener sees only events after it subscribed.

## See also

- [The agent cursor](/docs/concepts/agent-cursor), what the events describe
- [`installAgentVisuals`](/docs/reference/core/install-agent-visuals), the layer that emits them
- [`waitingForUser`](/docs/reference/core/waiting-for-user), a tool saying it waits for the person
- [`useAgentEvents`](/docs/reference/react/use-agent-events), the same events in a React component
