Grammar
Reference for .too source syntax in Toolang 0.4.0, based on
tree-sitter-toolang 0.4.0.
The upstream syntax and CST reference
and generated EBNF
contain the complete parser contract. Runtime defaults and validation below are
identified separately. See authoring conventions
and Run agent scripts for usage.
Changes in 0.4.0
- Use
generate Nfor repeated independent calls,runfor a single call returning an array or consuming an entire array, andreducefor sequential reduction.scatter,storm,gather, andsettleare ordinary text. - Reducer initializers use
initial:, replacingfrom:. async run,await,spawn, andexecsupport background calls, handles, independent roots, and control transfer.- Lane clauses precede named or inline targets. Named collection targets use
using; inline targets omit it. Unit spellings do not depend on the count. - Repeat counts and conditions are independently optional. An
untilcondition accepts a name or inline text and may appear anywhere in its repeat body. choreremains a declaration;taskis no longer a source declaration.#@marks program documentation;##!is item documentation containing!.- Same-line content retains every
#. Explicit text blocks preserve keywords, comment markers, and assignment-looking lines as literal content.
Program and layout
program ::= (trivia | item)*
item ::= with | struct | psyche | skill | service | prompt | chore
| context | instruct | agic | flowTop-level declarations start at column zero. The first substantive entry in a body establishes its baseline; structural siblings share it. A deeper entry requires an enclosing body, and dedents must reach an ancestor baseline. Comments and blank lines do not satisfy a required body. Cap and chore bodies are optional; struct, agic, and flow bodies are required.
Spaces and tabs separate structural tokens. Tabs advance to eight-column stops; do not mix tabs and spaces in structural indentation. LF and CRLF are supported. EOF can finish a final nonempty line, but cannot supply missing content.
Names, types, and signatures
identifier ::= /[a-z][a-z0-9_]*/
type_name ::= /[A-Z][A-Za-z0-9]*/
cap_name ::= /[a-z][a-z0-9_-]*/
integer_literal ::= /[0-9]+/
type ::= ("Text" | "Number" | "Boolean" | "Json" | "Part" | type_name) "[]"*
params ::= "(" (param ("," param)*)? ")"
param ::= (identifier | "_") "?"? (":" type)?Runnable, agent, local, and handle names use identifier. Chore names use the
same spelling as cap names. Keywords are allowed in explicit name positions:
let run = Evidence. binds the local run. _ can name a parameter, but cannot
be a local destination or await handle. Qualified route references use
([A-Za-z_][A-Za-z0-9_-]*::)*(agic:|flow:)?[A-Za-z_][A-Za-z0-9_-]*;
call targets use the narrower identifier form.
[] is a contiguous suffix; spaces before it are allowed. Integers are unsigned
decimal digits, including leading zeros. lane/lanes and time/times are
interchangeable parser tokens; the formatter chooses their spelling by value.
Runtime signature defaults:
- Omitting the parameter list implies
_ : Part[];()declares no inputs. - An explicit untyped
_defaults toPart[]; an untyped named input defaults toText. If_is present, it must be first. - An omitted declaration return type defaults to
Text. Inline target defaults depend on the operation. Astructdefines a user-defined structured type.
struct Finding:
summary: Text
sources?: Text[]
agic summarize(_: Text, style?: Text) -> Finding:
Summarize {{_}} in the requested {{style}} style.Typed boundaries
Named input values must match the runnable signature. Text-source callers
(including the CLI) decode Number, Boolean, arrays, and structs from text;
the decoded HTTP run endpoint accepts their JSON values directly. Boolean
text uses lowercase true or false, and a Boolean is not a Number.
Struct fields are checked for unknown keys, missing required fields, and
declared types. Output is checked against the declared return type as well;
an incompatible model response fails the run.
Part[] carries ordered multimodal content. Text requires text-compatible
parts; it does not silently stringify images. Part requires exactly one part.
Array operations act on the outer array: generate 3 with a Text[] target
returns Text[][], and map preserves that outer item boundary.
Comments and content
| Marker | Structural meaning |
|---|---|
# | Plain comment; also allowed inline on structural lines. |
#! | Shebang only at byte zero; otherwise a plain comment. |
#@ | Program documentation at program scope and column zero. |
## | Item documentation. ! after this marker is ordinary text. |
## @param name description | Parameter documentation with a same-line description. |
Content can follow its introducing : or = on the same line, or occupy an
indented block. Same-line content consumes the whole physical line, including
#; it has no inline comments. Multiline content establishes a text baseline,
preserves deeper indentation, and ends on dedent. Once explicit text starts,
keywords, Markdown fences, comment markers, and assignment-looking lines remain
literal. Blank lines alone cannot satisfy required content.
Implicit agic messages and flow runs form paragraphs: adjacent lines and one
intervening blank line stay together; two blank lines or a structural comment
split them. Each substantive line checks the context's complete first word for
syntax. runworker and run_suffix stay prose; run selects a flow operation.
Use explicit content when prose starts with a keyword.
flow explain:
let note = # This hash is content.
run:
# This heading is literal.
generate and await remain literal here.
Explain {{note}} and {{_}}.Templates such as {{_}}, {{topic}}, and {{_1._}} remain literal parser text;
placeholder extraction and substitution belong to language semantics.
Templates and includes
Content uses a restricted Mustache template language:
| Form | Meaning |
|---|---|
{{_}} | Current primary input |
{{topic}}, {{finding.summary}} | Named value or dotted field lookup |
{{items.0}} | Array item by zero-based index |
{{#items}}...{{.}}...{{/items}} | Positive section; iterate an array and access its current item |
{{^items}}...{{/items}} | Inverted section for an absent or false value |
Substituted text is not HTML-escaped. Sections must balance. Partials, template comments, delimiter changes, triple braces, expressions, and callable values are unsupported. Required named inputs must be supplied. An omitted optional input renders as empty text; use sections when surrounding text should also depend on its presence.
A line beginning with @ includes a file, for example @"notes with spaces.md".
A line beginning with $ invokes an available prompt; see
Prompt files. Markdown fenced code
blocks keep include and prompt lines literal. Content inclusion is resolved
by the caller and is separate from with, which acquires a cap definition.
History variables
| Variable | Value and scope |
|---|---|
_1, _2, ... | Previous completed iteration frames, newest first, within the nearest repeat's windowing capacity |
_1._ | Primary value at the end of the previous iteration; in a reducer, the current accumulator |
_1.__, _1._name | Primary and named values at entry to that iteration |
_1.name | A named value at exit from that iteration |
_far | Recalled compacted history as text, or empty text when excluded |
_near | Recalled recent messages as a JSON array, or an empty array when excluded |
_past | Recalled summary as a user message, followed by recalled recent messages |
A repeat starts with no completed frames. Guard an in-window frame with
{{#_1}}...{{/_1}} before using it on the first iteration. Directly reading a
missing frame fails; referring beyond the window fails even inside a guard.
An until condition that needs unavailable in-window frames waits until those
frames exist. Nested loops select their own history scope. Reduce keeps one
frame and seeds _1._ from initial: or the first item before its first call.
_far, _near, and _past follow the agic's recall selection independently
of iteration history.
Declarations
with ::= "with" ("psyche" | "skill" | "service" | "prompt") reference line_end
struct ::= "struct" type_name ":" line_end field_body
field ::= identifier "?"? ":" type line_end
cap ::= ("psyche" | "skill" | "service" | "prompt") cap_name ":" line_end cap_body?
chore ::= "chore" cap_name ":" line_end cap_body?
property ::= identifier "=" raw_value line_end
context ::= "context" identifier? ":" content
instruct ::= "instruct" identifier? ":" contentA struct requires at least one field. Caps and chores have an optional property
prefix followed by optional literal content. Comments and blank lines may
separate properties. The first non-property text line ends the property prefix
permanently. Properties and raw with references end before #; consumers
validate their values. A prompt has no typed signature; runtime rejects prompt
properties. An omitted context or instruct name defaults semantically to
default.
with psyche gh:briceyan/concise
skill review:
description = Review supplied changes.
Review {{_}} for concrete defects.
chore review_changes:
title = Review changes
Review the latest changes.
instruct: Give concise, source-backed answers.
context project: A documentation project.Agic and shared directives
agic ::= "agic" identifier? params? ("->" type)? ":" line_end agic_body
flow ::= "flow" identifier? params? ("->" type)? ":" line_end flow_body
message ::= ("user" | "assistant" | "tool") ":" content | implicit_paragraphAgics accept directives, messages, or directives followed by messages. Flows
require statements, optionally preceded by directives. pass is a standalone
whole-body alternative for either; it cannot coexist with other entries.
Bare agic paragraphs are user messages at runtime.
| Directive | Operators | Value |
|---|---|---|
models, tools, skills, services, psyches, prompts | =, +=, -= | Nonempty query text. |
hands, handoffs | = | Comma-separated runnable references, none, or *. |
recall | = | Comma-separated far/near, none, default, or *. |
lanes | = | Integer or default. |
instruct, context | = | Identifier, default, or none. |
hands permits model-requested run and spawn targets; handoffs permits
exec targets. At a root, omission selects all visible targets. A child inherits
its parent's routing settings within the same module; crossing modules resets
omitted routing settings to that module's visible targets. Explicit * selects
all visible targets and none selects none.
These are routing permissions for agics, not model or tool resource queries.
Use agic:NAME, flow:NAME, or a qualified module ref to disambiguate targets.
recall inherits the parent setting, starting with both far and near at a
root; none supplies neither, while default and * restore both. lanes
inherits concurrency, starting at 4; lanes = default restores 4. An operation's
explicit lane clause selects its own concurrency setting.
Directives form a leading prefix; the first message or statement ends it. Unknown assignments in that prefix are errors. Special list values stand alone. Structural inline comments are allowed on directive lines. Runtime validates query expressions, numeric ranges, duplicates, and referenced names.
instruct = name and context = name select top-level declarations; none
disables that layer. Omission inherits the parent's selection or defaults at a
root. Runnable-local instruct: and context: blocks are invalid.
agic research(_: Text):
tools = tavily/*
recall = far, near
user: Research {{_}} and cite sources.Flow
The following forms use BODY for same-line or indented content, NAME for an
identifier, and T for a type. Brackets indicate optional syntax.
run NAME
run [-> T]: BODY
async run NAME
async run [-> T]: BODY
spawn NAME
spawn [-> T]: BODY
await NAME
exec NAME
exec [-> T]: BODY
seek AGENT NAME
seek AGENT [-> T]: BODY
ask: BODY
let NAME = VALUE_STATEMENT
let VALUE_STATEMENT
let NAME = BODY
generate N [in P lanes] using NAME
generate N [in P lanes] [-> T]: BODY
map [in P lanes] using NAME
map [in P lanes] [-> T]: BODY
reduce using NAME
reduce [-> T]: BODY
keep first N
keep last N
keep [in P lanes] if NAME
keep [in P lanes] if [-> Boolean]: BODY
drop first N
drop last N
drop [in P lanes] if NAME
drop [in P lanes] if [-> Boolean]: BODY
sort ascending|descending [in P lanes] by NAME
sort ascending|descending [in P lanes] by [-> Number]: BODYrun invokes a named or inline runnable; async run returns a handle for a
background child. spawn starts an independent root and may retain its handle
through let. await waits for one named handle. exec transfers control to a
successor. seek and ask express agent and human requests, respectively.
Toolang 0.4.0 parses both forms, but the current executor reports a
bridge-required error because the corresponding execution bridges are absent.
At runtime, ordinary value statements update _; named let updates only its
local, and nameless let discards the result. Bare async launches and spawns
preserve _. A text binding evaluates Content into Part[]. exec and
repeat are not value statements and cannot be bound. The parser recognizes a
broader operation set after let; runtime rejects bound repeats.
generate N returns N complete child results in an outer array. map transforms
each outer item. reduce combines items sequentially. To produce an array in
one model call or summarize an entire array, use run with the appropriate
input/output signature. Filtering requires Boolean results; sorting requires
Number scores. Lane clauses precede targets, with using required only for
named generate/map/reduce targets. Reduce has no lane clause.
Reduction initializers
agic merge(_: Text) -> Text:
Incorporate {{_}} into the report in {{_1._}}.
flow combine(_: Text[]) -> Text:
reduce using merge:
initial: A report with no findings yet.
flow combine_inline(_: Text[]) -> Text:
reduce -> Text:
Incorporate {{_}} into the report in {{_1._}}.
initial:
A report with no findings yet.A named reducer's header colon requires an indented initial:. An inline
multiline reducer permits an initializer at its text baseline after nonempty
reducer text; a deeper initial: stays literal. Same-line reducer text cannot
have a following initializer. Without one, runtime seeds from the first item.
Repeat
agic inspect:
Inspect {{_}} and identify useful improvements.
agic ready -> Boolean:
Is {{_}} ready to publish?
agic revise:
Improve {{_}} using the available evidence.
flow improve:
repeat 5 times windowing 3:
run inspect
until ready
run: Improve {{_}} using the available evidence.
repeat:
until: Is {{_}} ready to publish?
run reviseA repeat requires at least one statement and permits at most one until at its
body baseline. Count and window are optional; count precedes window. A condition
may appear before, between, or after statements. It takes a bare name or :
followed by content, with no return annotation or argument list. Nested repeats
own their conditions; until is invalid outside a repeat.
Runtime checks the condition at its authored position. True exits the owning
repeat; false continues with the remaining statements. Without a count or
condition, repeat continues until control transfer, cancellation, or failure.
windowing N sets positive history capacity, which defaults to 3 prior frames.
CST
The root is program. Runnable bodies expose repeated directive, message,
or stmt fields. Statements use names such as run_stmt, generate_stmt,
reduce_stmt, and let_stmt; a bound operation is let_stmt.stmt.
Targets are runnable_name or inline_agic nodes. Authored text is exposed through
content containers with text leaves; a reducer's initial field points
directly to initializer content. See the upstream
CST contract
for all public fields and recovery nodes.
Validate and format
Use offline language commands to inspect .too files without making model calls:
too parse --check script.too
too fmt --check script.too
too highlight script.tooparse --check validates syntax and authored-language constraints; runtime
resource availability and execution are separate checks. See the
CLI reference for command options.