Skip to content

Agent Runtime Specification

Scope

Owns reusable runtime primitives for long-running Robota work:

  • background task lifecycle, queueing, cancellation, events, and state snapshots
  • subagent job compatibility facade over the generic background task layer
  • subagent runner ports and worktree isolation runner decoration

This package is a composable material layer. It provides stateful runtime services and ports that higher packages assemble with providers, sessions, processes, transports, and UI.

Boundaries

  • Does not create providers, sessions, tools, prompts, child processes, Git worktrees, transports, or TUI state.
  • Does not read config files or project context.
  • Does not import agent-sdk, agent-sessions, agent-tools, provider packages, or agent-cli.
  • Concrete I/O belongs in adapters owned by runtime shells or dedicated adapter packages.
  • SDK assembly may re-export this package for compatibility, but this package remains the SSOT for runtime lifecycle contracts.
  • Layer position — below agent-sessions. agent-sessions may consume agent-runtime services; agent-runtime must never depend on agent-sessions. Dependency direction is strictly upward: agent-coreagent-runtimeagent-sessionsagent-sdk.
  • Contract stability. Public API shapes are stable runtime lifecycle contracts. Higher-layer packages (agent-sessions, agent-sdk) depend on these contracts. Breaking changes to the public API surface require coordinating all consumers before merging.

Architecture Overview

text
agent-runtime
  ├── background-tasks/
  │   ├── state-machine.ts                 -- pure lifecycle transitions
  │   ├── background-task-manager.ts       -- registry, queue, wait/cancel/close/send/read
  │   ├── log-pages.ts                     -- output capture and cursor-based log page helpers
  │   └── types.ts                         -- task requests, state, result, runner ports
  └── subagents/
      ├── types.ts                         -- subagent job contracts and runner port
      ├── subagent-manager.ts              -- compatibility facade over BackgroundTaskManager
      └── worktree-subagent-runner.ts      -- runner decorator using injected worktree adapter

Design rules:

  • lifecycle transitions are pure and table-driven
  • managers own registries and concurrency, not execution I/O
  • runners execute one job and report through handles/events
  • decorators add behavior by wrapping runner ports
  • concrete side effects are injected behind ports

Type Ownership

TypeLocationPurpose
IBackgroundTaskManagersrc/background-tasks/types.tsGeneric background task registry API
IBackgroundTaskRunnersrc/background-tasks/types.tsPort for executing one task kind
IBackgroundTaskStatesrc/background-tasks/types.tsImmutable task state snapshot shape
IBackgroundTaskRequestsrc/background-tasks/types.tsAgent/process task request union
IBackgroundTaskResultsrc/background-tasks/types.tsCompleted task output and metadata
TBackgroundTaskEventsrc/background-tasks/types.tsLifecycle/progress event union
TBackgroundTaskTimeoutReasonsrc/background-tasks/types.tsWatchdog terminal reason union
ILimitedOutputCapturesrc/background-tasks/log-pages.tsUTF-8-safe bounded output capture used by process-like adapters
ISerializableProviderProfilesrc/background-tasks/types.tsProvider profile handoff for background workers, including credential references and provider-owned options
ISubagentManagersrc/subagents/types.tsSubagent job compatibility facade
ISubagentRunnersrc/subagents/types.tsPort for executing one subagent job
ISubagentSpawnRequestsrc/subagents/types.tsSubagent spawn request
ISubagentJobStatesrc/subagents/types.tsSubagent job state projection
ISubagentJobResultsrc/subagents/types.tsSubagent completion output and metadata
ISubagentWorktreeAdaptersrc/subagents/worktree-subagent-runner.tsPort for concrete worktree I/O
IPreparedSubagentWorktreesrc/subagents/worktree-subagent-runner.tsPrepared worktree handoff data

Hook event types and hook execution are owned by agent-core.

Public API Surface

Background Tasks

ExportKindDescription
BackgroundTaskManagerclassIn-memory task registry and scheduler
BackgroundTaskErrorclassTyped runtime error with category and recoverability
transitionBackgroundTaskStatusfunctionPure state transition function
isTerminalBackgroundTaskStatusfunctionTerminal-state predicate
getBackgroundTaskTransitionsfunctionTransition table snapshot for tests/audits
createLimitedOutputCapturefunctionUTF-8-safe bounded output capture helper
appendPrefixedLogLinesfunctionAppend source-prefixed non-empty log lines
createBackgroundTaskLogPagefunctionCursor-based log pagination helper

Background Task Runners (Concrete — default implementations)

The following are concrete IBackgroundTaskRunner implementations provided by this package. They depend on Node.js child_process. CLI and SDK shells use them as default runners; test environments may substitute no-op runners through the IBackgroundTaskRunner port.

ExportKindDescription
createManagedShellProcessRunnerfunctionSpawns a shell command via node:child_process.spawn; streams stdout/stderr as logs
createScheduledTaskRunnerfunctionSchedules cron-pattern tasks via croner; triggers a child runner on each firing

