# Events reference

> One catalog names every event. A conversation's stream carries what happens as it happens; your webhooks get what settles. Each event says where it arrives, what it means, and every field of its `data`.

## How each arrives

The SDKs hand you both as one event: `event.type`, `event.user` and `event.data`.

On the stream:

- `seq` (`integer`): Its place on the conversation's stream, counting up: send the last one you saw to pick up after it.
- `type` (`string`): What happened, from the one catalog of events: the events reference says what each carries and where it is delivered. Limits: one of 34 values. Example: `message.completed`.
- `data` (`map of any`): What it says: its fields depend on its type, as the events reference lists them.
- `created_at` (`string`): When it happened, as an ISO 8601 time.

In a webhook:

- `id` (`string`): The event (evt_...): the same on every retry, so use it to skip one you already took. Example: `evt_4hq`.
- `object` (`"event"`): Always event.
- `type` (`string`): An event a webhook carries: every event of the catalog but the six that ride only the stream (message.delta, task.progress, usage.updated, screen.control, error and ping). Limits: one of 28 values. Example: `task.completed`.
- `mode` (`"live" | "test"`): The mode it happened in: test or live.
- `created_at` (`string`): When it happened, as an ISO 8601 time.
- `user_id` (`string | null`): Your id for the user it concerns; null for your company's own Bash, or when it concerns no user.
- `task_id` (`string | null`): The task it concerns (task_...); null when none.
- `conversation_id` (`string | null`): The conversation it concerns (conv_...); null when none.
- `data` (`map of any`): What it says: its fields depend on its type, as the events reference lists them.

## The reply

### `message.delta`

The reply as it is written, a piece at a time. Arrives: stream only.

- `text` (`string`): The next piece of the reply, as it is written.
- `turn_id` (`string`, may be absent): The turn it belongs to (turn_...).
- `task_id` (`string`, may be absent): For words a task writes, rather than Bash's reply: the task (task_...).

### `message.completed`

The reply is complete: its answer (its final words, after any search), its whole text, and what the turn cost. An empty text means the turn only started work: `task.started` names it. Arrives: stream and webhook.

- `text` (`string`): The whole reply. For a message sent straight to work: Started work on it. Empty when Bash started work without a word.
- `answer` (`string | null`, may be absent): The reply's answer: its final words, the part after any search or lookup Bash made on the way, trimmed; null when it said nothing. Absent from older events.
- `turn_id` (`string`, may be absent): The turn (turn_...).
- `task_id` (`string`, may be absent): For a task's words (every step's, joined), rather than Bash's reply: the task (task_...).
- `data` (`unknown`, may be absent): The data you asked for with output_schema, when the reply carries it.
- `error` (`{ code: string; message: string }`, may be absent): Why the turn failed, as a code and a message in plain words; absent when it did not.
- `usage` (`{ turn_cost_usd: number; conversation_total_usd: number; cost_complete: boolean } | null`, may be absent): What the turn has cost (turn_cost_usd), the conversation's total, and whether every charge is in (cost_complete); null when it could not be read.

## The work

### `task.started`

Bash started work on its computer: the task's id and title. Arrives: stream and webhook.

- `task_id` (`string`): The task Bash started (task_...).
- `title` (`string | null`): What the work is, in a few words; null until Bash names it.
- `turn_id` (`string`, may be absent): The turn that started it (turn_...).

### `task.progress`

A step of the work, or a change in its status. Arrives: stream only.

- `progress` (`'step' | 'status'`): step: a step of the work (a tool used, or its to-do list). status: where the work is (working, waiting).
- `task_id` (`string`, may be absent): The task (task_...), on a conversation's stream.
- `turn_id` (`string`, may be absent): The turn (turn_...), when Bash's reply took the step.
- `status` (`string`, may be absent): For a status: working, or waiting on an approval or a question.
- `tool` (`string`, may be absent): For a step Bash's reply took: the tool it used.
- `todos` (`{ content: string; status: string; }[]`, may be absent): For a to-do list: each step of the plan, with its content and its status (pending, in_progress, completed).

