Virta is a TypeScript-based DAG workflow and pipeline engine focused on portability, round-trip workflow interoperability, and secure tooling for AI-assisted development. See SPEC.md for the full technical specification.
- Pure TypeScript runtime with constructor-based step identity and parallel execution across DAG levels.
- Topological planning via
buildLevelsto group dependency-satisfied steps that can run in parallel. - Hooked pipeline runner (
runPipeline) that surfaces lifecycle events and returns structuredPipelineResultstatus.
Virta intentionally supports multiple representations so teams can exchange workflows with external systems:
- Amazon States Language (ASL) (docs) import/export.
- Arazzo (spec) import/export.
- BPMN 2.0 (OMG spec) process import/export to interoperate with BPM tools while preserving DAG semantics.
- TypeScript procedural code generation and parsing (export/import with DAG validation).
- JSONata (docs) for inside-step transformations.
| Capability / Feature | ASL (AWS Step Functions) | Arazzo | BPMN 2.0 |
|---|---|---|---|
| DAG task graph (steps + dependencies) | ✅ Full | ✅ Full | ✅ Full (tasks/gateways mapped to DAG nodes) |
| Parallel branches | ✅ Parallel state | ✅ parallel block |
✅ Parallel gateways |
| Conditional choice | ✅ Choice state | ✅ switch/when |
✅ Exclusive gateways |
| Loop/repeat constructs | Map, Retry) |
loop / bounded) |
while) |
| Timers / waits | ✅ Wait state | ✅ sleep |
✅ Intermediate timer events |
| Error handling & retries | ✅ Catch / Retry |
✅ on_error |
✅ Boundary events (mapped to retries/compensation) |
| Data mapping / expressions | ✅ Pass/Parameters | ✅ Inputs/Outputs (JSONata) | ✅ Data objects (JSONata inside tasks) |
| Human tasks / forms | ❌ Not modeled | ❌ Not modeled | |
| Vendor-specific extensions | States.*) |
Round-trip intent: import/export fidelity is measured against this matrix; unsupported elements are dropped or downgraded with explicit warnings. A conformance validator (per adapter package) will exercise feature-coverage fixtures to flag gaps when formats evolve.
An execution planner selects the right deployment model per pipeline:
- Inline AWS Lambda for simple or latency-sensitive pipelines.
- AWS Step Functions for orchestrated workflows.
- Hybrid splits when some steps need orchestration and others prefer inline execution.
The @virta/runner package provides a unified execution API with automatic fallback:
- Lambda-first execution attempts to run in Lambda (or local simulation).
- Runtime monitoring detects approaching timeouts.
- Automatic fallback migrates execution to Step Functions (via hybrid split) or Fargate if needed.
- Local simulation via
docker-localadapter usingdocker-lambdaanddocker-step-functions.
Virta can be exposed through an MCP server so LLM tools and IDE agents can introspect and operate pipelines:
- Tools include listing pipelines, retrieving definitions, previewing plans, running pipelines, and exporting/importing ASL, Arazzo, BPMN, or TypeScript.
- Suggested package name:
@virta/mcp-server.
A fluent API for constructing pipelines in TypeScript without boilerplate:
const pipeline = new PipelineBuilder<Source, Target>()
.add(Step1)
.add(Step2, { dependsOn: [Step1] })
.build();Monorepo packages are organized to keep the core runtime separate from format adapters and infra tooling. Folder names stay unscoped (e.g., packages/core), while package.json names use the scoped @virta/* convention common across TypeScript/Node libraries:
packages/core(@virta/core) — DAG engine (TransformationContext,PipelineStep,buildLevels,runPipeline).packages/registry(@virta/registry) — registration utilities andPipelineDefinitionconversion helpers.packages/jsonata(@virta/jsonata) — JSONata helpers for step-level transformations.packages/asl,packages/arazzo,packages/bpmn(@virta/asl,@virta/arazzo,@virta/bpmn) — import/export adapters for ASL, Arazzo, and BPMN.packages/ts-codegen(@virta/ts-codegen) — TypeScript code generation and parsing with DAG validation.packages/planner(@virta/planner) — critical path analysis and execution mode selection.packages/cdk(@virta/cdk) — CDK/projen infrastructure generators for Lambda/Step Functions deployments.packages/runner(@virta/runner) — unified execution runner with adapters and fallback.packages/mcp-server(@virta/mcp-server) — MCP tooling surface for pipelines.packages/examples(@virta/examples) — sample pipelines and demos.
pnpm installto restore dependencies.pnpm -r build/pnpm -r lintto build and type-check all packages.pnpm -r testto run package-level test suites (e.g.,@virta/core).
Changes are versioned with Changesets:
- Run
pnpm changesetto record package-specific change notes. - Run
pnpm version:packagesto apply pending changesets and update package versions across the monorepo. - Run
pnpm releaseto publish updated packages after builds/tests succeed.
Virta packages publish under the @virta scope to GitHub Packages:
- Authenticate with a token that has the
packages:writescope:export GITHUB_TOKEN=<gh_token>. - Use the repo
.npmrc(scope registry is already set tohttps://npm.pkg.github.com). - Run validation before publishing:
pnpm -r lintandpnpm -r test. - Create a changeset for each package that should release:
pnpm changeset. - Apply the versions:
pnpm version:packages(this updatespackage.jsonfiles and changelogs). - Publish to GitHub Packages:
pnpm release.
To ship the current @virta/core build first, add the changeset noted above, then run steps 5 and 6 to push the package to GitHub Packages.
Releases can also run via CI with the Release packages workflow. On pushes to main, the workflow:
- installs dependencies with pnpm on Node.js 24, runs
pnpm -r lintandpnpm -r test, and then invokeschangesets/action@v1withpnpm version:packages/pnpm release. - uses
secrets.GITHUB_TOKENfor both repository writes and publishing tonpm.pkg.github.com(the.npmrcexpectsGITHUB_TOKEN).
When there are unpublished changesets, the workflow opens a release PR. Merging that PR triggers the publish step to GitHub Packages with the updated versions and changelogs.