croner production dependency: croner@^10.0.1 is used by createScheduledTaskRunner to parse cron expressions and fire scheduled background tasks. It has no Node.js native bindings and is safe for any Node.js runtime target.

Subagents

ExportKindDescription
SubagentManagerclassSubagent facade over BackgroundTaskManager
WorktreeSubagentRunnerclassDecorates an ISubagentRunner with worktree isolation behavior
createWorktreeSubagentRunnerfunctionFactory for WorktreeSubagentRunner
GitWorktreeIsolationAdapterclassConcrete ISubagentWorktreeAdapter using execFileSync + Git CLI
createGitWorktreeIsolationAdapterfunctionFactory for GitWorktreeIsolationAdapter

Note on GitWorktreeIsolationAdapter: This is a concrete CLI adapter (calls execFileSync, performs Git operations) that lives in agent-runtime for historical reasons. CLI-AUDIT-006 classified it as a CLI adapter; it should eventually move to agent-cli/src/subagents/ when ARCH-FIX-024 is executed.

The package entrypoint exports these symbols explicitly from src/index.ts. SDK compatibility barrels may re-export the same symbols, but they must not redefine the contracts.

Extension Points

Consumers extend the runtime by implementing ports:

PortImplemented byContract
IBackgroundTaskRunnerSDK, CLI, test, or transport-adapter packagesExecutes one task kind and returns a cancellable handle
ISubagentRunnerSDK in-process runner or CLI child-process runnerExecutes one subagent job and reports structured progress
ISubagentWorktreeAdapterCLI or a future Node adapter packageCreates, inspects, and removes concrete worktrees
TBackgroundTaskEventListenerSDK, transports, CLI state managerReceives task lifecycle/progress events without mutating runtime state

Runtime ports own required shapes. Adapter packages own concrete I/O and must not add global task registries outside BackgroundTaskManager.

Runner handles may expose logPath and transcriptPath for append-only diagnostic streams. BackgroundTaskManager projects those paths into task state immediately after runner start and preserves matching result metadata on completion.

Task requests may include generic primitive metadata. The runtime treats this as opaque provenance/control-plane data: it clones metadata into IBackgroundTaskState, preserves it in state snapshots, and never interprets SDK-, command-, skill-, transport-, or UI-specific keys. Higher layers may use metadata for origin projection, grouping, or workspace read models, but lifecycle transitions, queueing, cancellation, and runner behavior must not depend on those keys.

Transparent Workflow Relationship

The cross-cutting transparent workflow contract is defined in ../../../.agents/specs/transparent-workflow.md. agent-runtime owns the mechanical background task lifecycle state machine and transition validation for agent/process work. It does not own command authorization provenance, user-local preference semantics, memory inspection, or TUI disclosure policy.

Current runtime statuses are queued, running, waiting_permission, completed, failed, and cancelled. The transparent workflow user-facing vocabulary displays waiting_permission as waiting-for-input; a future API change may alias or rename this status only with compatibility tests. archived is a visibility/retention projection over terminal records, not a state that restarts execution. Runtime close() remains the mechanical terminal-record dismissal operation.

User-Local Storage Relationship

Baseline workflow storage policy is defined in ../../../.agents/specs/user-local-storage.md. agent-runtime does not resolve storage roots, validate repository boundaries, or persist baseline workflow state. It may expose session-local task ids, metadata, events, and state snapshots; SDK storage contracts decide whether and how higher layers persist those associations.

User-Local Memory Relationship

Inspectable user-local memory behavior is specified in ../../../.agents/specs/user-local-memory.md. agent-runtime may expose task ids, group ids, lifecycle state, and metadata that SDK projections use for user-local associations. Runtime must not read or write user-local memory, project memory, or command-history preferences, and remembered values must not influence runtime command execution.

Process Execution Relationship

Transparent process execution is specified in ../../../.agents/specs/process-execution.md. agent-runtime owns generic process task lifecycle, stdout/stderr log paging contracts, timeout, cancellation, send/read controls, exit code, signal code, and state transitions. Runtime does not own command selection, command meaning, environment-summary presentation, action provenance, or correctness interpretation.

Background Work State Relationship

Switchable background work state is specified in ../../../.agents/specs/background-work-state.md. agent-runtime owns mechanical task lifecycle, events, cancellation, wait, send, close, and log read operations. It does not own selected workspace entry state, filled/empty UI indicators, presentation grouping, archive visibility, or TUI detail rendering.

Runtime may expose retention metadata only as task lifecycle or registry state protected by state-machine tests. archived remains a visibility/retention projection over terminal records, not a status that restarts or resumes execution.

Error Taxonomy

BackgroundTaskError is the package error class for lifecycle and runner failures.

