> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentium.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> EventBus in kid language — watch a run, don't steer it. onAny, shared bus, lifecycle events.

# Events

## In plain terms

The **event bus** is a mailbox.

When something happens ("run started", "tool used", "run finished"), Agentium drops a note in the mailbox. You can listen.

You **watch** with the bus. You **steer** with hooks.

| I want to…                                  | Use                   |
| ------------------------------------------- | --------------------- |
| Log, metrics, traces, webhooks              | `eventBus` / `onAny`  |
| Skip a tool, stop the loop, change messages | `hooks` / `loopHooks` |

Trying to "approve a tool" by emitting on the bus will not work. Approval has its own API. See [Approval](/agents/approval).

***

## The smallest example

```typescript theme={null}
const agent = new Agent({
  name: "assistant",
  model: openai("gpt-4o"),
});

agent.eventBus.on("run.start", ({ input }) => {
  console.log("User asked:", input);
});

agent.eventBus.on("run.complete", ({ output }) => {
  console.log("Answer:", output.text);
});

await agent.run("Hello");
```

`agent.events` is the same object as `agent.eventBus`.

***

## Listen to everything — `onAny`

Best attachment point for tracers. You don't have to list 70 event names.

```typescript theme={null}
agent.eventBus.onAny((event, data) => {
  console.log(event, data);
});
```

***

## One bus for the whole process

By default **each** agent/team/workflow gets its **own** bus. A tracer on agent A will not see agent B.

Share one:

```typescript theme={null}
// Option A
new Agent({ name: "a", model, sharedEventBus: true });
new Agent({ name: "b", model, sharedEventBus: true });

// Option B
new Agent({ name: "a", model, eventBus: EventBus.shared });
```

```typescript theme={null}
import { EventBus } from "@agentium/core";

EventBus.shared.onAny((event, data) => {
  // every entity in this Node process
});
```

`EventBus.resetShared()` exists for tests.

***

## Events that actually fire

Prefer this short list (`LIFECYCLE_EVENTS`):

| Event                                                     | When                           |
| --------------------------------------------------------- | ------------------------------ |
| `run.start`                                               | A run begins                   |
| `run.complete`                                            | A run finished                 |
| `run.error`                                               | A run threw                    |
| `run.cancelled`                                           | `AbortSignal` fired            |
| `run.stream.chunk`                                        | A stream piece                 |
| `tool.call` / `tool.result`                               | A tool ran                     |
| `tool.approval.request` / `tool.approval.response`        | Human gate                     |
| `team.delegate`                                           | Team handed work to a member   |
| `handoff.transfer` / `handoff.complete`                   | Agent handoff                  |
| `workflow.step`                                           | Workflow step start/done/error |
| `memory.extract` / `memory.error`                         | Memory job                     |
| `memory.correction.recorded`                              | Human correction saved         |
| `memory.learning.invalidated`                             | A lesson was superseded        |
| `cost.tracked`                                            | Tokens billed                  |
| `cache.hit` / `cache.miss`                                | Semantic cache                 |
| `subagent.start` / `subagent.complete` / `subagent.error` | Helper agent                   |

Many older names in `AgentEventMap` are marked **@deprecated** and are **never emitted**. Don't build products on them.

Import the list:

```typescript theme={null}
import { LIFECYCLE_EVENTS } from "@agentium/core";
```

***

## Methods

| Method                       | Meaning                               |
| ---------------------------- | ------------------------------------- |
| `on(event, handler)`         | Call me every time                    |
| `once(event, handler)`       | Call me once                          |
| `off(event, handler)`        | Stop calling me                       |
| `onAny(handler)`             | Call me for every event               |
| `offAny(handler)`            | Stop the catch-all                    |
| `emit(event, data)`          | (internal) drop a note in the mailbox |
| `removeAllListeners(event?)` | Clear listeners                       |

`EventBus.shared` — process-wide singleton.

***

## Observability

`@agentium/observability` already listens to the bus. You usually just call `instrument(agent)`. See [Observability](/observability/overview).
