Background processes

Last updated 3 November 2026

View .md

Machines are not open yet. These pages describe Machines as they will open; until then, a create answers 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).

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 lists each operation, marked Planned.

Start one

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), 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 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.

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.

Wait for it, extend it, stop it

# 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 keeps the Machine and its disks awake.