> Fetch the index of every Tonbo docs page as Markdown at https://tonbo.dev/llms.txt

# Background processes

Last updated 3 November 2026

> Machines are not open yet. These pages describe Machines as they will open; until then, a create answers [`region_not_offered`](https://tonbo.dev/docs/machines/troubleshooting/manage.md#region_not_offered) (422), “Machines are not offered in any region yet.”

Start a command that keeps running after your call returns, then read its output, wait for it, give it more time or stop it, from any client with a key of your account. Use it for builds, test suites and agent tasks that outlast one connection; a short command is simpler as one call (see [Run commands](https://tonbo.dev/docs/machines/exec.md)).

> Planned Not served yet. This page describes how it will work, as decided; until it is served, every request below answers 404 at `https://api.us-east-1.tonbo.sh/v1`. The [Machines API reference](https://tonbo.dev/docs/reference/management/machines.md) lists each operation, marked Planned.

## Start one

```shell
curl -sS https://api.us-east-1.tonbo.sh/v1/machines/hello/processes \
  -H "Authorization: Bearer $TONBO_API_KEY" \
  -H "Idempotency-Key: build-42-attempt-1" \
  -H "Content-Type: application/json" \
  -d '{"command": ["make", "test"], "timeout_seconds": 7200, "label": "build-42"}'
```

It answers 201 with the process’s record, whose `process` is its id, once it has started exactly once, waking the Machine first if it is asleep. The body takes the same `command`, `cwd`, `env`, `stdin` and `user` as a command (see [How the command runs](https://tonbo.dev/docs/machines/exec.md#how)), a `label` to find it by, and its deadline.

Send the same request with the same `Idempotency-Key` again and it answers 200 with the same record, running or ended, and starts nothing: an agent that crashed finds its job that way.

## How long it runs

- Until it exits, its deadline, a kill, or the Machine’s sleep or stop. Nothing about the caller ends it.
- `timeout_seconds` is 1 hour by default and at most 6 hours, counted from its start. Tonbo keeps the deadline outside the Machine, so no setting inside it, a `ulimit` included, moves it.
- While it runs it keeps the Machine awake, and its deadline bounds what that costs.
- No process survives a sleep, and none is started again at the next wake. Work longer than 6 hours writes its progress to the Volume or the [database](https://tonbo.dev/docs/machines/database.md) and starts again from there in a new process.
- It starts with the program’s resource limits, 1,048,576 open files among them, and may lower its own or, as `root`, raise them.

## Read its output

Its stdout and stderr go to a buffer of its last 16 MiB, one sequence of byte offsets for both. A full buffer drops the oldest bytes; output never ends the process.

```shell
curl -sSN "https://api.us-east-1.tonbo.sh/v1/machines/hello/processes/<process>/output?offset=0&follow=true" \
  -H "Authorization: Bearer $TONBO_API_KEY"
```

The answer is one JSON object per line: `stdout` and `stderr` lines with their `offset` and base64 `data`, a `gap` for bytes the buffer dropped, a `tick` every 30 seconds of silence, and an `end` line once the process has ended and every kept byte was sent. Without `follow` it stops at an `eof` line with the `next_offset` to read from next. Several readers may follow at once. The buffer is gone when the Machine sleeps (410 `output_gone`), and it never reaches the Machine’s [logs](https://tonbo.dev/docs/machines/logs.md).

## Wait for it, extend it, stop it

```shell
# Wait up to 50 seconds for it to end, then read its record
curl -sS "https://api.us-east-1.tonbo.sh/v1/machines/hello/processes/<process>?wait_seconds=50" \
  -H "Authorization: Bearer $TONBO_API_KEY"

# Give it 4 hours from its start
curl -sS -X PUT https://api.us-east-1.tonbo.sh/v1/machines/hello/processes/<process>/deadline \
  -H "Authorization: Bearer $TONBO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"timeout_seconds": 14400}'

# Send it a signal; it does not end it by itself
curl -sS https://api.us-east-1.tonbo.sh/v1/machines/hello/processes/<process>/signal \
  -H "Authorization: Bearer $TONBO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"signal": "INT"}'

# Kill it: SIGTERM, the grace, then a kill of whatever is left
curl -sS -X DELETE "https://api.us-east-1.tonbo.sh/v1/machines/hello/processes/<process>?grace_seconds=10" \
  -H "Authorization: Bearer $TONBO_API_KEY"

# List the running ones
curl -sS "https://api.us-east-1.tonbo.sh/v1/machines/hello/processes?state=running" \
  -H "Authorization: Bearer $TONBO_API_KEY"
```

- A kill’s grace is 5 seconds by default and at most 60. It works on a running command too, which is how another client stops a stuck one.
- None of these wakes the Machine or keeps it awake: a running process already does. Signals are named (`HUP`, `INT`, `TERM`, `KILL` and a few more), never numbers.
- Records are kept 24 hours after a process ends, across sleeps, at most 10,000 a Machine.

## How it ended

An ended record’s `end.reason` says why: `exited` with its `exit_code`, `signaled` with its `signal`, `timeout`, `killed`, or `activation_ended` when the Machine slept or stopped, with the `stop_reason`. All of these are known outcomes. Only `lost` means Tonbo does not know how it ended; read what it wrote to the Volume or the database before you run it again.

Between processes, while your agent thinks, a [hold](https://tonbo.dev/docs/machines/holds.md) keeps the Machine and its disks awake.