CategoryRecoverableTypical source
validationyesInvalid depth, unknown runner kind, invalid state transition
capacityyesFuture queue/capacity enforcement
permissionyesFuture permission flow denial or timeout
timeoutyesIdle, max runtime, output limit, repetition, or stale worker watchdog
runneryesRunner start, cancellation, unsupported send/log operations
crashnoFuture process crash projection from adapters
provideryesProvider failure projected by a runner
processyesShell/process task failure projected by a runner

Adapters may map external failures into BackgroundTaskError categories, but they must not expose vendor-specific error objects through public runtime state.

Event Architecture

BackgroundTaskManager emits TBackgroundTaskEvent through:

  • an optional constructor eventSink
  • zero or more subscribe(listener) registrations

Events contain cloned task snapshots or primitive progress data. Consumers may project these events into TUI rows, transport messages, or logs, but event listeners must not mutate manager state directly.

Watchdog and Shutdown Contract

BackgroundTaskManager owns provider-neutral watchdog semantics for long-running agent tasks:

  • idleTimeoutMs means no new runner progress event has arrived within the configured window. Text deltas, tool start/end events, and permission requests all refresh lastActivityAt.
  • maxRuntimeMs is a separate wall-clock cap. The default is 0, so background agents do not have a default wall-clock cap; consumers may opt in per request or manager configuration. Legacy agent timeoutMs maps to idleTimeoutMs; process timeoutMs remains the runner-owned wall-clock process timeout.
  • Agent requests may set outputLimitBytes, maxTextDeltas, repetitionWindow, and repetitionThreshold to stop runaway streams.
  • Watchdog failures set IBackgroundTaskState.timeoutReason to idle, max_runtime, output_limit, repetition, or stale_worker, cancel the runner handle when possible, and fail the task with BackgroundTaskError category timeout.
  • Terminal task records, logs, and transcript paths remain in the registry until close() is called.

IBackgroundTaskManager.shutdown(reason?) is the runtime-owned graceful shutdown API. It is idempotent, rejects new spawns after shutdown starts, cancels all queued/running tasks through their handles, emits terminal events before resolving when possible, and never deletes terminal records.

Worktree Runner Contract

WorktreeSubagentRunner depends on:

  • an inner ISubagentRunner
  • an ISubagentWorktreeAdapter
  • optional hooks and hook executors

For non-worktree requests it delegates unchanged. For isolation: 'worktree' it must:

  • prepare a worktree through the adapter
  • pass cwd, worktreePath, and branchName to the inner runner
  • fire WorktreeCreate after preparation
  • remove clean worktrees exactly once on success, async failure, sync start failure, or successful cancellation
  • preserve dirty worktrees and return worktreePath, branchName, worktreeStatus, and worktreeNextAction metadata
  • propagate adapter-provided baseRevision and parentStatus as handoff metadata when available
  • preserve existing result metadata
  • fire WorktreeRemove when a clean worktree is removed

Package Integration

  • agent-sdk imports this package and composes it with config/context/session assembly.
  • agent-cli injects concrete adapters such as child-process runners and Git worktree adapters through SDK/runtime ports.
  • Transport packages consume task events and controls but do not own task transitions.

Test Strategy

Unit tests cover:

  • background state-machine transitions
  • background task manager lifecycle, queueing, cancellation, progress, metadata projection, watchdogs, and shutdown
  • bounded output capture and cursor-based log pagination helpers
  • subagent manager lifecycle facade behavior
  • worktree runner clean/dirty/failure/delegation/hook behavior with fake adapters

Adapter packages or shells must add integration tests for concrete side effects such as local Git or child processes.

Class Contract Registry

ClassImplementsDepends on
BackgroundTaskManagerIBackgroundTaskManagerIBackgroundTaskRunner, TBackgroundTaskEventListener, pure transition helpers
SubagentManagerISubagentManagerIBackgroundTaskManager, IBackgroundTaskRunner, ISubagentRunner
WorktreeSubagentRunnerISubagentRunnerinner ISubagentRunner, ISubagentWorktreeAdapter, agent-core hook runner

Pure helper contracts:

  • createLimitedOutputCapture() owns bounded output truncation semantics for adapters that need a provider-neutral output string.
  • appendPrefixedLogLines() owns source-prefixed log line projection.
  • createBackgroundTaskLogPage() owns cursor pagination for append-only task logs.

Cross-package port consumers:

  • agent-sdk consumes SubagentManager, IBackgroundTaskRunner, ISubagentRunner, and TBackgroundTaskEvent.
  • agent-cli consumes runtime contracts through SDK re-exports and implements concrete child-process/Git adapters.
  • Transport packages consume task events and control APIs through SDK InteractiveSession.

Dependencies

Production dependencies:

PackageReason
@robota-sdk/agent-coreHook types and hook runner used by WorktreeSubagentRunner

This package must not depend on SDK, sessions, tool, provider, transport, or CLI packages.

Released under the MIT License.