Complete reference for IntentScript syntax and semantics.
- Lexical Structure
- Task Structure
- Type System
- Expressions
- Constraints
- Validation Checks
- Pipelines
- Semantics
Line comments start with // and continue to end of line:
// This is a comment
task "Example" v1.0 { // Inline comment
goal: "Demonstrate comments"
run: step1 // Another comment
}
Block comments are reserved for future versions.
Identifiers match the pattern [A-Za-z_][A-Za-z0-9_]*:
valid_identifier
_private
CamelCase
snake_case
CONSTANT
Reserved keywords:
task goal input constraints
output_schema checks run on
off true false bool
int float text url
email path bytes json
openapi markdown xlsx pdf
object list enum optional
Double-quoted UTF-8 strings with escape sequences:
"simple string"
"string with\nnewline"
"string with\ttab"
"string with \"quotes\""
"string with\\backslash"
Integers and floating-point numbers:
42 // Integer
3.14 // Float
0 // Zero
1000000 // Large number
0.001 // Small float
Semantic version numbers:
v1.0
v1.2.3
v2.0.0
task <name> [version] {
<sections>
}
Example:
task "MyTask" v1.0 {
goal: "Task description"
input: param: type
constraints: { net = off }
output_schema: type
checks: { validation }
run: pipeline
}
Minimum required sections:
goalinput(can be empty)run
constraintsoutput_schemachecks
Sections can appear in any order, but conventional order is:
goalinputconstraintsoutput_schemachecksrun
Boolean value: true or false
input: enabled: bool = true
Integer number
input: count: int = 10
Floating-point number
input: price: float = 19.99
UTF-8 string
input: name: text = "default"
URL string
input: endpoint: url = "https://api.example.com"
Email address string
input: contact: email
Filesystem path
input: file: path
Raw byte array
input: data: bytes
JSON data
input: config: json
Object with named fields
input: user: object {
name: text
age: int
email: email
}
Nested objects:
input: config: object {
database: object {
host: text
port: int
}
cache: object {
enabled: bool
ttl: int
}
}
Ordered collection of items
input: tags: list[text]
input: numbers: list[int]
input: users: list[object {
name: text
email: email
}]
Enumeration of string values
input: status: enum("draft", "published", "archived")
input: level: enum("debug", "info", "warn", "error")
Optional value (may be absent)
input: description: optional[text]
input: metadata: optional[json]
OpenAPI specification document
input: api_spec: openapi
Markdown document
input: readme: markdown
Excel spreadsheet
input: data: xlsx
PDF document
input: report: pdf
Type checking rules:
- Exact match: Types must match exactly
- Optional handling:
optional[T]requires explicit handling - Subtyping: No implicit conversions
- Domain types: Treated as opaque values
"string"
42
3.14
true
false
Reference inputs or variables:
input_name
variable_name
function_name()
function_name(arg1, arg2)
function_name(key1: value1, key2: value2)
Named arguments:
render_template(name: "template", vars: config)
Positional arguments:
format_string("Hello, %s", name)
Mixed arguments (positional first):
process(input_file, output: output_file, format: "json")
constraints: {
fs_read_roots = ["./data", "./config"]
fs_write_roots = ["./output", "./artifacts"]
}
constraints: {
net = on // Enable network (off by default)
}
constraints: {
templates = on
}
constraints: {
exports = on // Enable XLSX, PDF exports
}
constraints: {
exec = on
}
constraints: {
forbid_ambiguous_terms = on
require_security_schemes = on
max_repairs = 3
timeout_ms = 60000
}
Inline (single constraint):
constraints: net = off
Block (multiple constraints):
constraints: {
net = off
templates = on
fs_read_roots = ["./"]
}
Validates that content is not empty
checks: {
must_not_be_empty
}
Validates UTF-8 encoding
checks: {
must_be_valid_utf8
}
Validates presence of sections
checks: {
must_have_sections(["Introduction", "Conclusion"])
}
Validates absence of patterns
checks: {
must_not_contain(["TODO", "FIXME", "WIP"])
}
Validates path prefixes
checks: {
must_include_paths_prefix("/api")
}
Validates UUID format for parameters
checks: {
must_use_uuid_format_for_params(["id", "user_id"])
}
Validates security schemes
checks: {
must_have_security_schemes(["bearerAuth", "apiKey"])
}
Validates all links in document
checks: {
validate_links
}
Validates against JSON schema
checks: {
validate_json_schema
}
Generic validation against output schema
checks: {
validate
}
Define custom validation predicates:
checks: {
custom_check(arg1: value1, arg2: value2)
}
Checks can run:
- During execution: On intermediate artifacts
- After execution: On final outputs
- Both: Specified in IR
Chain steps with ->:
run:
step1 ->
step2 ->
step3
run:
read_file(input_path) ->
parse_json ->
validate
run:
load_data ->
transform ->
save_results
Named arguments:
run:
read_file(path: input_file) ->
transform(operation: "uppercase") ->
write_file(path: output_file)
Positional arguments:
run:
format_string("Hello, %s", name) ->
write_file(output_path)
Data flows implicitly through pipeline:
run:
read_file(input) -> // Produces bytes
parse_json -> // Consumes bytes, produces json
validate -> // Consumes json
report(format: "text") // Produces text report
read_file(path)
write_file(path)
scan(directory, pattern: "**/*.md")
parse_json
parse_openapi
parse_markdown
validate
validate_schema
render_template(name, vars: {...})
export_xlsx(sheet: name, headers: true, output: path)
export_pdf(output: path)
report(format: "text")
report(format: "json", output: path)
report(format: "markdown", output: path)
Tasks describe what to achieve, not how:
task "Example" v1.0 {
goal: "Validate API specification"
// Declares intent, not implementation
run: read_file(spec) -> parse_openapi -> validate
}
Same inputs always produce same outputs:
- Compilation: Same source → same IR
- Execution: Same IR + inputs → same outputs
- Audit: Complete log of all operations
No unbounded loops:
// ❌ Not allowed: unbounded loop
while (condition) { ... }
// ✅ Allowed: bounded iteration
map(items, transform)
Iteration only over explicit collections:
run:
scan(directory, pattern: "*.md") -> // Bounded by filesystem
map(parse_markdown) -> // Bounded by input
validate
All side effects require explicit capabilities:
constraints: {
fs_read_roots = ["./data"] // Can only read from ./data
fs_write_roots = ["./output"] // Can only write to ./output
net = off // No network access
}
Violations are runtime errors:
// ❌ Error: Cannot read from ./secrets (not in fs_read_roots)
run: read_file("./secrets/key.txt")
Checks validate outputs:
checks: {
must_have_sections(["Introduction"])
}
Failed checks trigger bounded repair:
- Execute pipeline
- Run checks
- If failed and repairs < max_repairs:
- Attempt repair
- Go to step 2
- If failed and repairs >= max_repairs:
- Report failure
Static type checking at compile time:
input: count: int
// ❌ Error: Type mismatch
run: format_string(count) // Expects text, got int
Optional types require explicit handling:
input: description: optional[text]
// ❌ Error: Optional not handled
run: format_string(description)
// ✅ Correct: Handle optional
run: format_string(description or "No description")
Errors are reported with precise locations:
error[E0042]: type mismatch
--> task.intent:12:15
|
12 | run: format_string(count)
| ^^^^^ expected text, found int
|
help: convert to text: format_string(to_text(count))
Categories:
- Parse errors: Syntax issues
- Type errors: Type mismatches
- Semantic errors: Constraint violations
- Runtime errors: Execution failures
File ::= Task*
Task ::= "task" String Version? "{" Section* "}"
Version ::= "v" Number ("." Number)*
Section ::= GoalSection
| InputSection
| ConstraintsSection
| OutputSchemaSection
| ChecksSection
| RunSection
GoalSection ::= "goal" ":" Expr
InputSection ::= "input" ":" (InputDecl | "{" InputDecl* "}")
ConstraintsSection ::= "constraints" ":" (ConstraintDecl | "{" ConstraintDecl* "}")
OutputSchemaSection ::= "output_schema" ":" TypeExpr
ChecksSection ::= "checks" ":" (CheckDecl | "{" CheckDecl* "}")
RunSection ::= "run" ":" Pipeline
InputDecl ::= Ident ":" TypeExpr ("=" Literal)?
ConstraintDecl ::= Ident "=" ("on" | "off" | Literal | Expr)
CheckDecl ::= CallExpr | Ident
Pipeline ::= Step ("->" Step)*
Step ::= CallExpr | Ident
Expr ::= CallExpr | Ident | Literal
CallExpr ::= Ident "(" ArgList? ")"
ArgList ::= Arg ("," Arg)*
Arg ::= (Ident ":")? Expr
Literal ::= String | Number | "true" | "false"
TypeExpr ::= PrimitiveType
| "object" "{" (Ident ":" TypeExpr)* "}"
| "list" "[" TypeExpr "]"
| "enum" "(" String ("," String)* ")"
| "optional" "[" TypeExpr "]"
| DomainType
PrimitiveType ::= "bool" | "int" | "float" | "text"
| "url" | "email" | "path" | "bytes" | "json"
DomainType ::= "openapi" | "markdown" | "xlsx" | "pdf"
Ident ::= [A-Za-z_][A-Za-z0-9_]*
String ::= '"' ([^"\\] | '\\' .)* '"'
Number ::= [0-9]+ ("." [0-9]+)?// ❌ Bad
task "T1" v1.0 { ... }
// ✅ Good
task "ValidateOpenAPISpec" v1.0 { ... }
// ❌ Bad
goal: "Do stuff"
// ✅ Good
goal: "Validate OpenAPI specification against RustAPI policies"
// ❌ Bad: Too permissive
constraints: {
fs_read_roots = ["/"]
net = on
}
// ✅ Good: Minimal permissions
constraints: {
fs_read_roots = ["./data"]
net = off
}
// ❌ Bad: No defaults
input: {
timeout: int
retries: int
}
// ✅ Good: Sensible defaults
input: {
timeout: int = 30000
retries: int = 3
}
// ❌ Bad: Too generic
input: config: text
// ✅ Good: Specific type
input: config: json
// ❌ Bad: No validation
checks: {}
// ✅ Good: Multiple checks
checks: {
must_not_be_empty
validate_schema
must_have_required_fields
}