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

> ## Agent Instructions
> H Platform has four products: the Agents API (managed computer-use agents, base URL https://agp.eu.hcompany.ai/api/v2 or https://agp.hcompany.ai/api/v2 for the US), the Models API (OpenAI-compatible Holo vision-language models at https://api.hcompany.ai/v1), HoloDesktop CLI (Holo on the user's own desktop), and HoloTab (a free no-code Chrome extension that runs Holo in the user's browser, with recordable routines and schedules).
> Authenticate with a bearer API key from the HAI_API_KEY environment variable. SDKs: `pip install hai-agents` (Python, `from hai_agents import Client`) and `npm install hai-agents` (TypeScript, `import { HaiAgentsClient } from "hai-agents"`). CLI: `hai`.
> Agents do work in a browser or on a desktop; describe the task as an imperative instruction. To run a task quickly, prefer the pre-built agent `h/web-surfer-flash`. Read results from the session's `latest_answer` after it reaches a terminal status.
> Sessions are the unit of work; wait for a terminal status (completed, failed, timed_out, interrupted) before reading the answer. Use webhooks or the `changes` long-poll endpoint to follow progress.

# List events

> Paginated list of everything the agent observed and did in a session, for replay and audit.

Returns a session's events, oldest first, for replay and audit. For live tailing, use [`/changes`](/agents-api/sessions/changes). Auth is optional, so public shares work.

**Returns** a [page envelope](/agents-api/api-reference#pagination) of events in the [event shape](#event-shape).

## Path parameters

<ParamField path="id" type="string" required>
  The session ID.
</ParamField>

## Query parameters

<ParamField query="page" type="integer" default="1">
  Page number (1-based).
</ParamField>

<ParamField query="size" type="integer" default="50">
  Items per page. Maximum: `200`.
</ParamField>

<ParamField query="sort" type="string" default="timestamp">
  Sort order. Options: `timestamp`, `-timestamp`.
</ParamField>

<ParamField query="type" type="string">
  Filter by event type, e.g. `AgentEvent` or `MetricsUpdateEvent`. See [Event shape](#event-shape) for the full list.
</ParamField>

## Event shape

Every event, on both this endpoint and [`/changes`](/agents-api/sessions/changes), is the same envelope:

```json Event envelope theme={"system"}
{ "type": "AgentEvent", "data": { "...": "..." }, "timestamp": "2026-06-01T15:14:05Z" }
```

| Field | Type | Description |
| - | - | - |
| `type` | string | The event type (see below). |
| `data` | object | Type-specific payload. |
| `timestamp` | string | ISO 8601 time the event was recorded. |

### Event types (`type`)

`data` is an open JSON object whose shape varies by type, so treat this list as representative rather than exhaustive (other types such as `DelayAgentStartEvent`, `AgentRunStatusChangeEvent`, and `LiveViewUrlEvent` may appear).

| `type` | `data` | Emitted when |
| - | - | - |
| `RequestStartEvent` | `{}` | The session request is received. |
| `RequestStartDispatchedEvent` | `{ "status": "..." }` | The run is dispatched for execution. |
| `AgentStartedEvent` | `{}` | The agent begins executing. |
| `AgentEvent` | the step event (see below) | The agent observes, decides, acts, or answers. |
| `MetricsUpdateEvent` | `{ "metrics": {...} }` | Usage and cost are rolled up. `metrics` carries `steps`, `total_cost`, `input_cost`, `output_cost`, `reasoning_cost`, and `cost_per_model[]`. Cost fields are in USD and `null` when a model's price is unavailable. |
| `ActiveStateChangeEvent` | `{ "state": "..." }` | The agent's active state changes (`running`, `idle`, or `awaiting_tool_results`, which also carries `pending_tool_calls` for [custom tools](/agents-api/custom-tools)). |
| `AgentCompletionEvent` | `{ "reason": "..." }` | The run ends (e.g. `"finished"`). |
| `AgentErrorEvent` | `{ "error": "...", "trace": "...", "info": ... }` | The run fails. The session moves to `failed`. |
| `RunnerSessionEvent` | `{ "runner_session_id": "..." }` | The agent connects to a cloud browser. `runner_session_id` is the browser session id that the [session files](/agents-api/sessions/list-files) endpoints address, not the agent session id. |
| `FileTransferEvent` | `{ "direction": "...", "path": "...", "size_bytes": 1234 }` | The agent reads a file out of its browser (`direction: "download"`) or writes one in (`"upload"`). `size_bytes` is `null` for reads. |
| `AttachmentEvent` | `{ "origin": "agent" \| "user", "name": "...", "path": "...", "media_type": "...", "size_bytes": 1234, "url": "..." }` | The user or the agent attaches a file to the session. `url` downloads it. |

### Agent activity (`AgentEvent.data`)

The agent's step-by-step trace lives inside `AgentEvent`. Its `data` is the step event, and `data.kind` tells you what happened:

| `data.kind` | Payload (under `data`) | Meaning |
| - | - | - |
| `policy_event` | `reasoning_content`, `content`, `tool_reqs[]`, `validation_errors[]` | The agent's decision: its reasoning, message, and the action(s) it chose. |
| `observation_event` | `type`, `text`, `image`, `metadata` (see [Observation shapes](#observation-shapes)) | What the agent perceived this step. |
| `tool_result` | `tool_req` (`tool_name`, `args`, `id`), `result`, `truncated`, `output_artifact_path` | The outcome of an action. `result` is opaque JSON. Oversized text output is cut to a head/tail preview (16 KiB) with `truncated: true`. When the agent has a code sandbox, the full text is kept there and `output_artifact_path` is its path inside the sandbox (not a URL). |
| `answer_event` | `answer` | The final answer. Same value as [`/changes`](/agents-api/sessions/changes) `answer`. |
| `error_event` | `error`, `origin`, `tool_req?` | A recoverable error during the step (e.g. a failed or invalid action). |
| `message_event` | `caller_id`, `content[]` | A user or agent message. |
| `flow_event` | `flow`, `origin` | A control-flow signal such as `pause`, `resume`, or `force_answer`, including the ones you trigger via the [session controls](/agents-api/sessions/pause), and `reset_history` when the agent [compacts its context](/agents-api/agents/overview#context-auto-compaction). |

Each `tool_reqs[]` entry (and `tool_result.tool_req`) is `{ tool_name, args, id }`. `policy_event.content` and `reasoning_content` may be `null`.

Parsing a stream means switching on the outer `type`, then for `AgentEvent`, on `data.kind`:

```json AgentEvent theme={"system"}
{
  "type": "AgentEvent",
  "timestamp": "2026-06-01T15:14:05Z",
  "data": {
    "kind": "observation_event",
    "type": "web",
    "text": null,
    "image": { "type": "url", "source": "https://.../screenshot-7f3a.png", "media_type": "image/png" },
    "metadata": {
      "url": "https://example.com",
      "title": "Example Domain",
      "text": "# Example Domain\nThis domain is for use in illustrative examples...",
      "tabs": ["0"],
      "current_tab": "0",
      "viewport_size": [1200, 1200],
      "page_size": [1200, 3000],
      "scroll_position": [0, 0]
    }
  }
}
```

### Observation shapes

An `observation_event` is flat: `type` names the environment that produced it, `image` is the screenshot (if any), and `metadata` is that environment's snapshot, shaped by `type` (an open object, so switch on `type` to read it). The Browser emits one of two `type`s, depending on the environment's [`mode`](/agents-api/browser/configuration).

The page text lives in `metadata`, not in the top-level `text`: read `metadata.text` for `web` and `metadata.page_markdown` (or `page_html`) for `textual_web`. The top-level `text` carries only occasional step notices (e.g. `[page unchanged since previous observation]`) and is `null` for most observations.

**`web`** is emitted in `visual` mode: a screenshot (top-level `image`) plus page `metadata`.

| `metadata` field | Type | Description |
| - | - | - |
| `url` | string | Current page URL. |
| `title` | string | Page title. |
| `text` | string | Visible page rendered as markdown. Empty unless the mode sets `markdown: true`. |
| `tabs` | string\[] | Open tab IDs. |
| `current_tab` | string | Active tab ID. |
| `viewport_size` | integer\[] | Viewport `[width, height]` in pixels. |
| `page_size` | integer\[] | Full page `[width, height]` in pixels. |
| `scroll_position` | integer\[] | Scroll offset `[x, y]` in pixels. |
| `cursor_position` | integer\[] \| null | Cursor `[x, y]` in pixels. |

**`textual_web`** is emitted in `text` mode: paginated page text under `metadata`, no screenshot.

| `metadata` field | Type | Description |
| - | - | - |
| `url` | string | Current page URL. |
| `title` | string | Page title. |
| `tabs` | string\[] | Open tab IDs. |
| `current_tab` | string | Active tab ID. |
| `mode` | string | `"markdown"` or `"html"`. |
| `page_markdown` | string | Full page rendered as markdown. |
| `page_html` | string | Full page HTML. |
| `text_offset` | integer | Start character offset of the current chunk. |
| `chunk_size` | integer | Characters per chunk. |
| `chunk_number` | integer | Current chunk, 1-based. |
| `total_chunks` | integer | Total chunks for the page. |

### Images

The `image` on an `observation_event`, and any image inside `message_event.content[]`, is `{ source, type, media_type }`. `type` is `url` for platform-served screenshots (fetch `source` with your API key) or `base64` for inline images. Images embedded in a `tool_result.result` or an `answer_event.answer` stay inline as base64 within that opaque payload, never as URLs.

## Examples

<CodeGroup>
  ```bash cURL theme={"system"}
  curl "https://agp.eu.hcompany.ai/api/v2/sessions/$SESSION_ID/events?size=10" \
    -H "Authorization: Bearer $HAI_API_KEY"
  ```

  ```python Python theme={"system"}
  from hai_agents import Client

  client = Client()

  page = client.sessions.list_session_events(session_id, size=10)
  for event in page.items:
      print(event.type, event.timestamp)
  ```

  ```typescript TypeScript theme={"system"}
  import { HaiAgentsClient } from "hai-agents";

  const client = new HaiAgentsClient();

  const page = await client.sessions.listSessionEvents({ id: sessionId, size: 10 });
  for (const event of page.items) {
    console.log(event.type, event.timestamp);
  }
  ```
</CodeGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.