src/effect/ and are imported from smithers-orchestrator/effect/*. They assume familiarity with the Effect library.
Runners
Three functions run Effect programs inside the shared Smithers managed runtime. The runtime is initialized once, annotates all logs with"service": "smithers", and normalizes failures to SmithersError.
EFFECT_RUN_PROMISE
Runs an Effect and returns aPromise. The promise rejects with a SmithersError on failure.
EFFECT_RUN_SYNC
Runs a synchronous Effect immediately. ThrowsSmithersError on failure. Use this only when you are certain the Effect performs no async work.
EFFECT_RUN_FORK
Forks an Effect as a background fiber. Returns the fiber immediately without awaiting the result. Suitable for fire-and-forget side effects like metric updates.EFFECT_SINGLE_RUNNER
TheEFFECT_SINGLE_RUNNER pattern provides a singleton @effect/cluster SingleRunner backed by an in-memory SQLite database. It manages the task worker entity lifecycle, serializes dispatches by bridge key, and survives multiple concurrent callers sharing the same runtime.
The singleton is initialized lazily on first dispatch and reused for the lifetime of the process.
EFFECT_TASK_RUNTIME
Task-scoped context propagated viaAsyncLocalStorage. Tools and compute callbacks read this to find the current runId, stepId, heartbeat handle, and abort signal without threading the values through call stacks.
requireTaskRuntime throws SmithersError("TASK_RUNTIME_UNAVAILABLE") when called outside a task execution scope.
Bridges
Bridges connect the Smithers engine to Effect programs. The engine dispatches execution to a bridge; the bridge translates that into the correct Effect constructs and reports results back.EFFECT_ACTIVITY_BRIDGE
The activity bridge wraps legacy task execution in an@effect/workflow Activity with idempotency and retry semantics. Each task maps to a SmithersTaskBridge workflow instance keyed by adapter namespace, workflow name, run ID, node ID, and iteration.
RetriableTaskFailure is a sentinel error class. Throw it from an activity to trigger a retry within the bridge’s retry loop.
EFFECT_WORKFLOW_BRIDGE
The workflow bridge is the top-level seam that routes a task to the appropriate execution path:compute, static, or legacy. It manages inflight and completed execution maps to prevent duplicate dispatches across concurrent engine invocations.
| Classification | Condition |
|---|---|
"compute" | desc.computeFn set, no agent, no cache, no worktree, no scorers |
"static" | desc.staticPayload set, no agent, no cache, no worktree, no scorers |
"legacy" | Everything else — forwarded to legacyExecuteTaskFn |
EFFECT_WORKFLOW_MAKE_BRIDGE
Wraps an entire workflow body execution in an@effect/workflow Workflow using AsyncLocalStorage to thread the bridge runtime through the call stack. Used for child workflow execution and continue-as-new semantics.
Scope and engine context.
EFFECT_COMPUTE_TASK_BRIDGE
Executes acomputeFn task directly within the bridge — no agent involved. Manages the full attempt lifecycle: DB insert, node state transitions, heartbeat flushing, timeout enforcement, and event emission. Integrates with the heartbeat watchdog when desc.heartbeatTimeoutMs is set.
EFFECT_STATIC_TASK_BRIDGE
Executes astaticPayload task without invoking any agent or compute function. The payload is validated against the output schema and persisted immediately.
EFFECT_DEFERRED_BRIDGE
Lightweight in-memory deferred resolution map. StoresExit values keyed by (runId, nodeId, iteration) and reads them back during replay or resume. Used for simple approval and timer synchronization that does not need durable persistence.
EFFECT_DURABLE_DEFERRED_BRIDGE
Durable version of the deferred bridge built on@effect/workflow DurableDeferred. Approval and WaitForEvent nodes use this so that the resolution is durable across restarts.
Each deferral is keyed by an execution ID derived from the adapter namespace, run ID, node ID, and iteration.
EFFECT_DEFERRED_STATE_BRIDGE
Manages the state machine for timer, approval, andWaitForEvent nodes. Reads attempt metadata from the database, determines whether a deferred task is still pending or has already been resolved, and drives the appropriate resolution path.
Key exports:
resolveDeferredTaskStateBridge function drives the resolution loop. It reads the current attempt snapshot, handles timer expiry, matches incoming signals, and emits the appropriate SmithersEvent when the node settles.
EFFECT_CHILD_WORKFLOW_EXECUTION
Child workflow execution is provided by theWorkflowMakeBridgeRuntime context, accessible from within an active workflow body via getWorkflowMakeBridgeRuntime().
Scope. Its continue-as-new loop runs independently but shares the parent engine scope’s lifecycle.
EFFECT_WORKER_ENTITY_DISPATCH
Task dispatches pass through an@effect/cluster Entity (the TaskWorkerEntity). The entity is defined using @effect/rpc and sharded via the SingleRunner. Each invocation is addressed by its bridgeKey — a composite of adapter namespace, workflow name, run ID, node ID, and iteration.
EFFECT_SANDBOX_ENTITY_TRANSPORT
Sandbox execution (Bubblewrap, Docker, Codeplane) is routed through an Entity transport. TheSandboxEntity and SandboxEntityExecutor bridge the SandboxTransportService interface into the cluster entity model.
Infrastructure
EFFECT_CHILD_PROCESS
Wraps Node.jschild_process.spawn in an Effect with full lifecycle management: output capture, truncation, idle timeout, total timeout, AbortSignal forwarding, and detached process group cleanup.
maxOutputBytes is truncated and a smithers.tool.output_truncated_total metric is incremented. The process group is killed with SIGKILL on abort or timeout.
EFFECT_INTEROP
Utilities for wrapping non-Effect code so it fits cleanly into Effect pipelines.SmithersError. Pass code to set a specific SmithersErrorCode; without it the code defaults to "INTERNAL_ERROR".
EFFECT_SQL_MESSAGE_STORAGE
Provides a SQLite-backed implementation of@effect/workflow’s message storage interface. Used by the workflow engine to persist workflow state across process restarts.
_smithers_runs, _smithers_nodes, and _smithers_attempts tables plus supporting indices. The getSqlMessageStorage(db) function returns an existing instance without creating one.
EFFECT_LOGGING
Thin wrappers aroundEffect.logDebug/Info/Warning/Error that fire-and-forget via runFork. Each accepts an optional annotations map and an optional log span name.
EFFECT_LOG_FORMATS_JSON_PRETTY_LOGFMT
Log format selection is controlled viaSmithersObservabilityOptions.logFormat. The observability layer applies the chosen format to the shared runtime layer:
| Format | Description |
|---|---|
"json" | Structured JSON lines — suitable for log aggregation pipelines |
"pretty" | Human-readable colored output for local development |
"logfmt" | Key=value logfmt — compatible with Loki and similar systems |
EFFECT_METRICS
Pre-defined EffectMetric instances for every significant system boundary in Smithers. Import individual metrics and compose them with Metric.increment, Metric.update, Metric.set, or Metric.tagged.
Counters (selection)
| Name | Metric |
|---|---|
runsTotal | smithers.runs.total |
nodesStarted / nodesFinished / nodesFailed | smithers.nodes.* |
toolCallsTotal / toolCallErrorsTotal | smithers.tool_calls.* |
approvalsRequested / approvalsGranted / approvalsDenied | smithers.approvals.* |
tokensInputTotal / tokensOutputTotal | smithers.tokens.* |
tokensContextWindowBucketTotal | smithers.tokens.context_window_bucket_total |
runsFinishedTotal / runsFailedTotal / runsCancelledTotal | smithers.runs.*_total |
errorsTotal | smithers.errors.total |
sandboxCreatedTotal / sandboxCompletedTotal | smithers.sandbox.* |
| Name | Metric |
|---|---|
activeRuns / activeNodes | smithers.runs.active, smithers.nodes.active |
schedulerQueueDepth | smithers.scheduler.queue_depth |
approvalPending | smithers.approval.pending |
timersPending | smithers.timers.pending |
processMemoryRssBytes / processHeapUsedBytes | smithers.process.* |
| Name | Metric |
|---|---|
nodeDuration / attemptDuration | smithers.node.duration_ms, smithers.attempt.duration_ms |
toolDuration | smithers.tool.duration_ms |
runDuration | smithers.run.duration_ms |
tokensInputPerCall / tokensOutputPerCall | smithers.tokens.*_per_call |
tokensContextWindowPerCall | smithers.tokens.context_window_per_call |
sandboxDurationMs / sandboxBundleSizeBytes | smithers.sandbox.* |
heartbeatDataSizeBytes / heartbeatIntervalMs | smithers.heartbeats.* |
trackEvent(event: SmithersEvent) is the high-level entry point — it maps every event type to the correct set of metric updates:
updateProcessMetrics() snapshots process.memoryUsage() and process uptime into gauges. Call it on a recurring interval from a background fiber.
EFFECT_DIFF_BUNDLE_COMPUTE
Produces a serializable diff bundle by comparing a git working tree against a base ref. Captures tracked file changes, binary files, and untracked files.EFFECT_DIFF_BUNDLE_APPLY
Applies a previously computedDiffBundle to a target directory. Attempts git apply first; falls back to per-patch application using the diff library for text patches and direct file writes for binary patches.
EFFECT_SCHEDULER_WAKE_QUEUE
A lightweight notify/wait queue used to wake the scheduler when new work becomes available, avoiding busy polling.notify() resolves a pending wait() immediately, or increments an internal pending counter so the next wait() call returns without suspending. Multiple notify() calls before a wait() are coalesced into a single wakeup.
EFFECT_WORKFLOW_VERSIONING_RUNTIME
Manages workflow patch decisions for safe migration of long-running workflows. A patch decision is a boolean recorded against a stringpatchId. New runs see true; runs that pre-date the patch see false (as stored in the run config).
usePatched hook to branch on a patch:
usePatched calls resolve() on the ambient WorkflowVersioningRuntime. Outside a versioning scope it always returns false.