# Atman DSL Syntax Reference
## Top-level declarations
| `flow name(params) -> ret { contract? stmts }` | Flow declaration. `-> ret` and `contract` optional. |
| `route "pattern" { flow: name }` | Route pattern → flow mapping |
| `default_route { flow: name }` | Fallback flow for unmatched input |
| `on session.start { stmts }` | Lifecycle hook: `session.start`, `session.end`, `session.context_compact`, `turn.start`, `turn.end` |
## Statements
| `name = expr` | Bind expression to variable |
| `{ field: alias, field2 } = expr` | Destructure struct |
| `when cond { stmts }` | Conditional block |
| `return expr` | Return from flow |
| `expr` | Bare expression (side effect) |
| `watch target { on event { actions } }` | Watch declaration |
## Expressions
### Literals
| `"..."` | string |
| `123` | int |
| `1.5` | float |
| `true` / `false` | bool |
| `@"/path"` | file reference |
### Operators (precedence low → high)
| 0 | `\|>` | Pipe |
| 1 | `\|\|` | Logical OR |
| 2 | `&&` | Logical AND |
| 3 | `== != < <= > >=` | Comparison |
| 4 | `+ -` | Add / Subtract |
| 5 | `* / %` | Multiply / Divide / Modulo |
| — | `!expr` | Unary NOT |
| — | `-expr` | Unary negate |
### Special nodes
#### `llm { kwargs }` — LLM call
```
llm {
model: "smart", // model alias or full name
context: session, // use session messages as context
system: @"prompts/system.md", // system prompt (string or @file)
messages: [...], // explicit message list (alternative to context)
prompt: "direct prompt", // direct prompt (alternative to context/messages)
input: { file: file, content: code }, // structured input for schema
schema: Review, // output type name
cache: true, // enable prompt caching
retry: 3, // retry count on failure
retry_classified: [timeout], // retry only specific error kinds
context_budget: 8000, // truncate prompt to token budget
stall_timeout: 120, // LLM stall timeout in seconds
tools: [fs.read, bash.spawn, "mcp.*"], // tool allowlist, "mcp.*" = all MCP
fallback: "default response", // fallback on failure
}
```
#### `fanout [items] collect: all|first` — Parallel fanout
#### `user_confirm(msg)` — User confirmation gate (returns bool)
#### `subflow(name, args...)` — Subflow invocation (enables recursion)
#### `fix_until_test_passes { kwargs }` — Edit-test loop
#### Message constructors
`user_msg(...)`, `assistant_msg(...)`, `system_msg(...)`, `tool_result(...)`
### Watch declarations
```
watch reply {
on token(match: "ERROR" | "FATAL") { abort("...") }
on elapsed(> 30000 ms) { warn("...") }
on tokens_consumed(>= 8000) { warn("...") }
}
```
Actions: `abort(msg?)` or `warn(msg?)`
### Contract blocks
Optional block at the start of a flow body. The parser accepts any block
name with `key: value` kwargs, but only `capabilities` is enforced by the
runtime:
```atman
contract {
scope { read: [project_root], write: [project_root], network: [any] }
capabilities { shell: true }
interjection { accept: [L1, L4] }
}
```
| `capabilities { shell: true }` | ✅ yes | Required for Tier 4 tools (bash, term). Without it, shell tools are blocked. |
| `scope { read, write, network }` | declarative | Declares intended access scope. Not enforced — FS access is controlled by session-level `fs_access_mode`. |
| `interjection { accept: [L1, L4] }` | declarative | Declares which interjection levels to auto-accept. Not enforced — injections are user-triggered. |
## Types
| `string` `int` `bool` `path` `float` | Primitives |
| `TypeName` | Named type |
| `[Type]` | List type |
| `{ field: Type, ... }` | Struct type |
## Example
```
flow review_code(file: path) -> Review {
contract {
scope { read: [project_root], write: [] }
}
gather = fanout [fs.read(file), fetch_rule("code-review")] collect: all
primary = llm {
model: "smart",
messages: [system_msg(@"prompts/review.md"), user_msg("Review.")]
input: gather
schema: Review
}
return primary
}
```