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

# Run commands

> Run any shell command inside an instance from your backend, the escape hatch for anything the API does not wrap.

`POST /v1/instances/{id}/exec` runs a shell command inside the instance, straight from your backend. It is the escape hatch for anything the API does not wrap as its own call.

The command runs through `sh -c` as the image's default user, on the same box the agent works on, so it sees the agent's files, tools, and credentials.

## Request

<ParamField body="command" type="string" required>
  The shell command to run inside the instance. It is passed to `sh -c`, so pipes, redirects, and `&&` chains all work. It must not contain a null byte, which no shell can carry: one returns `400 invalid_request`.
</ParamField>

<Note>
  A `running` instance runs the command right away. A `sleeping` instance is woken first, the same way a request to one of its URLs or an explicit [start](/docs/agents-api/instances#start) wakes it, so the first call after a sleep takes about 10 seconds longer in the common case, and a couple of minutes when the wake has to rebuild the instance (it then boots fresh: files on disk are kept, processes and in-memory state are not). The wake can fail the way a start can: `409 try_again` means a sleep checkpoint was being written (tens of seconds on a large instance, retry with backoff), `502 provisioning_failed` means the wake failed, `409 capacity_unavailable` means a rebuild found no host with room, and `402 insufficient_balance` means the instance is suspended for non-payment. Exec does not wait for a wake another request started: an instance that is already `waking` returns `400 invalid_request`, as does any other status that is not `running` or `sleeping` (a deleted instance returns `404 not_found`). If the platform cannot reach the instance at all, you get `502 provisioning_failed`. Every exec counts as [activity](/docs/agents-api/instances#auto-sleep), so an instance you drive only through exec stays up while commands keep coming.
</Note>

## Response

A command that runs but exits nonzero is a normal result: you get `200` with its `exit_code`, `stdout`, and `stderr`. Errors are reserved for the platform, not your command.

<ResponseField name="exit_code" type="integer">
  The command's exit code. Nonzero is still a `200`; read this to branch.
</ResponseField>

<ResponseField name="stdout" type="string">
  Standard output, capped at 512 KB. See `truncated`.
</ResponseField>

<ResponseField name="stderr" type="string">
  Standard error, with its own separate 512 KB cap.
</ResponseField>

<ResponseField name="truncated" type="boolean">
  `true` when either stream spilled past its 512 KB cap. The middle of the output is cut and a truncation marker is left in its place.
</ResponseField>

<Note>
  `exit_code` values 125, 126, and 127 may come from the container runtime rather than your command, for example 127 when the binary is not found. The call waits up to 13 minutes (780 seconds) for the command, a wake from sleep included, then fails with `502 provisioning_failed`. The command itself is not stopped by that: it keeps running inside the instance, so a blind retry starts a second copy. For longer jobs, start the command in the background with its output sent to a file, `nohup ./job.sh > job.log 2>&1 &`, and poll with a second exec. The redirect is required: a background command that still writes to the call's own output holds the call open until it exits.
</Note>

## Example

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/exec \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{ "command": "node --version" }'
  ```

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

  resp = requests.post(
      "https://api.agent37.com/v1/instances/ab12cd34ef/exec",
      headers={"Authorization": "Bearer sk_live_..."},
      json={"command": "node --version"},
  )
  result = resp.json()
  print(result["exit_code"], result["stdout"])
  ```

  ```javascript node theme={null}
  const resp = await fetch(
    "https://api.agent37.com/v1/instances/ab12cd34ef/exec",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer sk_live_...",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ command: "node --version" }),
    }
  );
  const result = await resp.json();
  console.log(result.exit_code, result.stdout);
  ```

  ```json response theme={null}
  {
    "exit_code": 0,
    "stdout": "v24.2.0\n",
    "stderr": "",
    "truncated": false
  }
  ```
</CodeGroup>

## Build on exec

Anything the API does not wrap as its own endpoint, you build on `exec`. For moving files, prefer the instance's own [files endpoints](/docs/agents-api/files) at `https://{instanceId}.agent37.app` (`PUT /v1/files/content` to upload, `GET /v1/files/content` to download), but a quick text read works over exec too. A "Download the report" button in your product can be one exec call that reads the file the agent wrote:

```bash curl theme={null}
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/exec \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "command": "cat ~/reports/ev-makers-memo.md" }'
```

Pushing a file in is the same trick in reverse. Encode it on your side and decode it inside the instance:

```bash curl theme={null}
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/exec \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "command": "mkdir -p ~/data && echo aGVsbG8sd29ybGQK | base64 -d > ~/data/ev-prices.csv" }'
```

For binary or large files, use the [files endpoints](/docs/agents-api/files) on the instance URL instead, where `GET /v1/files/content` streams a download of any size with no 512 KB cap, or stage them at a URL your backend controls and `curl` them down from inside the instance.
