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

# Run subprocesses and send input

> Start an additional process inside an active operation, exchange input, observe output, and end it deliberately.

Use an additional subprocess when two processes need the same live environment. For example, a primary process can wait for a result file while a child receives input and writes that file. Both processes share the operation's filesystem and resource limits.

Use the REST subprocess endpoints for this workflow. Starting a new operation creates a separate runtime; the Python SDK's `popen()` wrapper also starts its own operation.

Complete [access setup](/sandboxes/start/set-up-access) before using the REST endpoints. The complete [interactive-process recipe](/sandboxes/cookbook/interact-with-a-process) uses one bounded standard-library Python program.

## Keep the parent alive until the work is done

The primary process controls the operation lifetime. When it finishes, finalization begins and additional subprocesses cannot continue independently. Design the parent with a bounded coordination condition, such as waiting for a completion file until a deadline. A subprocess finishing does not finalize the parent or create its own result image.

Before spawning a child, confirm that the parent has reached `ASSIGNED` or `EXECUTING` and has published an application readiness signal. Status alone says that the runtime is active; it does not prove that a service or file inside the runtime is ready. A short `GET /operations/{operationId}?inflight=1` poll can inspect partial parent output when a dedicated readiness endpoint is unavailable.

```mermaid theme={null}
%%{init: { "sequence": { "diagramMarginX": 10, "actorMargin": 25, "width": 100, "height": 40, "mirrorActors": false, "wrap": true } } }%%
sequenceDiagram
  participant Client
  participant Parent
  participant Child
  Parent-->>Client: Readiness observed
  Client->>Child: Spawn child
  Client->>Child: First input
  Client->>Child: Last input + EOF
  Child-->>Parent: Completion file
  Child-->>Client: Child result
  Parent-->>Client: Parent ends<br/>Finalize operation
```

Client arrows represent REST requests, not direct connections to guest processes. This is the normal path in the [interactive recipe](/sandboxes/cookbook/interact-with-a-process). The file coordinates the two processes. If the primary process ends first, finalization stops any remaining child; the client cannot keep it alive by continuing to poll.

## Spawn and address the child

Send an `ExecSpec` to `POST /operations/{operationId}/subprocesses`. VM-level fields such as `image`, `disposable`, `timeout`, and `resources_limits` belong to the parent operation and are not accepted in the child request.

A successful response returns a fresh `spid` of 2 or greater and a `Location` for its result. Preserve both the parent operation UUID and the child `spid`. If the create request times out, inspect the event stream for a matching `spawn` event before retrying because the child may already exist.

See [Spawn an additional subprocess](/api-reference/sandboxes/operation/spawn-an-additional-subprocess-inside-a-running-instance).

## Send ordered input and EOF

Set the child's initial `stdin.close` to `false` when later writes are required. Send each chunk to `POST /operations/{operationId}/subprocesses/{spid}/stdin`. Serialize writes to the same child when order matters; concurrent writes have unspecified order. The API does not append a newline.

Use `encoding: "ascii"` for text and `encoding: "base64"` for arbitrary bytes. Send `close: true` on the final write, or send an empty close-only request, to deliver EOF. A `204` confirms the request completed. A `504` leaves delivery uncertain, so a blind retry can duplicate input. Add sequence numbers or another application-level idempotency marker when duplicate input would be harmful.

See [Write to subprocess stdin](/api-reference/sandboxes/operation/write-to-a-subprocesss-stdin-andor-close-it).

## Observe completion or signal the process

Read `GET /operations/{operationId}/subprocesses/{spid}` until the child result is ready. Honor `Retry-After` for a `425` response and keep polling bounded. Check the child's exit code, signal, timeout flag, stdout, stderr, encoding, and truncation separately from the parent result.

To stop a live child, call `DELETE /operations/{operationId}/subprocesses/{spid}?signal=SIGTERM` or choose another documented signal. The signal targets the subprocess's process group. Completion is observed later in the child result: a signalled child reports `exit_code: -1` and the signal number. Signalling `spid=1` ends the primary workload and therefore ends the operation.

See [Signal a subprocess](/api-reference/sandboxes/operation/kill-one-subprocess).

## Handle lifetime races

| Race | Required behavior |
| - | - |
| Child exits first | Inspect its result, then let the primary workload reach its own terminal condition. |
| Parent exits first | Stop child requests. Finalization terminates remaining children; inspect both terminal results rather than retrying against the finished runtime. |
| Client fails while parent remains active | Cancel the parent if the workflow owns it and cannot safely resume. Poll until the parent is terminal. |
| Stdin write returns `504` | Treat delivery as unknown and reconcile at the application protocol level. |

The [interactive-process recipe](/sandboxes/cookbook/interact-with-a-process) covers normal two-write input with EOF, a child terminated by `SIGTERM` while the parent completes normally, and a negative case where the parent finishes first. Its `finally` block cancels any parent operation left active after a client-side failure.
