Skip to main content

Positioning & Design Principles

Agent Flow is a domain-specific language (DSL) for dynamic agent workflows.

It answers one question: when a workflow contains both control structure that must execute exactly (stages, parallelism, validation, retries, budgets) and inherently non-deterministic model calls, how should the code be organized?

Agent Flow's answer: separate the two at the syntax level. Deterministic parts are written as language structures and executed verbatim by the runtime; non-deterministic parts are fenced inside the single entry point agent(), and must carry an output contract.

.flow → Lexer/Parser (Langium) → AST → semantic analysis + type checking
→ Flow IR → ESTree → restricted JavaScript (glue code)
→ Sandbox (subprocess + isolate) → Flow Runtime → AgentRuntime adapter

Five design principles

1. Determinism first

Every structure that can execute deterministically — pipeline, stage, if, parallel, require, schema validation, limits, retry — is executed deterministically by the Runtime, never delegated to an agent. Errors discoverable at compile time (type mismatches, undeclared dependencies, reserved-word collisions) never survive to runtime.

2. agent() is the only point of non-determinism

Model calls concentrate in a single expression whose result must pass the JSON Schema declared by expect. This is Runtime-enforced, not a prompt suggestion — a failed validation automatically enters a repair loop, and exhausting it raises OutputValidationError.

3. The verdict belongs to the Runtime

verification.passed can only be computed from the verify { pass when ... } expression. An agent cannot return it. A model may claim "I ran the tests" — but the "passed" conclusion is always rendered by the runtime.

4. Capabilities only narrow

tools and write express requested capabilities; the effective set is host policy ∩ workflow request. Declaring more never yields more.

5. Embeddable, vendor-free

The language references no specific agent product; agent systems plug in through the AgentRuntime interface. Switch models or vendors — the workflow stays unchanged.

What it looks like

A minimal but complete workflow (excerpted from examples/simple.flow):

workflow hello(input: Request) -> Result {
use agent "writer" as writer

type Request { text: text }
type Result { answer: text }

pipeline {
stage answer -> Result {
return agent(writer) {
task "Answer the request"
input { request: input }
tools none
expect Result
}
}

return answer
}
}

Structure, types, contracts, resources — all explicit; the model appears in exactly one place, agent(writer).

Where it fits

  • Multi-stage, dependency-aware agent processes (plan → execute → verify → summarize)
  • Parallel fan-out over batch inputs with concurrency and budget control
  • Outputs that must pass a contract (structured data feeding downstream systems) and verification conclusions that must be auditable
  • Workflows that run in untrusted environments (compiled output is restricted JS, sandboxable)

If your case is a single-turn Q&A, a pure conversation, or a one-off script with no governance needs — call the model API directly; you don't need a DSL.

Next steps

  • Why a DSL — the full argument for benefits and necessity
  • Quickstart — run your first workflow in ten minutes