Skip to main content
A process is a stateful execution unit in cyrnel. When a client submits code, cyrnel creates a process record with a stable identifier (id), runs it on the active environment module, captures its output, and persists the result to the database. Process execution does not block the client request; the API responds immediately and the process runs asynchronously.

Process Model

Each process has the following fields:
  • id: stable database identifier (auto-incrementing integer, persists across restarts)
  • pid: ephemeral in-memory process identifier, or null when the process is not in active memory (see Unload a Process)
  • ref: optional reference label (trimmed; must be non-empty if present, unique)
  • state: lifecycle phase (see below)
  • exitState: execution outcome (see below)
  • error: error message if the process failed, otherwise null
  • code: the submitted source
  • timeoutMs: per-process timeout in milliseconds. null = no enforcement, undefined = 30s default
  • envConfig: opaque configuration passed through to the environment module
  • output: structured key/value payload emitted by cyrnel.output(...)
  • stdout, stderr: captured text output
  • createdAt: ISO-8601 timestamp of creation
  • completedAt: ISO-8601 timestamp of completion, or null if still running
Process creation records and execution results are persisted in the database. Runtime state (running/queued/terminating) is ephemeral and held in memory, restarting the API clears active executions but the creation record and any completed results survive.

Process states

Process exit states

Create a Process

POST /processes
Rules:
  • code is required and must be a string.
  • ref is optional, trimmed, unique if provided, and must be non-empty if present.
  • timeoutMs is in milliseconds. Must be a positive integer, or null to disable enforcement, or undefined to use the default (30s). This is a hard enforcement ceiling, execution is terminated when the wall clock exceeds this value.
  • envConfig is optional, opaque configuration passed through to the environment module. Its shape is environment-dependent and validated by the module itself.
  • autorun controls whether execution starts immediately. When true (default), the process is queued and runs right away. When false, the process is created in idle state and must be started via the run signal.
Response (201):

Run an Existing Process

POST /processes/:id/signals/run
  • The process must currently be idle.
  • If the process has stored outputs (any of exitState, output, stdout, stderr is non-empty), force: true is required to overwrite them.
The run signal also works on historical processes that only exist in the database (for example after an API restart, or after an unload). The process is revived into active memory under the same id with a fresh pid and executes again. If the historical record has stored outputs, force: true is required; re-running overwrites the stored outputs. Response (200): the process record.

Kill a Process

POST /processes/:id/signals/kill
  • If the process is queued, it transitions straight to idle with exitState = "canceled".
  • If running, it moves to terminating first, then to idle with exitState = "canceled" once the environment confirms.
  • If already idle: including historical processes that only exist in the database - the call returns 409.
Response (200): the process record.

Unload a Process

POST /processes/:id/signals/unload Removes an idle process from active memory while keeping its database record and outputs intact. The process id remains valid, and a subsequent run signal revives it under the same id with a fresh pid. This is useful for releasing memory while preserving history. Rules:
  • The process must be idle. Queued, running, and terminating processes return 409 (unloading would orphan the execution).
  • If the process is already outside active memory, the call returns 409.
  • Unknown ids return 404.
After unloading, the process reports pid: null and state: "idle" and is listed among historical database processes. Unloading is not destructive: the code, outputs, stdout, and stderr remain available. Response (200): the process record.

Automatic unloading

When CYRNEL_MAX_IDLE_PROCESSES is set, idle processes are unloaded automatically (least recently executed first) once the in-memory idle pool exceeds the cap. The behavior is identical to an explicit unload - the database record and outputs are preserved, and the process can be revived with a run signal. The cap is checked whenever a process becomes idle or is created without autorun; queued and running processes are never unloaded. The cap is unlimited when the variable is unset.

Inspect a Process

/output, /stdout, and /stderr return 409 unless the process is idle.

Filtering /processes

Query parameters:
  • state: One of idle | queued | running | terminating
  • status: One of success | failed | timeout | canceled | null
  • ref: Exact match (trimmed, non-empty)
Results include both active in-memory processes and historical processes from the database, ordered newest-first by creation time.

Pagination

GET /processes returns the paginated envelope { items, nextCursor, hasMore }; see Pagination for the cursor rules, limit semantics, and error codes.

Delete a Process

DELETE /processes/:id The process must be idle. The record is permanently removed from the database (including code, outputs, stdout, and stderr). Historical processes that only exist in the database can be deleted directly; they are always idle. The response is 200 with the deleted process record in the body.
Last modified on August 25, 2026