### `task.completed`

The work is done: its answer (its final reply), its summary, and what it cost. Arrives: stream and webhook.

- `task_id` (`string`): The task (task_...).
- `status` (`string`, may be absent): How it ended, on the conversation's stream: completed, failed or stopped.
- `cost_usd` (`number | null`, may be absent): What it cost, in billed US dollars; null when not known yet.
- `cost_complete` (`boolean`, may be absent): Whether every charge is in: false when the last ones can still land, on usage.updated.
- `summary` (`string | null`, may be absent): Everything the work said, every step's words joined: its narration and its final reply together; null when it said nothing.
- `answer` (`string | null`, may be absent): The work's answer: its final reply, the words of its last step that said anything; null when none did. Absent from older events.

### `task.failed`

The work failed: why, and what it cost. Arrives: stream and webhook.

- `task_id` (`string`): The task (task_...).
- `status` (`string`, may be absent): How it ended, on the conversation's stream: completed, failed or stopped.
- `cost_usd` (`number | null`, may be absent): What it cost, in billed US dollars; null when not known yet.
- `cost_complete` (`boolean`, may be absent): Whether every charge is in: false when the last ones can still land, on usage.updated.
- `reason` (`string`, may be absent): Why it failed, as a short code, such as disconnected.
- `message` (`string | null`, may be absent): More about why, in plain words; null when there is no more.
- `title` (`string`, may be absent): What the work was, when it failed before it started.
- `turn_id` (`string`, may be absent): The turn that tried to start it (turn_...), when it failed before it started.

### `task.stopped`

The work was stopped: by you or a person, or by a limit, the credits running out or a policy, which its reason names. Arrives: stream and webhook.

