Skip to content

Rulvar API reference


Rulvar API reference / @rulvar/executor

@rulvar/executor

Isolated tool executors for Rulvar: the subprocess ToolExecutorProvider (fresh workdir per dispatch, replaced environment, timeout and output bounds) and the container adapter over the same seam, plus the executor conformance kit and the optional two-phase effect ledger (a durable intent BEFORE the external effect, the outcome after, so a crash leaves an orphan intent as the reconciliation signal instead of an untracked effect).

Part of Rulvar, an embeddable TypeScript engine for durable, budget-bounded multi-agent LLM workflows, where a completed LLM call is never paid for twice. Full documentation: docs.rulvar.com.

Install

bash
pnpm add @rulvar/core @rulvar/executor

What it is NOT

The executors isolate a dispatch; they are not a security sandbox by themselves (bring a container or OS boundary for hostile code), and the effect ledger is not a transactional outbox, not an authorization surface, and not exactly-once delivery: the host's reconciliation against provider receipts stays mandatory.

Documentation

License

Apache-2.0

Classes

ClassDescription
ExecutorErrorA failed isolated dispatch. The engine catches whatever a ToolExecutorProvider throws and turns it into the call's error tool result, so message is what the model sees: it is kept concise and carries a stderr tail on exit.
LedgerCorruptionErrorThe fail-closed refusal of loadEffectLedger (RV502, widened by RV607): the file holds at least one line the scan cannot admit, unparseable bytes on an interior line, invalid UTF-8, a JSON value that is not an object, a missing or mistyped required field, or an unknown phase, none of which the writer's tail repair can produce, so it means external damage or a foreign writer, never a normal crash artifact. Reconciling from a partial scan would silently drop intents; triage the named lines instead (tolerateCorrupt: true surfaces them as data).

Interfaces

InterfaceDescription
ChildResult-
ChildSpec-
ConformanceExecutorConfigThe executor options the shared contract exercises.
ContainerExecutorOptions-
CorruptLedgerLineOne malformed line of the ledger file, surfaced for triage.
EffectLedgerScanWhat loadEffectLedger reads back from a JSONL ledger file.
ExecutorConformanceCheck-
ExecutorConformanceSuite-
ExecutorTestRegistrarStructural subset of the Vitest/Jest registration API.
SubprocessCommandSpecThe command a subprocess tool runs, carried on its executorSpec.
SubprocessExecutorOptions@rulvar/executor: isolated tool executors (RV-216). Reference ToolExecutorProvider adapters that run a tool's work OUT of the engine process, so a tool whose input is hostile or model-generated cannot reach host capabilities the way an in-process tool (an ordinary function call) can.
SubprocessToolInit@rulvar/executor: isolated tool executors (RV-216). Reference ToolExecutorProvider adapters that run a tool's work OUT of the engine process, so a tool whose input is hostile or model-generated cannot reach host capabilities the way an in-process tool (an ordinary function call) can.
ToolEffectIntentThe pre-dispatch half of a two-phase ledger entry (RV404): everything the executor knows BEFORE the external effect is dispatched, which is exactly the set a host needs to reconcile an orphaned effect with the effect's provider (look the idempotency key up, correlate by tool and argsHash). attemptId is the attempt join key (RV501): the outcome record of the same attempt carries the identical value. startedAt remains the documented legacy join for rows written before the id shipped; a wall-clock millisecond is not unique, which is why the id exists.
ToolEffectLedgerThe side-effect ledger seam. An executor calls record once per dispatch (success or failure). Binding an approval to its effect is then a lookup: the approval entry and the effect share (runId, tool, argsHash), and the idempotency key is stable across a rerun of the same call.
ToolEffectRecordOne dispatch's side-effect facts, for the ledger.
TornLedgerArtifactA torn fragment the writer quarantined while repairing a tail (RV502).

Type Aliases

Type AliasDescription
ChildStopReason-
ConformanceExecutorFactoryBuilds the provider under test from a shared-contract config.
ExecutorErrorCodeWhy an isolated dispatch failed.

Functions

FunctionDescription
containerExecutorBuilds a container ToolExecutorProvider over a docker-compatible CLI. Register it as createEngine({ executors: { container: containerExecutor({ image }) } }); tools declaring executor: 'container' dispatch through it. Define such tools with subprocessTool and set executor to 'container', or hand-build a ToolDef.
executorConformanceBuilds the conformance suite. factory produces the provider under test from a shared config; the kit supplies the command (its own runner, run by runtime, default the current Node) and the per-check options.
hashArgsA stable content hash of the arguments for the ledger's argsHash. It canonicalizes object key order so equal arguments hash equally regardless of property order.
jsonlEffectLedgerA two-phase ToolEffectLedger appending JSON lines to path (`{ phase: 'intent'
loadEffectLedgerScans a JSONL ledger file into intents, outcomes, and the orphaned intents a host must reconcile, pairing attempts exactly (RV501). A torn TRAILING fragment (the crash-mid-write artifact) is tolerated and reported; everything else the scan cannot decode, parse, and validate, invalid UTF-8, non-object JSON, a missing required field, an unknown phase (RV607), fails the scan closed with a typed LedgerCorruptionError unless tolerateCorrupt asks for the lines as data (RV502). Under tolerateCorrupt the scan never throws anything rawer than that: a malformed line is data, not an exception.
memoryEffectLedgerAn in-memory ledger for tests and single-process hosts. It implements the two-phase capability: intents() exposes the pre-dispatch rows, entries() the outcomes, exactly as before.
parseToolResultThe tool-program result protocol: the child's stdout, trimmed, is the JSON result. Empty stdout is the null result; anything else must parse as JSON or the dispatch fails typed protocol. Diagnostics belong on stderr, which never enters the result.
registerExecutorConformance-
runChildProcessSpawns one child and resolves with its captured output and exit status, or rejects if the process could not be spawned at all (e.g. the command is a bare name and PATH is not in env, so it cannot be resolved). A child that exits non-zero or is killed resolves normally; interpreting that is the caller's job.
subprocessExecutor@rulvar/executor: isolated tool executors (RV-216). Reference ToolExecutorProvider adapters that run a tool's work OUT of the engine process, so a tool whose input is hostile or model-generated cannot reach host capabilities the way an in-process tool (an ordinary function call) can.
subprocessTool@rulvar/executor: isolated tool executors (RV-216). Reference ToolExecutorProvider adapters that run a tool's work OUT of the engine process, so a tool whose input is hostile or model-generated cannot reach host capabilities the way an in-process tool (an ordinary function call) can.