Skip to main content

Packages & architecture

Agent Flow is a pnpm monorepo of five packages laid out along the compilation chain:

.flow source


@dynamic-workflow/lang Langium grammar + parsing (lex/parse → AST)


@dynamic-workflow/compiler semantic + type checking → Flow IR → codegen (restricted JS)


@dynamic-workflow/sandbox subprocess + isolated-vm, loads and runs the artifact


@dynamic-workflow/runtime runtime semantics: events, AgentRuntime adapter, FakeAgentRuntime


@dynamic-workflow/cli flow check / compile / run

Package list

PackageResponsibilityKey files
@dynamic-workflow/langgrammar and parser (Langium)src/language/agent-flow.langium
@dynamic-workflow/compilercheckFlow (diagnostics) and compileFlow (IR + JS codegen)src/checker.ts, src/codegen.ts
@dynamic-workflow/runtimeruntime semantics: FlowEventSink, the AgentRuntime interface and FakeAgentRuntime, typed errorssrc/fake-agent.ts etc.
@dynamic-workflow/sandboxsandbox execution: subprocess → isolated-vm → trusted bootstrap ($runtime ABI)e2e tests
@dynamic-workflow/clicommand line: check / compile / runsrc/main.ts

Every hop of the chain

  1. Parse (language): .flow → lexing/parsing (Langium) → syntax AST
  2. Check (compiler.checker): semantic diagnostics (scopes/resources/ dependencies) + type diagnostics (inference/assignability/expect), merged
  3. Compile (compiler.codegen): syntax AST → Flow IR (with metadata like StageIR.dependencies) → ESTree → restricted JavaScript
  4. Sandbox (sandbox): a subprocess hosts an isolated-vm running the trusted bootstrap; workflow glue reaches the host only through $host.invoke(op, payload)
  5. Runtime (runtime): deterministic structures execute inside the bootstrap; agent calls forward to host-side HostOps (the budget / concurrency / resolution / narrowing / validation / repair / retry pipeline); events stream through FlowEventSink

Plugging in your own agent system

Exactly one interface stands between language and model: AgentRuntime. As a host you provide:

  1. resolveAgent(resourceId) — map the logical id of use agent "my-assistant" onto a concrete implementation
  2. resolveTeam(teamId) — return the team (main plus members) for team.main / team.member(...) routing and membership validation
  3. Invocation — receive the task descriptor (target, task, input, the post-intersection tool set, write policy, OutputContract) and return a structured output; contract validation and the repair loop belong to the Runtime

Usage from the CLI (packages/cli/src/main.ts):

const agents = new FakeAgentRuntime({
teams: {
'engineering-team': {
main: 'lead',
members: ['lead', 'implementer', 'test-engineer', 'reviewer'],
},
},
});

const result = await runFlowSandboxed(compiled, input, {
host: { agents, events, context: { project: 'cli-demo' } },
});

Swap FakeAgentRuntime for your implementation (OpenAI, Anthropic, an internal gateway...) — the workflow doesn't change a line. That is where "vendor-free" lands.

Build & test

pnpm build # tsc -b: all packages
pnpm test # vitest unit tests
pnpm e2e # sandbox end-to-end tests
pnpm typecheck # type check
pnpm lint # biome