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

# Get session status

> Lightweight polling endpoint for session progress.

Returns only the live status of a session: current state, step count, token usage, and subagent IDs. It's the cheapest call for a quick liveness check. To follow a run and read its `answer`, long-poll [`changes`](/computer-use-agents/sessions/changes) instead.

**Returns** a status object with the fields below.

***

## Path parameters

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

***

## Response

<ResponseField name="status" type="string" required>
  Current session state: `queued`, `pending`, `running`, `paused`, `idle`, `awaiting_tool_results`, `completed`, `failed`, `timed_out`, or `interrupted`.
</ResponseField>

<ResponseField name="error" type="string">
  Short, stable error message if the session failed or timed out. `null` otherwise. Branch on `error_code`, not on this text.
</ResponseField>

<ResponseField name="error_code" type="string">
  Machine-readable failure category if the session failed or timed out: `environment_error`, `no_answer`, `answer_validation`, `timeout`, or `internal`. `null` otherwise. See [Read how the run ended](/computer-use-agents/observe-and-steer#read-how-the-run-ended).
</ResponseField>

<ResponseField name="outcome" type="string">
  The agent's self-assessed task outcome, reported with its final answer: `success`, `partial`, `infeasible`, or `blocked`. `null` until reported. See [Read how the run ended](/computer-use-agents/observe-and-steer#outcomes).
</ResponseField>

<ResponseField name="steps" type="integer">
  Number of steps the agent has taken, where each step is one decide-and-act cycle.
</ResponseField>

<ResponseField name="usage_per_model" type="array">
  Per-model token usage. Each entry is an object with `name`, `input_tokens`, `output_tokens`, and `reasoning_tokens`. Empty array until the agent calls a model.

  ```json theme={null}
  "usage_per_model": [
    {
      "name": "holo3-1-35b-a3b",
      "input_tokens": 12400,
      "output_tokens": 890,
      "reasoning_tokens": 0
    }
  ]
  ```
</ResponseField>

<ResponseField name="subagent_session_ids" type="array">
  IDs of the child sessions this session spawned, empty if it ran no subagents. Pull the full roster, each child labeled with its `agent`, with [`GET /sessions?parent_session_id={id}`](/computer-use-agents/sessions/list#find-the-subagents-a-session-spawned).
</ResponseField>

***

## Examples

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

  ```python Python theme={null}
  from hai_agents import Client

  client = Client()

  status = client.sessions.get_session_status(session_id)
  print(status.status, status.steps)
  ```

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

  const client = new HaiAgentsClient();

  const status = await client.sessions.getSessionStatus({ id: sessionId });
  console.log(status.status, status.steps);
  ```
</CodeGroup>

```json Response theme={null}
{
  "status": "running",
  "error": null,
  "error_code": null,
  "outcome": null,
  "steps": 7,
  "usage_per_model": [
    {
      "name": "holo3-1-35b-a3b",
      "input_tokens": 12400,
      "output_tokens": 890,
      "reasoning_tokens": 0
    }
  ],
  "subagent_session_ids": []
}
```

***

## Polling pattern

A typical polling loop checks status every few seconds and branches on the result:

<CodeGroup>
  ```python Python theme={null}
  import time

  while True:
      status = client.sessions.get_session_status(session_id)

      match status.status:
          case "completed":
              # status carries no answer; read the snapshot off the session
              session = client.sessions.get_session(session_id)
              print(f"Done in {status.steps} steps: {session.latest_answer}")
              break
          case "failed" | "timed_out" | "interrupted":
              print(f"Session ended: {status.status}")
              if status.error:
                  print(f"  Error: {status.error}")
              break
          case _:
              print(f"  {status.status}... ({status.steps} steps)")
              time.sleep(3)
  ```

  ```typescript TypeScript theme={null}
  while (true) {
    const status = await client.sessions.getSessionStatus({ id: sessionId });

    if (status.status === "completed") {
      // status carries no answer; read the snapshot off the session
      const session = await client.sessions.getSession({ id: sessionId });
      console.log(`Done in ${status.steps} steps: ${session.latestAnswer}`);
      break;
    }
    if (["failed", "timed_out", "interrupted"].includes(status.status)) {
      console.log(`Session ended: ${status.status}`, status.error ?? "");
      break;
    }
    console.log(`  ${status.status}... (${status.steps} steps)`);
    await new Promise((resolve) => setTimeout(resolve, 3000));
  }
  ```
</CodeGroup>

For the polling interval, 2 to 5 seconds works well for most use cases. For longer tasks (10+ minutes), back off to 10 to 15 seconds to reduce API calls.
