DSL compiler for the A2E (Agent-to-Execution) Protocol. It compiles a human-readable domain-specific language into A2E JSONL format, enabling AI agents to generate workflows without writing verbose JSON.
A2E is a declarative protocol that enables AI agents to safely generate and execute workflows without arbitrary code execution. The protocol defines 8 core operations (ApiCall, FilterData, TransformData, Conditional, Loop, StoreData, Wait, MergeData) and uses JSONL as its transport format.
See the full A2E specification.
Writing A2E workflows in raw JSONL is verbose and error-prone. a2e-lang provides a compact, readable syntax that compiles down to valid A2E JSONL:
a2e-lang DSL (human-readable) → A2E JSONL (machine-readable)
This is especially useful when AI agents (LLMs) generate workflows from natural language — the DSL is more concise than raw JSON, reducing token usage and generation errors.
pip install -e .Requires Python 3.10+.
Create a file named pipeline.a2e:
workflow "user-pipeline"
fetch_users = ApiCall {
method: "GET"
url: "https://api.example.com/users"
headers: { Authorization: credential("api-token") }
-> /workflow/users
}
filter_active = FilterData {
from /workflow/users
where status == "active", points > 100
-> /workflow/filtered
}
store = StoreData {
from /workflow/filtered
storage: "localStorage"
key: "active-users"
}
run: fetch_users -> filter_active -> store
Compile it:
# Official A2E spec format (recommended)
a2e-lang compile pipeline.a2e --spec
# Pretty-printed
a2e-lang compile pipeline.a2e --spec --pretty
# Legacy bundled format
a2e-lang compile pipeline.a2eOne JSONL line per operation, matching the A2E specification:
{"type":"operationUpdate","operationId":"fetch_users","operation":{"ApiCall":{"outputPath":"/workflow/users","method":"GET","url":"https://api.example.com/users"}}}
{"type":"operationUpdate","operationId":"filter_active","operation":{"FilterData":{"inputPath":"/workflow/users","outputPath":"/workflow/filtered","conditions":[{"field":"status","operator":"==","value":"active"}]}}}
{"type":"operationUpdate","operationId":"store","operation":{"StoreData":{"inputPath":"/workflow/filtered","storage":"localStorage","key":"active-users"}}}
{"type":"beginExecution","executionId":"user-pipeline","operationOrder":["fetch_users","filter_active","store"]}Each message has:
"type"— Message type (operationUpdateorbeginExecution)"operationId"— Unique operation identifier"executionId"— Workflow name as execution ID"operationOrder"— Full execution sequence
All operations bundled in a single operationUpdate message:
{"operationUpdate":{"workflowId":"user-pipeline","operations":[...]}}
{"beginExecution":{"workflowId":"user-pipeline","root":"fetch_users"}}a2e-lang compile <file> [--spec] [--pretty] # Compile .a2e to JSONL
a2e-lang validate <file> # Validate without compiling
a2e-lang ast <file> # Show parsed AST (debug)
a2e-lang graph <file> # Generate Mermaid flowchart
a2e-lang simulate <file> [--input data.json] # Dry-run workflow simulation
a2e-lang decompile <file> # Convert JSONL back to .a2e DSL
a2e-lang recover <file> # Auto-fix LLM syntax mistakes
a2e-lang tokens <file> # Token budget analysis (DSL vs JSONL)
a2e-lang score <file> # Syntax learnability score
a2e-lang prompt [template] --task "..." # Generate LLM prompt template
a2e-lang prompt --list # List available templates
a2e-lang run <file> [--input data.json] # Execute workflow with native engine
a2e-lang run <file> --no-retry # Execute without retry on failures
a2e-lang webhook <file> [--port 8080] # Start webhook server for HTTP triggers
a2e-lang sourcemap <file> [--out map.json] # Generate DSL->JSONL source map
a2e-lang registry list # List installed workflows
a2e-lang registry search <query> # Search registry
a2e-lang registry publish <file> # Publish workflow
💡 VSCode Extension: Install from
vscode-extension/for syntax highlighting, bracket matching, and code folding. See vscode-extension/README.md.💡 LSP Server: Run
python -m a2e_lang.lspfor diagnostics, autocompletion, and hover info. Requirespip install pygls.
| Flag | Description |
|---|---|
--spec |
Output in official A2E protocol format |
--pretty |
Pretty-print JSON output (indented) |
--watch |
Watch file and recompile on changes |
--input |
JSON file with mock data for simulation |
--max-operations |
Max operations limit (simulate) |
--max-depth |
Max nesting depth limit (simulate) |
--max-conditions |
Max conditions per operation (simulate) |
from a2e_lang import parse, Validator, Compiler, SpecCompiler
from a2e_lang import Simulator, Decompiler, generate_mermaid
# Parse and validate
workflow = parse(open("pipeline.a2e").read())
errors = Validator().validate(workflow)
# Validate with complexity limits (protects against LLM-generated bloat)
errors = Validator(max_operations=20, max_depth=3, max_conditions=5).validate(workflow)
# Compile — choose your format
jsonl_spec = SpecCompiler().compile(workflow) # Official A2E format
jsonl_legacy = Compiler().compile(workflow) # Legacy bundled format
jsonl_pretty = SpecCompiler().compile_pretty(workflow) # Pretty-printeda2e_lang/
├── grammar.lark # Lark EBNF grammar for the DSL
├── parser.py # Lark-based parser → AST
├── ast_nodes.py # Immutable AST data models (frozen dataclasses)
├── validator.py # Semantic validator (9 checks + complexity limits)
├── compiler.py # AST → Legacy bundled JSONL
├── compiler_spec.py # AST → Official A2E spec JSONL
├── graph.py # AST → Mermaid flowchart
├── simulator.py # Dry-run workflow simulation engine
├── decompiler.py # JSONL → DSL (reverse compiler)
├── watcher.py # File watcher for auto-recompilation
├── lsp.py # Language Server Protocol (diagnostics + completion)
├── recovery.py # Error recovery (auto-fix LLM syntax mistakes)
├── tokens.py # Token budget calculator (DSL vs JSONL)
├── prompts.py # LLM prompt templates (GPT-4, Claude, Gemini, etc.)
├── scoring.py # Syntax learnability scoring
├── engine.py # Native execution engine (8 op handlers)
├── logging.py # Structured logging (per-op timing)
├── resilience.py # Retry + circuit breaker
├── webhook.py # Webhook server (HTTP trigger)
├── registry.py # Workflow registry (publish/discover)
├── orchestrator.py # Multi-agent workflow chaining
├── plugins.py # Custom operation type registration
├── sourcemap.py # DSL → JSONL source mapping
├── errors.py # Error types with source locations
└── cli.py # Command-line interface (18 commands)
examples/
├── simple.a2e # Basic 3-operation pipeline
├── full_workflow.a2e # All 8 operation types demo
└── test_workers_ai.py # LLM agent generates a2e-lang from natural language
vscode-extension/ # VSCode syntax highlighting + LSP client
tests/ # 214 tests (pytest)
The pipeline has three core stages plus visualization and simulation:
- Parsing:
grammar.lark+ Lark (Earley parser) → AST (immutable frozen dataclasses) - Validation: 9 semantic checks + configurable complexity limits
- Compilation: AST → A2E protocol JSONL via
CompilerorSpecCompiler - Visualization: AST → Mermaid flowchart via
graph.py - Simulation: Dry-run execution with condition evaluation via
simulator.py
┌─────────────┐
┌──► │ Compiler │ ──► Legacy JSONL
│ └─────────────┘
┌──────┐ ┌─────┐ │ ┌─────────────┐
│.a2e │─►│Parse│──┼──► │SpecCompiler │ ──► A2E Spec JSONL
│source│ │+ AST│ │ └─────────────┘
└──────┘ └──┬──┘ │ ┌─────────────┐
│ ├──► │ Graph │ ──► Mermaid
┌───▼────┐│ └─────────────┘
│Validate││ ┌─────────────┐
└────────┘└──► │ Simulator │ ──► Execution Trace
└─────────────┘
All 8 core operations from the A2E protocol spec:
| Operation | Description |
|---|---|
ApiCall |
HTTP requests (GET, POST, PUT, DELETE, PATCH) |
FilterData |
Array filtering with conditions |
TransformData |
Data transformation (sort, select, map, group) |
Conditional |
Conditional branching (if/then/else) |
Loop |
Array iteration |
StoreData |
Persistent storage |
Wait |
Execution delay |
MergeData |
Merge multiple data sources |
Plus 8 additional utility operations: GetCurrentDateTime, ConvertTimezone, DateCalculation, FormatText, ExtractText, ValidateData, Calculate, EncodeDecode.
See LANGUAGE.md for the complete DSL syntax reference.
See ROADMAP.md for the strategic roadmap.
- A2E Protocol — The protocol specification this compiler targets