> ## 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 three 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), and HoloTab (a free no-code Chrome extension that runs Holo in the user's browser, with recordable routines and schedules). The `holo` CLI (`pip install "hai-agents[cli]"`) runs Agents API agents from a terminal, drives the user's own desktop with `-a h/holo-desktop`, and serves coding agents through `holo mcp`.
> 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: `holo`.
> 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.

# The event object

> The shape of every event a session records.

## Event shape

Every event, from [Events](https://hub.hcompany.ai/agents-api/sessions/events.md) and [Changes](https://hub.hcompany.ai/agents-api/sessions/changes.md), 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](#event-types-type). |
| `data` | object | Type-specific payload. |
| `timestamp` | string | ISO 8601 time the event was recorded. |

## Event types (`type`)

`data` is an open object shaped by `type`. This list is representative: other types such as `DelayAgentStartEvent` may appear.

| `type` | Emitted when |
| - | - |
| `RequestStartEvent` | The session request is received. |
| `RequestStartDispatchedEvent` | The session is dispatched for execution. |
| `AgentStartedEvent` | The agent begins executing. |
| `AgentEvent` | The agent observes, decides, acts, or answers. |
| `MetricsUpdateEvent` | Usage and cost are rolled up. Costs are in USD and `null` when a model's price is unavailable. |
| `ActiveStateChangeEvent` | The agent's active state changes. In `awaiting_tool_results`, `pending_tool_calls` lists the [custom tool](https://hub.hcompany.ai/agents-api/custom-tools.md) calls to answer. |
| `AgentRunStatusChangeEvent` | The session is paused or resumed. |
| `LiveViewUrlEvent` | A live view URL becomes available. |
| `AgentCompletionEvent` | The agent stops. |
| `AgentErrorEvent` | The agent fails. The session moves to `failed`. |
| `RunnerSessionEvent` | An environment, such as the cloud browser, comes online. The [session files](https://hub.hcompany.ai/agents-api/sessions/list-files.md) endpoints accept its `runner_session_id` or the agent session ID. |
| `FileTransferEvent` | The agent reads a file out of its browser (`download`) or writes one in (`upload`). `size_bytes` is `null` for reads. |
| `AttachmentEvent` | The user or the agent attaches a file to the session. `url` downloads it, and so does [`file_id`](https://hub.hcompany.ai/agents-api/sessions/resources#download-a-shared-file) when the platform stored the file. |

```json Event data by type theme={"system"}
[
  { "type": "RequestStartEvent", "data": {} },
  { "type": "RequestStartDispatchedEvent", "data": { "status": "..." } },
  { "type": "AgentStartedEvent", "data": {} },
  { "type": "MetricsUpdateEvent", "data": { "metrics": { "steps": 3, "total_cost": 0.0021, "input_cost": 0.0016, "output_cost": 0.0005, "reasoning_cost": 0.0, "cost_per_model": [] } } },
  { "type": "ActiveStateChangeEvent", "data": { "state": "awaiting_tool_results", "pending_tool_calls": [{ "tool_name": "lookup_order", "args": { "order_id": "A-1042" }, "id": "call_1" }] } },
  { "type": "AgentRunStatusChangeEvent", "data": { "status": "paused" } },
  { "type": "LiveViewUrlEvent", "data": { "live_view_url": "https://..." } },
  { "type": "AgentCompletionEvent", "data": { "reason": "finished" } },
  { "type": "AgentErrorEvent", "data": { "error": "...", "trace": "...", "info": {} } },
  { "type": "RunnerSessionEvent", "data": { "runner_session_id": "...", "kind": "web" } },
  { "type": "FileTransferEvent", "data": { "direction": "upload", "path": "report.pdf", "size_bytes": 1234 } },
  { "type": "AttachmentEvent", "data": { "origin": "agent", "name": "report.pdf", "path": "...", "media_type": "application/pdf", "size_bytes": 1234, "url": "https://...", "file_id": "..." } }
]
```

## 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` | Emitted when |
| - | - |
| `policy_event` | The agent decides: its reasoning, message, and the actions it chose. `content` and `reasoning_content` may be `null`. |
| `observation_event` | The agent perceives its environment ([observation shapes](#observation-shapes)). |
| `tool_result` | An action returns. `result` is opaque JSON. Oversized text output is cut to a head and tail preview (16 KiB) with `truncated: true`. With a code sandbox, the full text is kept there and `output_artifact_path` is its path inside the sandbox, not a URL. |
| `answer_event` | The agent answers. Same value as the [`/changes`](https://hub.hcompany.ai/agents-api/sessions/changes) `answer`. |
| `error_event` | A step hits a recoverable error, for example a failed or invalid action. |
| `message_event` | A user or agent message arrives. |
| `flow_event` | A control-flow signal fires: `pause`, `resume`, or `force_answer`, including the ones you trigger with the [session controls](https://hub.hcompany.ai/agents-api/sessions/pause.md), and `reset_history` when the agent [compacts its context](https://hub.hcompany.ai/agents-api/agents/overview.md). |

```json AgentEvent data by kind theme={"system"}
[
  { "kind": "policy_event", "reasoning_content": "...", "content": "...", "tool_reqs": [{ "tool_name": "...", "args": {}, "id": "call_7" }], "validation_errors": [] },
  { "kind": "tool_result", "tool_req": { "tool_name": "...", "args": {}, "id": "call_7" }, "result": {}, "truncated": false, "output_artifact_path": null },
  { "kind": "answer_event", "answer": "...", "outcome": "success" },
  { "kind": "error_event", "error": "...", "origin": "...", "tool_req": null },
  { "kind": "message_event", "caller_id": "user", "content": ["..."] },
  { "kind": "flow_event", "flow": "pause", "origin": "..." }
]
```

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`](https://hub.hcompany.ai/agents-api/browser/configuration#modes).

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 (for example `[page unchanged since previous observation]`) and is `null` for most observations.

In `visual` mode the Browser emits `web`: 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. |

In `text` mode it emits `textual_web`: 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.


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