Overview
The process runtime spawns agents as direct child processes with piped stdio, offering:- Minimal overhead (no tmux server required)
- Full stdout/stderr capture in a rolling buffer
- Automatic cleanup when the orchestrator stops
- Process group management for proper child termination
Configuration
Configure the process runtime inagent-orchestrator.yaml:
Requirements
No external dependencies. The plugin uses Node.js built-inchild_process module.
Runtime API
create(config)
Spawns a new child process with the specified launch command.string
required
Session identifier (must match
[a-zA-Z0-9_-]+)string
required
Working directory for the process (
cwd)string
required
Shell command to execute (runs with
shell: true)Record<string, string>
Environment variables merged with
process.envThe plugin uses
shell: true intentionally, as launch commands may contain pipes, redirects, or other shell syntax. Ensure launch commands come from trusted sources (YAML config, not user input).sendMessage(handle, message)
Writes a message to the process’s stdin, followed by a newline.getOutput(handle, lines)
Returns the last N lines from the rolling output buffer.number
default:"50"
Number of lines to retrieve from the buffer (max 1000)
The plugin maintains a rolling buffer of the last 1000 lines. Older lines are automatically discarded to prevent unbounded memory growth.
destroy(handle)
Terminates the process gracefully (SIGTERM), then forcefully (SIGKILL) after 5 seconds.Process termination flow
Process termination flow
- Send SIGTERM to the entire process group (via negative PID)
- Wait up to 5 seconds for graceful exit
- Send SIGKILL to force termination if still running
- Remove session from internal map
isAlive(handle)
Checks if the process has exited (exitCode === null).
Usage Examples
Basic Agent Launch
Send Messages to Agent
Monitor Output
Graceful Shutdown
Advanced Features
Rolling Output Buffer
The plugin captures stdout and stderr into a single rolling buffer with:- Max capacity: 1000 lines
- Automatic trimming when limit exceeded
- Separate partial-line buffers for stdout/stderr to prevent interleaved corruption
Process Group Management
The plugin usesdetached: true to spawn the child in its own process group, then kills the entire group (negative PID) on destroy:
Exit Handling
The plugin attaches exit handlers immediately (before anyawait) to ensure fast-exiting processes don’t slip through:
Partial Line Buffering
Each stream (stdout, stderr) maintains its own partial-line buffer to handle split writes:Troubleshooting
Process exits immediately after spawn
Process exits immediately after spawn
Cause: Launch command failed or invalidSolution:
- Check
launchCommandsyntax (test in a shell first) - Verify required binaries are in PATH
- Check
workspacePathexists and is accessible - Inspect exit code in output buffer:
[process exited with code X]
sendMessage throws 'stdin not writable'
sendMessage throws 'stdin not writable'
Cause: Process has exited or stdin was closedSolution:
Duplicate session ID error
Duplicate session ID error
Cause: Trying to create two sessions with the same IDSolution: Each session must have a unique ID. Call
destroy() before re-creating:Child processes survive after destroy
Child processes survive after destroy
Cause: Process group kill failed (rare)Solution: Manually kill orphaned processes:
Output buffer missing early lines
Output buffer missing early lines
Cause: Buffer only stores last 1000 linesSolution:
- For full output capture, redirect to a file in your launch command:
- Increase
MAX_OUTPUT_LINESin plugin source if needed (requires rebuild)
Comparison with Tmux Runtime
Use process runtime for production and automated workflows. Use tmux for development when you need to attach and debug agents interactively.
Security Considerations
Safe usage:shell: true is intentional for the launchCommand field, which comes from trusted YAML config and may contain pipes or redirects. Never interpolate untrusted user input into launch commands.