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

# Read logs

> Fetch an instance's boot and runtime logs from your backend to debug a container that will not start or crashed after booting.

`GET /v1/instances/{id}/logs` returns a snapshot of the container's own output, everything the entrypoint and the agent printed to stdout and stderr, plus a compact health readout. It is how you debug an instance that crashed after booting, or your own [custom image](/agents-api/custom-image) that will not come up.

Unlike [exec](/agents-api/exec), which needs a `running` container, logs works in **any** state: `running`, `sleeping`, `stopped`, or `failed`. That is the point. When a container will not stay up, exec has nothing to attach to, but its logs are still there. The one gap is an instance that slept so long it was parked off its host: its logs read empty until a wake brings it back.

<Note>
  A container that never got created at all (a bad image reference, or an `exec format error` from a wrong-architecture image) has no logs to show: `logs` is empty and `health` is `null`. The reason for that kind of failure lands in `status_reason` on the instance object, so fetch `GET /v1/instances/{id}` and read it. Logs cover the case where a container **did** start and then misbehaved.
</Note>

## Request

<ParamField query="tail" type="integer" default="500">
  How many of the most recent log lines to return. Defaults to 500, capped at 2000 (a larger value is clamped down). A value that is not a positive integer returns `400 invalid_request`.
</ParamField>

## Response

<ResponseField name="logs" type="string">
  The container's combined stdout and stderr, most recent `tail` lines. Capped at 512 KB; see `truncated`. Empty when there is no container.
</ResponseField>

<ResponseField name="truncated" type="boolean">
  `true` when the output spilled past the 512 KB cap and the oldest lines were dropped.
</ResponseField>

<ResponseField name="health" type="object | null">
  A compact runtime readout, or `null` when there is no container. It answers "did it crash, and why."

  <Expandable title="health">
    <ResponseField name="running" type="boolean">
      Whether the container is currently up.
    </ResponseField>

    <ResponseField name="restart_count" type="integer">
      How many times the container has booted beyond its first start. Wakes from [auto-sleep](/agents-api/instances#auto-sleep) count too, so a rising number on a sleeper is normal; a count that climbs while the instance never sleeps is a crash loop.
    </ResponseField>

    <ResponseField name="exit_code" type="integer | null">
      The last exit code when the runtime still has one, `null` otherwise. Expect `null` in most cases: crash evidence lives in `logs`, `restart_count`, and `resource_verdict`.
    </ResponseField>

    <ResponseField name="oom_suspected" type="boolean">
      Best-effort inference that the container was killed for exceeding its memory limit. `resource_verdict.memory` at `"critical"` is the reliable version of the same signal. If either fires, [resize](/agents-api/instances#resize) to a larger shape.
    </ResponseField>

    <ResponseField name="resource_verdict" type="object | null">
      Per-dimension pressure (`memory`, `cpu`, `disk`, and `overall`, each `healthy`, `pressure`, or `critical`), or `null` when the container is not running. `memory` reads `"critical"` after the instance has been killed for exceeding its memory limit.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="fetched_at" type="integer">
  When the snapshot was taken, in epoch seconds.
</ResponseField>

Unknown, deleted, or other-workspace ids return `404 not_found`. If the platform cannot reach the instance's host, you get `502 provisioning_failed`.

## Example

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.agent37.com/v1/instances/ab12cd34ef/logs?tail=200" \
    -H "Authorization: Bearer sk_live_..."
  ```

  ```python python theme={null}
  import requests

  resp = requests.get(
      "https://api.agent37.com/v1/instances/ab12cd34ef/logs",
      headers={"Authorization": "Bearer sk_live_..."},
      params={"tail": 200},
  )
  result = resp.json()
  print(result["health"], result["logs"])
  ```

  ```javascript node theme={null}
  const resp = await fetch(
    "https://api.agent37.com/v1/instances/ab12cd34ef/logs?tail=200",
    { headers: { Authorization: "Bearer sk_live_..." } }
  );
  const result = await resp.json();
  console.log(result.health, result.logs);
  ```

  ```json response theme={null}
  {
    "logs": "[agent37-hermes] Booting (gateway_port=3737 ...)\n[agent37-hermes] Starting hermes gateway daemon...\n",
    "truncated": false,
    "health": {
      "running": true,
      "restart_count": 0,
      "exit_code": null,
      "oom_suspected": false,
      "resource_verdict": { "memory": "healthy", "cpu": "healthy", "disk": "healthy", "overall": "healthy" }
    },
    "fetched_at": 1781222420
  }
  ```
</CodeGroup>

## Debugging a failed instance

When an instance is `failed` or stuck, logs and `health` together tell you which layer broke:

* **The image will not start** (a climbing `restart_count`, with the same error at the top of `logs` on every boot): read the entrypoint's own error. This is the usual signal for a [custom image](/agents-api/custom-image) mistake, such as a missing binary, an entrypoint that exits, or a service that never listens on `default_port`.
* **It ran out of memory** (`resource_verdict.memory` is `"critical"`): the agent needs a bigger box. [Resize](/agents-api/instances#resize) to a larger shape.
* **It booted but the agent is wedged**: the logs show the last thing it did before it stopped responding. [Restart](/agents-api/instances#restart) to recover it.

Once you have a `running` container, drop into it with [exec](/agents-api/exec) to inspect further.
