
Security News
Frontier AI Is Now Critical Infrastructure
The Fable shutdown shows how quickly model access can become a business continuity risk for AI-dependent engineering teams.
@agent-pattern-labs/iso-orchestrator
Advanced tools
Durable workflow primitives for AI-agent harnesses: resumable steps, keyed mutexes, and bounded parallel fan-out with file-backed state.
Durable workflow primitives for AI-agent harnesses.
This package is for the layer above a single agent session. An agent runtime
already knows how to think, call tools, and emit text. @agent-pattern-labs/iso-orchestrator
adds the deterministic parts that should not live only in prompt prose:
step() execution with file-backed recordsforEach(..., { maxParallel })It is intentionally generic. There is no built-in "dispatch a Codex worker" or "spawn an OpenCode task" primitive yet. Domain packages bring their own adapter for that part and use this package to enforce invariants around it.
npm install @agent-pattern-labs/iso-orchestrator
By default the package writes under .iso-orchestrator/ in the current
working directory:
.iso-orchestrator/
workflows/
my-flow-<hash>.json
locks/
my-flow-<hash>/
record.lock/
mutex/
company-role-<hash>.lock/
The workflow record contains:
idle, running, completed, failed)workflow.running, step.started, step.completed, ...)import { runWorkflow } from '@agent-pattern-labs/iso-orchestrator';
const { value, record } = await runWorkflow(
{
workflowId: 'apply-batch-2026-04-25',
dir: '.jobforge-runtime',
initialState: { applied: 0, skipped: 0 },
},
async (workflow) => {
await workflow.step('cleanup-geometra', async () => ({ ok: true }));
const jobs = [
{ company: 'Anthropic', role: 'Staff Engineer' },
{ company: 'OpenAI', role: 'Member of Technical Staff' },
{ company: 'Anthropic', role: 'Staff Engineer' },
];
const summary = await workflow.forEach(
jobs,
async (job) => {
return workflow.step(
`apply:${job.company}:${job.role}`,
async () => {
// Your own task-dispatch adapter goes here.
return { outcome: 'APPLIED', company: job.company, role: job.role };
},
{ idempotencyKey: `${job.company}:${job.role}` },
);
},
{
maxParallel: 2,
mutexKey: (job) => `${job.company}:${job.role}`,
},
);
await workflow.updateState((state) => ({
...state,
applied: summary.fulfilled,
skipped: summary.rejected,
}));
return summary;
},
);
console.log(value.fulfilled, record.status);
runWorkflow(options, fn)Creates or re-opens a workflow record, marks it running, executes fn, and
marks the workflow completed or failed.
Options:
workflowId: durable identifier for the logical workflowinitialState: JSON value written only when the workflow record does not exist yetdir: optional storage root (defaults to .iso-orchestrator)now: optional clock injection for testsopenWorkflow(options)Opens the workflow context without automatically running a top-level callback. Useful when you want finer control over lifecycle or only need inspection.
workflow.step(name, fn, options?)Runs one load-bearing step and persists its result.
idempotencyKey lets one logical step name be reused safely across runs.retry can be a number (3) or { attempts, shouldRetry }.Results must be JSON-serializable because they are persisted in the record.
workflow.withMutex(key, fn, options?)Runs fn while holding a process-safe filesystem lock for key. Useful when
two parallel tasks must never touch the same entity at once.
Options:
timeoutMs: how long to wait for the lockpollMs: wait interval while the lock is held elsewherestaleAfterMs: optional stale-lock eviction thresholdworkflow.heartbeat(key, detail?)Persists the latest heartbeat for a named worker or phase. This is useful when you want external inspectors to tell whether a background task is still progressing even if it is not currently holding a mutex.
workflow.touchLease(key, { holder, ttlMs, detail? })Acquires or renews a renewable lease for key.
WorkflowLeaseConflictError while the lease is activeUse this for "one worker owns this slot until its heartbeat expires" semantics without introducing a harness-specific queue.
workflow.releaseLease(key, holder?)Marks a lease released. Passing holder is optional but recommended so a
worker cannot accidentally release another worker's active lease.
workflow.forEach(items, fn, options?)Bounded fan-out over a list.
maxParallel controls concurrencymutexKey(item) optionally serializes related itemsstopOnError defaults to trueReturns a summary with results, fulfilled, and rejected.
workflow.updateState(updater)Replaces the durable JSON state. Accepts either a full state object or a functional updater.
workflow.appendEvent(input) / workflow.getRecord()Low-level helpers for custom lifecycle tracking and inspection.
This package does not try to be Temporal.
What it does:
What it does not do yet:
That narrower scope is deliberate. The goal is to let packages like JobForge stop expressing orchestration invariants only in prompt prose or Bash without forcing a heavyweight control plane.
FAQs
Durable workflow primitives for AI-agent harnesses: resumable steps, keyed mutexes, and bounded parallel fan-out with file-backed state.
We found that @agent-pattern-labs/iso-orchestrator demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Fable shutdown shows how quickly model access can become a business continuity risk for AI-dependent engineering teams.

Security News
AI agents are pulling packages into environments no scanner is watching, creating exposure before security teams can see it.

Security News
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.