> ## 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.

# Handle API errors

> Agents API error envelope, HTTP status codes from 400 to 504, how the SDKs raise and retry errors, and how to read a failed session's outcome and error code.

Failures come in two kinds:

* **HTTP errors**: the API rejected the request or hit a server fault. Every endpoint returns the same envelope.
* **[Session failures](#session-failures)**: the request was accepted, but the run ended `failed` or `timed_out`. The session's `error_code` says why.

## Error object

Every error response carries the same [envelope](/agents-api/api-reference#errors): a `message` that summarizes the problem, and a `detail` array with one entry per problem. For `422` validation errors, each `detail` entry keeps the failing field's path and reason, and `message` flattens them into one line:

```json Validation error (422) theme={"system"}
{
  "message": "agent: Field required",
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "agent"],
      "msg": "Field required",
      "input": {}
    }
  ]
}
```

Requests rejected before they reach the API (for example `401`) may carry only a `message`.

## HTTP status codes

### Success codes

| Code | Meaning | Used by |
| - | - | - |
| `200 OK` | Request succeeded. | GET endpoints, updates. |
| `201 Created` | Resource created. | POST /sessions, POST /agents. |
| `202 Accepted` | Action accepted, processed asynchronously. | POST /messages, POST /pause, POST /resume. |
| `204 No Content` | Action succeeded, no body. | DELETE /sessions, DELETE /agents. |

### Client error codes

| Code | Meaning | Common cause | What to do |
| - | - | - | - |
| `400 Bad Request` | Malformed request or invalid parameters. | Sending an event to a session that can't accept it. | Check the body against the endpoint docs. |
| `401 Unauthorized` | Missing or invalid API key. | No `Authorization` header, or expired key. | Check the key and its format. |
| `402 Payment Required` | Monthly token budget exhausted. | Creating (or restarting) a session after your organization used its plan's tokens. | `detail` carries `limit`, `used`, and `window_end`. Wait for the reset or upgrade. See [Token usage](/agents-api/plans-and-limits#token-usage). |
| `403 Forbidden` | Valid key, not allowed. | Modifying a reserved `h/` agent. | Check that your role allows it. |
| `404 Not Found` | Resource missing or not visible to you. | Wrong session ID, or another team's resource. | Check the ID and your access. |
| `409 Conflict` | Resource exists, or an identical idempotent request is still in flight. | Duplicate agent name, or a retry with the same [`Idempotency-Key`](/agents-api/sessions/create#header-idempotency-key) before the first finished. | Use a unique name, fetch the existing resource, or wait. |
| `422 Unprocessable Entity` | Body fails validation. | Missing fields, wrong types. | Read the `detail` array. |
| `429 Too Many Requests` | At the concurrency limit with [queueing](/agents-api/plans-and-limits#queued-sessions) declined, or the queue is full. | Too many sessions at once. | Leave `queue` at its default, wait for sessions to finish, or ask for a higher quota. See [Concurrent sessions](/agents-api/plans-and-limits#concurrent-sessions). |

### Server error codes

| Code | Meaning | What to do |
| - | - | - |
| `502 Bad Gateway` | Upstream service error. | Retry after a short pause. |
| `503 Service Unavailable` | Temporary capacity issue. | Retry after `Retry-After`. |
| `504 Gateway Timeout` | Request took too long. | Retry. |

## Handling errors with the SDK

The SDKs raise a typed error on any non-2xx response, with `status_code` / `statusCode` and the parsed `body`.

<CodeGroup>
  ```python Python theme={"system"}
  from hai_agents import Client
  from hai_agents.core import ApiError

  client = Client()

  try:
      session = client.sessions.create_session(
          agent="h/web-surfer-flash",
          messages=[{"type": "user_message", "message": "Open Hacker News and list the top 3 stories with their URLs."}],
      )
  except ApiError as err:
      print(err.status_code, err.body)
  ```

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

  const client = new HaiAgentsClient();

  try {
    const session = await client.sessions.createSession({
      body: {
        agent: "h/web-surfer-flash",
        messages: [{ type: "user_message", message: "Open Hacker News and list the top 3 stories with their URLs." }],
      },
    });
  } catch (err) {
    if (err instanceof HaiAgentsError) {
      console.error(err.statusCode, err.body);
    }
  }
  ```
</CodeGroup>

| Codes | Retry? |
| - | - |
| `408`, `429`, `5xx` | Yes. The SDKs retry with backoff, twice by default (tune with [`max_retries`](/agents-api/sdks#client-configuration)). Over raw HTTP, retry with backoff and honor `Retry-After`. |
| `400`, `401`, `402`, `403`, `404`, `422` | No. The same request fails the same way: fix it. |

Over-quota session creates need no retry logic: they [queue](/agents-api/plans-and-limits#queued-sessions) by default and start on their own.

## Session failures

A settled session reports two signals on [`status`](/agents-api/sessions/status), the [Session object](/agents-api/sessions/overview), and [`changes`](/agents-api/sessions/changes), so your code can branch without parsing prose.

### Outcomes

A session can end `completed` and still not do what you asked. `outcome` is the agent's own assessment, reported with its final answer:

| `outcome` | Meaning | Typical next step |
| - | - | - |
| `success` | Task fully done. | Use the answer. |
| `partial` | Some of the task done, not all. | Inspect before trusting. |
| `infeasible` | Can't be done as specified (for example, the item doesn't exist). | Don't retry. |
| `blocked` | An external obstacle stopped progress: login wall, captcha, missing permissions. | A human connects an account or a [vault](/agents-api/vaults/overview). |

`outcome` is a self-assessment, not verified ground truth: validate the answer itself for high-stakes flows. It is `null` when the agent ended without reporting one.

### Error codes

When a session ends `failed` or `timed_out`, it carries an `error_code` and an `error` message matching it:

| `error_code` | Meaning | Retry? |
| - | - | - |
| `environment_error` | The environment failed to provision or crashed. | Yes, as is. |
| `no_answer` | The agent ran out of budget (`max_steps` / `max_time_s`) or stopped without an answer. | Yes, with a higher budget or a narrower task. |
| `answer_validation` | The agent answered, but every attempt failed to match its `answer_format`. | Maybe. Simplify the schema or loosen required fields. |
| `timeout` | The session exceeded its maximum time (`status` is `timed_out`). | Yes, with a higher `max_time_s` or a smaller task. |
| `insufficient_credit` | The organization used its plan's included agent usage and has no credit left for the session's model calls. | Yes, after topping up credit or when the allowance renews. |
| `internal` | Unexpected platform error. | Yes, once. If it persists, contact support. |

* `error_code` is `null` unless the status is `failed` or `timed_out`.
* New codes may appear: treat unknown values like `internal`.
* `error` is a stable template derived from the code, never raw internals. Branch on `error_code`, log `error`.

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -s "https://agp.eu.hcompany.ai/api/v2/sessions/$SESSION_ID/status" \
    -H "Authorization: Bearer $HAI_API_KEY" | jq '{status, outcome, error_code, error}'
  ```

  ```python Python theme={"system"}
  result = client.run_session(
      agent="h/web-surfer-flash",
      messages="Cancel my Acme Co subscription",
  )

  if result.status in ("failed", "timed_out"):
      if result.error_code == "environment_error":
          ...  # transient: retry as is
      elif result.error_code in ("no_answer", "timeout"):
          ...  # raise the budget or narrow the task
      else:
          raise RuntimeError(f"Session failed: {result.error} ({result.error_code})")
  elif result.outcome == "blocked":
      ...  # needs credentials or a human in the loop
  elif result.outcome != "success":
      ...  # "partial", "infeasible", None: inspect before trusting
  ```

  ```typescript TypeScript theme={"system"}
  const result = await client.runSession({
    agent: "h/web-surfer-flash",
    messages: "Cancel my Acme Co subscription",
  });

  if (result.status === "failed" || result.status === "timed_out") {
    if (result.errorCode === "environment_error") {
      // transient: retry as is
    } else if (result.errorCode === "no_answer" || result.errorCode === "timeout") {
      // raise the budget or narrow the task
    } else {
      throw new Error(`Session failed: ${result.error} (${result.errorCode})`);
    }
  } else if (result.outcome === "blocked") {
    // needs credentials or a human in the loop
  } else if (result.outcome !== "success") {
    // "partial", "infeasible", undefined: inspect before trusting
  }
  ```
</CodeGroup>


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