- `task_id` (`string`): The task (task_...).
- `status` (`string`, may be absent): How it ended, on the conversation's stream: completed, failed or stopped.
- `cost_usd` (`number | null`, may be absent): What it cost, in billed US dollars; null when not known yet.
- `cost_complete` (`boolean`, may be absent): Whether every charge is in: false when the last ones can still land, on usage.updated.
- `reason` (`string`, may be absent): Why it stopped, when a limit or a policy stopped it rather than a person: max_turns, max_budget, credits_exhausted (the account's credits ran out) or hook_blocked.
- `message` (`string | null`, may be absent): More about why, in plain words (a policy hook's own words); null when there is no more.

## What Bash waits on

### `interaction.created`

Bash waits on someone: an approval, a question, an app to connect, a hand-off, or a call to your tool. Arrives: stream and webhook.

- `interaction_id` (`string`): What Bash waits on, to answer by its id (int_..., or call_... for a call to your tool).
- `type` (`InteractionType`): What answer it takes: approval, question, connect, handoff or tool_call.
- `task_id` (`string`, may be absent): The task that asked (task_...).
- `turn_id` (`string`, may be absent): For a call to your tool from Bash's reply: the turn (turn_...).
- `name` (`string`, may be absent): For a call to your tool: the tool's name.
- `arguments` (`unknown`, may be absent): For a call to your tool: what Bash passed it.
- `server` (`string`, may be absent): For a call to a tool of your MCP server in a test run, which Bash never runs for real there: the server's slug.

### `interaction.resolved`

What Bash waited on was answered, or withdrawn. Arrives: stream and webhook.

- `interaction_id` (`string`, may be absent): What was answered, withdrawn or closed (int_... or call_...). Absent when interaction is sent instead.
- `interaction` (`Interaction`, may be absent): For an ask that settles without waking the work (a hand-off's verdict, a question the server asked), answered or withdrawn: the whole interaction, with its outcome. Webhook only.
- `type` (`InteractionType`, may be absent): For a call to your tool: tool_call.
- `task_id` (`string`, may be absent): The task that asked (task_...).
- `outcome` (`string`, may be absent): cancelled: its task's stop or failure, or a newer message, closed it unanswered. Absent when it was answered or withdrawn.
- `reason` (`string`, may be absent): With outcome cancelled: stopped or failed (its task ended), or superseded (a new message came in).
- `status` (`string`, may be absent): For a call to your tool: completed with your output, or failed with your error.

### `interaction.expired`

A call to your tool went unanswered for too long. Arrives: stream and webhook.

- `interaction_id` (`string`): What expired unanswered (int_... or call_...).
- `type` (`InteractionType`, may be absent): What answer it took.
- `task_id` (`string`, may be absent): The task that asked (task_...).

## The screen

### `screen.control`

Who has the screen: a person took the wheel, or Bash has it back. Arrives: stream only.

- `by` (`'user' | 'bash'`): Who drives the screen now: user, the person, or bash.
- `session_id` (`string`, may be absent): The session the person drives from (ses_...).

## Sessions

### `session.started`

A session opened: a live screen, a voice call, or Bash inside your app. Arrives: stream and webhook.

- `session_id` (`string`): The session (ses_...).
- `user_id` (`string | null`): Your id for its user; null on your company's own Bash.
- `conversation_id` (`string | null`): Its conversation (conv_...); null for a screen opened alone.
- `chat` (`boolean`): Whether it shows the conversation.
- `screen` (`false | 'view' | 'control'`): Its screen: view, control, or false for none.
- `voice` (`boolean`): Whether your user can talk by voice.
- `memory` (`boolean`): Whether it shows what Bash remembers.
- `expires_at` (`string`): When its token stops working, as an ISO 8601 time.

### `session.ended`

A session ended. A voice call's carries its `seconds` and its `transcript`. Arrives: stream and webhook.

- `session_id` (`string | null`): The session (ses_...); null for a call that no session opened.
- `user_id` (`string | null`): Your id for its user; null on your company's own Bash.
- `conversation_id` (`string | null`): Its conversation (conv_...); null when it had none.
- `end_reason` (`string`): Why it ended: revoked when you ended the session, otherwise how its call ended, such as lost.
- `seconds` (`number`, may be absent): For a call: how long it lasted, in seconds.
- `transcript` (`{ speaker: "user" | "bash"; text: string; }[]`, may be absent): For a call: what was said, in order, by user or bash.
- `transcript_truncated` (`boolean`, may be absent): For a call: true when the transcript stops at its 100,000 characters.

## Files

### `file.created`

Bash made a file: its id, its name and its task. Arrives: stream and webhook.

- `file_id` (`string`): The file (file_...): read it with GET /v1/files/{file_id}.
- `task_id` (`string`, may be absent): The task that made it (task_...).
- `filename` (`string | null`): Its name; null when it has none.
- `mime_type` (`string | null`): Its type, such as application/pdf; null when unknown.
- `size_bytes` (`number | null`): Its size, in bytes; null when unknown.

## Routines

### `routine.fired`

A routine ran, on its schedule or on your call. Arrives: stream and webhook.

- `routine_id` (`string`): The routine (rtn_...).
- `run_id` (`string`): This run of it.
- `conversation_id` (`string`): The conversation the run posts into (conv_...).
- `user_id` (`string | null`): Your id for its user; null on your company's own Bash.
- `turn_id` (`string`): The turn the run started (turn_...).

## Money

### `usage.updated`

Charges that landed after a turn settled, for the turn and its work. Arrives: stream only.

- `delta_usd` (`number`): What was just charged, in billed US dollars.
- `task_id` (`string`, may be absent): The task it was charged to (task_...), when it was.
- `task_total_usd` (`number`, may be absent): That task's total so far, in billed US dollars.
- `conversation_total_usd` (`number | null`): The conversation's total so far, in billed US dollars; null when not known.
- `user` (`{ day: { spent_usd: number; cap_usd: number | null; remaining_usd: number | null }; month: { spent_usd: number; cap_usd: number | null; remaining_usd: number | null } } | null`): The spend, cap and what is left, today and this month, of the user the charge was billed to (your company's own Bash counts as one); null when the standing could not be read.
- `as_of` (`string`): When these numbers were read, as an ISO 8601 time.

### `usage.threshold_reached`

Spend passed one of your alert thresholds. Arrives: webhook only.

- `scope` (`'company' | 'user'`): Whose spend: company, all of your company's, or user, one user's.
- `user_id` (`string`, may be absent): For a user's alert: your id for the user.
- `period` (`'day' | 'month'`): The period the cap is for: day or month (UTC).
- `period_start` (`string`): When the period started, as an ISO 8601 time.
- `threshold_pct` (`number`): The share of the cap spent, in percent: one of your alert thresholds, or 100 at the cap.
- `spent_usd` (`number`): What has been spent in the period, in billed US dollars.
- `cap_usd` (`number`): The cap, in US dollars.

### `usage.cap_reached`

Spend reached one of your caps. Arrives: webhook only.

- `scope` (`'company' | 'user'`): Whose spend: company, all of your company's, or user, one user's.
- `user_id` (`string`, may be absent): For a user's alert: your id for the user.
- `period` (`'day' | 'month'`): The period the cap is for: day or month (UTC).
- `period_start` (`string`): When the period started, as an ISO 8601 time.
- `threshold_pct` (`number`): The share of the cap spent, in percent: one of your alert thresholds, or 100 at the cap.
- `spent_usd` (`number`): What has been spent in the period, in billed US dollars.
- `cap_usd` (`number`): The cap, in US dollars.

## The conversation

### `conversation.status`

The conversation's status (`idle`, `replying`, `working` or `waiting`) and its turn's: `turn_status` is `running`, `working`, `requires_action`, `completed`, `failed` or `stopped`. Webhooks carry the turns that settle. Arrives: stream and webhook.

- `status` (`'idle' | 'replying' | 'working' | 'waiting'`): What the conversation is doing now: idle, replying, working or waiting.
- `turn_id` (`string`, may be absent): The turn that changed it (turn_...).
- `turn_status` (`'running' | 'working' | 'requires_action' | 'completed' | 'failed' | 'stopped'`, may be absent): Where that turn is now: running, working, requires_action, or settled as completed, failed or stopped.
- `data` (`unknown`, may be absent): When the turn settled: the data you asked for with output_schema.
- `outcome` (`{ met: boolean; reason: string }`, may be absent): When the turn settled: whether it met your success_criteria (met), and why (reason).
- `error` (`{ code: string; message: string }`, may be absent): When the turn failed: why, as a code and a message.
- `usage` (`{ turn_cost_usd: number; conversation_total_usd: number; cost_complete: boolean } | null`, may be absent): When the turn settled: what it cost, the conversation's total, and whether every charge is in.

## Users

### `user.created`

A user was made, the first time you named them. Arrives: webhook only.

- `user_id` (`string`): Your id for the user Vestra just made, the first time you named them.

### `user.deleted`

A user's erasure finished: their Bash, computer, memory and files are gone. Arrives: webhook only.

- `user_id` (`string`): Your id for the user who was erased.
- `complete` (`boolean`, may be absent): Whether every part was erased; false when a part could not be, and it is retried.

## Connected apps

### `connection.completed`

An app was connected. Arrives: webhook only.

- `user_id` (`string | null`): Your id for the user who connected; null on your company's own Bash.
- `connection` (`{ object: 'connection'; id: string; user_id: string | null; app: string; status: string; label: string | null; created_at: string }`): The connection made: its id (con_...), app, status, label and when it was made.

### `connection.failed`

Connecting an app failed. Arrives: webhook only.

- `user_id` (`string | null`): Your id for the user; null on your company's own Bash.
- `app` (`string`): The app that did not connect.
- `connection_id` (`string | null`): The connection that failed (con_...); null when none was made.
- `reason` (`string | null`): Why, in plain words; null when the app did not say.

### `connection.removed`

An app was disconnected. Arrives: webhook only.

- `user_id` (`string | null`): Your id for the user; null on your company's own Bash.
- `connection_id` (`string`): The connection removed (con_...).
- `app` (`string`): Its app.

## Memory

### `memory.observed`

Bash learned something new to remember about a user. Arrives: webhook only.

- `user_id` (`string`): Your id for the user Bash learned about.
- `task_id` (`string`): The task it learned it in (task_...).
- `conversation_id` (`string`, may be absent): That task's conversation (conv_...).
- `observation` (`string`): What Bash learned, in plain words: keep it in your memory, which your memory endpoint gives back.
- `kind` (`string`): What kind of fact it is, such as preference or identity.
- `source` (`string`): How Bash learned it, such as agent_inferred.
- `observed_at` (`string`): When it learned it, as an ISO 8601 time.

## Batches

### `batch.completed`

Every item of a batch has finished. Arrives: webhook only.

- `batch_id` (`string`): The batch (bat_...).
- `status` (`'completed' | 'cancelled'`): completed: every item finished. cancelled: you cancelled it.
- `item_count` (`number`): How many items it had.
- `counts` (`{ queued: number; running: number; succeeded: number; failed: number; cancelled: number }`): Its items, by status: queued, running, succeeded, failed and cancelled.

## Deployments

### `deployment.version_created`

A deployment has a new version. Arrives: webhook only.

- `deployment_id` (`string`): The deployment (dep_...).
- `version` (`number`): The new version.
- `manifest_sha256` (`string`): A fingerprint of the version's file: two versions with the same one are the same setup.

### `deployment.promoted`

A version went live in its mode. Arrives: webhook only.

- `deployment_id` (`string`): The deployment (dep_...).
- `from_version` (`number | null`): The version it ran before; null when none did.
- `to_version` (`number`): The version it runs now.
- `became_default` (`boolean`): Whether this promotion made the deployment your company's default.

### `deployment.rolled_back`

A deployment went back to an earlier version. Arrives: webhook only.

- `deployment_id` (`string`): The deployment (dep_...).
- `from_version` (`number | null`): The version it ran before; null when none did.
- `to_version` (`number`): The version it runs now.

## Tests

### `test_run.completed`

A test run finished, with how many scenarios passed. Its `error_code` is null unless the run ended in `error`: `interrupted` when it stopped reporting. Arrives: webhook only.

- `test_run_id` (`string`): The test run (trun_...).
- `deployment_id` (`string`): The deployment it tested (dep_...).
- `version` (`number`): The version it tested.
- `status` (`'passed' | 'failed' | 'error'`): passed: every test passed. failed: at least one did not. error: the run could not finish.
- `error_code` (`string | null`): Why the run could not finish, such as interrupted; null unless its status is error.
- `passed` (`number`): How many tests passed.
- `total` (`number`): How many tests it played.
- `promoted` (`{ mode: 'live' | 'test'; version: number } | null`): What the pass promoted, its mode and version; null when it promoted nothing.
- `became_default` (`boolean`): Whether that promotion made the deployment your company's default.

## Keys

### `key.created`

A key was made. Arrives: webhook only.

- `key_id` (`string`): The key (key_...).
- `name` (`string | null`, may be absent): Its name; null when it has none.

### `key.revoked`

A key was revoked. Arrives: webhook only.

- `key_id` (`string`): The key that stopped working (key_...).

## The stream itself

### `error`

The stream's own error: its code and its message. Arrives: stream only.

- `code` (`string`): A stable code to branch on.
- `message` (`string`): What went wrong, in plain words.
- `turn_id` (`string`, may be absent): The turn it happened in (turn_...).

### `ping`

A keep-alive on the stream: nothing happened. Arrives: stream only.

No data: it says only that it happened.
