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

# Events

> Run JavaScript or Python whenever a selected agent event fires.

The **Events** page lets you attach a small script to any agent event. Each time
that event fires, your code runs in a secure sandbox with the event's data. Unlike
[Hooks](/sidebar-menu/hooks) (which call an external URL and can block or rewrite the
request) and the [event pre-processor](/sidebar-menu/event-pre-processor) (which
returns a verdict for inbound messages), event actions are **fire-and-forget
side-effects**: they never block the agent and their return value is ignored — but
they can still *act* through `ctx.tools`.

One exception: **Goal Check** rows under the *Goals & Handoff* channel are not event
actions — they are per-goal verification code whose return value *is* the verdict,
stored on the goal itself (Purpose page) and merely editable here too. See
[Goals & Goal Checks](/sidebar-menu/goals).

## Creating an event action

1. Pick a **channel / category** (Conversation, Tools, Goals & Handoff, Billing,
   Automation, Email, Messaging, Feeds, Webhook, or Connectors).
2. Pick an **event** within that channel. The info box shows exactly what data the
   event passes to your script.
3. Click **Create action**, then write your script in the editor on the right.

## The script

Your code defines `handle(event, ctx)`:

```js theme={null}
async function handle(event, ctx) {
  // `event` is the payload for this event (see the info box for every field).
  // For lifecycle events, the fields are on `event` directly.
  // For inbound channels (Email/Messaging/Feeds/Webhook/Connectors),
  // the per-event fields are under `event.payload`.

  await ctx.tools.email_send({
    to: 'ops@example.com',
    subject: `New payment: ${event.tier_name}`,
    body: JSON.stringify(event),
  });

  ctx.audit('handled', { session: event.session_id });
}
```

* **`event`** — the event payload. Every field is documented in the info box next to
  the event selector.
* **`ctx.tools.<name>(input)`** — call the agent's tools (send email, read mail, web
  search, memory, run code, and more). Calls are billed and rate-limited exactly as
  when the agent calls them.
* **`ctx.audit(event, data)`** — record a structured note.

Python is also supported (define `async def handle(event, ctx)`); the language is
auto-detected and selectable per action.

## Channels & events

| Category                      | Events                                                                       |
| ----------------------------- | ---------------------------------------------------------------------------- |
| **Conversation**              | on user message, before query, after query, on error, conversation start/end |
| **Tools**                     | before tool call, after tool call                                            |
| **Goals & Handoff**           | goal complete, on handoff, handoff resolved, on alert                        |
| **Billing**                   | on payment, on rate limit                                                    |
| **Automation**                | scheduled run                                                                |
| **Email / Messaging / Feeds** | inbound email, inbound message, new feed item                                |
| **Webhook / Connectors**      | inbound webhook, connector event                                             |

<Note>
  Actions run fire-and-forget and cannot block, drop, or rewrite an event. To gate or
  transform inbound messages, use the [event pre-processor](/sidebar-menu/event-pre-processor);
  to control the chat flow, use [Hooks](/sidebar-menu/hooks).
</Note>
