Core Examples
Note: These examples hoist a host extension with
use<ext:app> => $appand call methods via dotted access ($app.prompt(),$app.fetch(), etc.). Built-in functions (log,range,json) need no prefix. Frontmatter is opaque to rill; the host parses it and provides named variables to the script context.
Extraction Operators
Demonstrates destructuring, slicing, and enumeration.
Destructuring Function Results
# Destructure dict results into named variables
[output: "test output", code: 0] -> destruct<output: $out, code: $code>
$code -> .gt(0) ? {
"Tests failed:\n{$out}" -> log
}
"All tests passed" -> logProcessing Structured Data
# Process list of file-mode pairs
[
["src/auth.ts", "security"],
["src/api.ts", "performance"],
["src/db.ts", "security"]
] -> seq({
$ -> destruct<$f, $mode>
"Review {$f} for {$mode} issues" -> log
})Slicing Results
# Get first 3 items
["a", "b", "c", "d", "e"] -> slice<:3>
# ["a", "b", "c"]# Process in reverse order
["a", "b", "c"] -> slice<::-1>
# ["c", "b", "a"]Dict Iteration
# Use .entries to iterate over dict key-value pairs
[host: "localhost", port: 8080] -> .entries -> seq({
"{$[0]}={$[1]}"
}) -> .join("\n")Collection Operations
Pipeline operators for fan, fold, seq, filter, and aggregate patterns.
fan: Parallel Transform
# Define closure first, then use it
|x| { $x * 2 } => $double
[1, 2, 3, 4, 5] -> fan($double)
# [2, 4, 6, 8, 10]# Map with inline block
["alice", "bob", "carol"] -> fan({ "Hello, {$}!" })
# ["Hello, alice!", "Hello, bob!", "Hello, carol!"]filter: Parallel Predicate
# Keep elements matching condition (block form)
[1, 2, 3, 4, 5] -> filter({ .gt(2) })
# [3, 4, 5]# Filter with closure predicate
|x| { $x % 2 == 0 } => $even
[1, 2, 3, 4, 5, 6] -> filter($even)
# [2, 4, 6]# Filter non-empty strings
["hello", "", "world", ""] -> filter({ !.empty })
# ["hello", "world"]# Chain filter and fan
|x| { $x * 2 } => $dbl
[1, 2, 3, 4, 5] -> filter({ .gt(2) }) -> fan($dbl)
# [6, 8, 10]# Filter structured data
[
[name: "alice", age: 30],
[name: "bob", age: 17],
[name: "carol", age: 25]
] -> filter({ $.age -> .ge(18) })
# [[name: "alice", age: 30], dict[name: "carol", age: 25]]fold/chain: Reduction and Sequential Chaining
# Chain transformations
|s|"{$s} -> validated" => $validate
|s|"{$s} -> processed" => $process
|s|"{$s} -> complete" => $complete
"input" -> chain([$validate, $process, $complete])
# "input -> validated -> processed -> complete"
# Numeric reduction
|x|($x + 10) => $add10
|x|($x * 2) => $double
5 -> chain([$add10, $double, $add10])
# ((5 + 10) * 2) + 10 = 40seq with break: Early Termination
# Break stops iteration and returns collected results up to that point
[1, 2, 3, 4, 5] -> seq({
($ == 3) ? break
$ * 2
}) => $result
# Result: [2, 4]seq catches the break signal and returns the partial results list. Elements processed before break are included; the element that triggered break is not.
# Use filter to find matching elements
[1, 2, 3, 4, 5] -> filter({ .gt(3) })
# Result: [4, 5]Aggregate/Sum
# Sum numbers using fold
[10, 20, 30, 40] -> fold(0, { $@ + $ })
# 100
# Count matching elements using filter (parallel predicate)
$items -> filter({ .contains("error") }) -> .len => $count
"Found {$count} errors" -> logTransform and Collect
# Process items, collect results using fan
["file1.txt", "file2.txt", "file3.txt"] -> fan({ "analyzed: {$}" }) -> .join("\n")
# "analyzed: file1.txt\nanalyzed: file2.txt\nanalyzed: file3.txt"Args Type and Strict Invocation
Explicit argument unpacking with validation.
Named Args (Strict Invocation)
# Define a function
|a, b, c| { "{$a}-{$b}-{$c}" } => $fmt
# Create named args and invoke
ordered[a: 1, b: 2, c: 3] -> $fmt(...) # "1-2-3"
# Store args for later use
ordered[a: 1, b: 2, c: 3] => $myArgs
$myArgs -> $fmt(...) # "1-2-3"Named Args
# Named args spread positionally into parameters
|width, height|($width * $height) => $area
ordered[width: 10, height: 20] -> $area(...) # 200Parameter Defaults
# Defaults fill missing trailing arguments
|x, y = 10, z = 20|($x + $y + $z) => $fn
ordered[x: 5] -> $fn(...) # 35 (5 + 10 + 20)
ordered[x: 5, y: 10, z: 30] -> $fn(...) # 45 (5 + 10 + 30)Type Checking with .^type
# Use .^type to inspect values
42 => $x
$x.^type == number # true
"hello" => $s
$s.^type == string # true
[1, 2] => $l
$l.^type == list # true
ordered[a: 1, b: 2] => $t
$t.^type == ordered # true
[a: 1] => $d
$d.^type == dict # true
# Parameterized type comparison
[1, 2, 3] => $nums
$nums.^type == list(number) # true — exact structural match
["a", "b"] => $strs
$strs.^type == list(string) # true
$strs.^type == list(number) # false
# Use json() to serialize
[name: "test", count: 42] -> json
# '{"name":"test","count":42}'
# Use log() to debug while continuing pipe
"processing" -> log -> .len # logs "processing", returns 10Workflow Examples (require host functions)
Feature Implementation Workflow
Validates requirements, creates spec, iterates on review, then implements.
timeout: 00:10:00
args: requirements: string
use<ext:app> => $app
"""
Review the requirements document at {$requirements}.
Check for completeness and clarity.
Output READY if complete, or list missing elements.
""" -> $app.prompt() => $validation
$validation -> .contains("READY") -> !$ ? {
error "Requirements incomplete: {$validation}"
}
"""
Create a technical specification from {$requirements}.
Include API design, data models, and component structure.
""" -> $app.prompt() => $spec
"Specification created" -> log
$spec -> while (.contains("REVISION")) do {
"""
Review this specification for issues:
{$}
Output APPROVED if ready, or REVISION REQUIRED with feedback.
""" -> $app.prompt() => $review
$review -> ?(.contains("APPROVED")) { break }
"""
Update the specification based on this feedback:
{$review}
Original spec:
{$}
""" -> $app.prompt()
} => $approved_spec
"""
Implement the approved specification:
{$approved_spec}
Create the necessary files and tests.
""" -> $app.prompt() => $implementation
$app.prompt("Run tests and verify implementation") => $verification
$verification -> ?(.contains("PASS")) {
[0, "Workflow complete"]
} ! {
[1, "Verification failed: {$verification}"]
}Document-Driven Task Loop
Works through a checklist until complete.
args: plan: string
use<ext:app> => $app
# Initial check
$app.prompt("Read {$plan} and find the first unchecked item (- [ ])") => $status
# Work loop
$status -> while (!.contains("ALL COMPLETE")) do {
"""
Based on this status:
{$}
1. Implement the identified unchecked item
2. Mark it complete in {$plan}
3. Check if any unchecked items remain
4. Output ALL COMPLETE if done, or describe next item
""" -> $app.prompt()
} => $final
"Plan complete: {$final}" -> logTest-Fix Loop
Runs tests, fixes failures, repeats until passing.
args: target: string
use<ext:app> => $app
# Run tests
$app.prompt("Run tests for {$target} and report results") => $result
# Fix loop
$result -> while (.contains("FAIL")) do {
"Fixing failures..." -> log
"""
Fix these test failures:
{$}
Make minimal changes. Then run tests again and report results.
""" -> $app.prompt()
} => $final
$final -> ?(.contains("PASS")) {
"All tests passing"
} ! {
error "Could not fix all tests"
}Code Review
Reviews code against multiple criteria.
---
args: file: string
---
use<ext:app> => $app
$app.prompt("Read and summarize {$file}") => $summary
"""
Evaluate for SECURITY issues:
{$summary}
Output PASS, WARN, or FAIL with explanation.
""" -> $app.prompt() => $security
"""
Evaluate for PERFORMANCE issues:
{$summary}
Output PASS, WARN, or FAIL with explanation.
""" -> $app.prompt() => $performance
$security -> .contains("FAIL") -> ? {
error "Security review failed: {$security}"
}
$performance -> .contains("FAIL") -> ? {
error "Performance review failed: {$performance}"
}
"Code review passed"Environment-Aware Deployment
Deploys based on environment configuration.
args: service: string
use<ext:app> => $app
# Validate environment
$ENV.DEPLOY_ENV -> ?(.empty()) {
error "DEPLOY_ENV not set"
}
# Environment-specific deployment
($ENV.DEPLOY_ENV == "production") ? {
"""
Deploy {$service} to production.
- Run full test suite first
- Enable monitoring
- Use blue-green deployment
""" -> $app.prompt()
} ! ($ENV.DEPLOY_ENV == "staging") ? {
"""
Deploy {$service} to staging.
- Run smoke tests
- Enable debug logging
""" -> $app.prompt()
} ! {
$app.prompt("Deploy {$service} to development environment")
} => $result
"Deployment complete" -> log
[0, "Deployed {$service} to {$ENV.DEPLOY_ENV}"]Retry Pattern
Retries an operation until success or max attempts. Use do-while since you always want at least one attempt:
---
args: operation: string
---
use<ext:app> => $app
# Do-while: body runs first, then condition checked
do<limit: 5> {
"""
Perform: {$operation}
Output SUCCESS, RETRY, or FAILED.
""" -> $app.prompt()
} while (.contains("RETRY")) => $result
# Loop exits when result doesn't contain RETRY
$result -> .contains("SUCCESS") ? [code: 0, msg: "Succeeded"] ! dict[code: 1, msg: "Failed: {$result}"]The do-while form eliminates the separate first-attempt code since the body always executes at least once.
Inline Capture Pattern
Captures mid-chain for debugging or later reference while data continues flowing.
---
args: file: string
---
use<ext:app> => $app
# Inline capture: value flows through $raw to log to conditional
$app.prompt("Read {$file}") => $raw -> log -> .contains("ERROR") -> ? {
error "Failed to read: {$raw}"
}
# Continue with $raw available for later use
$app.prompt("Analyze this content:\n{$raw}") => $analysis -> log -> .empty -> ? {
error "Analysis produced no output"
}
# Both $raw and $analysis available
"""
Compare the original:
{$raw}
With the analysis:
{$analysis}
""" -> $app.prompt()Semantically, => $var -> is => $var.set($) -> — the capture acts like log, storing the value while passing it through unchanged.
Type-Safe Variables
Uses type annotations to prevent accidental type changes during script execution.
args: file: string
use<ext:app> => $app
# Define a typed helper closure
|input: string| {
$app.prompt("Validate: {$input}") -> ?(.contains("VALID")) { true } ! { false }
} => $validate:closure
# Capture with explicit type locks the variable
"processing" => $status:string
"checking {$file}" => $status # OK: same type
# 42 => $status # ERROR: cannot assign number to string
# Closures are type-locked too
# "oops" => $validate # ERROR: cannot assign string to closure
# Inline type annotation in pipe chain
$app.prompt("Check {$file}") => $result:string -> log -> ?(.contains("ERROR")) {
error $result
}
# Type annotations catch mistakes early
$app.prompt("Analyze {$file}") => $analysis:string
?(.contains("FAIL")) {
error "Analysis failed: {$analysis}"
}
[0, "Processing complete"]# Parameterized type annotation on closure parameter
|items: list(string)| {
$items -> seq({ $ -> .upper })
} => $upper_all:closure
# Runtime validates element types
$upper_all(list["hello", "world"])
# Result: list["HELLO", "WORLD"]Pattern Extraction
Extracts specific information from responses.
---
args: logfile: string
---
use<ext:app> => $app
$app.prompt("Read {$logfile} and find all ERROR lines") => $errors
$errors -> .empty -> ? {
"No errors found"
} ! {
"""
Analyze these errors and categorize them:
{$errors}
For each unique error type, suggest a fix.
""" -> $app.prompt() => $analysis
"Error analysis complete" -> log
$analysis
}Multi-Phase Pipeline with Bailout
Each phase can halt the pipeline on failure.
---
args: file: string
---
# Multi-phase pipeline with early exit on errors
"content of {$file}" => $content
$content -> .contains("ERROR") ? {
"Read failed" -> return
}
"analyzed: {$content}" => $analysis
$analysis -> .contains("FAIL") ? {
"Analysis failed" -> return
}
"Pipeline complete: {$analysis}"Arithmetic in Loops
Uses bar-delimited arithmetic for calculations within workflow logic.
args: items: string
use<ext:app> => $app
# Count items and calculate batch sizes
$app.prompt("Count items in {$items}") -> .match("(\\d+) items") => $m
$m -> .empty -> ? {
error "Could not parse item count"
}
$m.groups[0] -> number => $count
# Calculate batches: ceil(count / 10)
(($count + 9) / 10) => $batches
"Processing {$count} items in {$batches} batches" -> log
# Process each batch using range
range(1, $batches + 1) -> seq({
$ => $batch_num
(($batch_num - 1) * 10) => $start
($start + 10) => $end
"""
Process batch {$batch_num} of {$batches}
Items {$start} through {$end}
""" -> $app.prompt()})
[0, "Processed all batches"]Signal-Based Workflow
Uses explicit signals for workflow control.
args: task: string
exceptions:
- ":::BLOCKED:::"
- ":::NEEDS_HUMAN:::"
use<ext:app> => $app
"""
Work on this task: {$task}
Rules:
- Output :::BLOCKED::: if you need information you don't have
- Output :::NEEDS_HUMAN::: if human judgment is required
- Output :::DONE::: when complete
""" -> $app.prompt() => $result
$result -> while (!.contains(":::DONE:::")) do {
"""
Continue working on: {$task}
Previous progress:
{$}
Remember the signal rules.
""" -> $app.prompt()
} => $final
"Task complete: {$final}" -> logVector Database
Vector database operations for semantic search and RAG workflows. These examples hoist a qdrant extension with use<ext:qdrant> => $qdrant and call $qdrant.method(...). The same script runs against pinecone or chroma by changing the hoisted extension to use<ext:pinecone> or use<ext:chroma> — method signatures match across providers.
RAG Pipeline
Embed query, search similar vectors, format context for LLM.
args: question: string
use<ext:openai> => $openai
use<ext:qdrant> => $qdrant
use<ext:anthropic> => $anthropic
# Generate embedding for the query
$question -> $openai.embed => $query_vector
# Search for similar documents
$query_vector -> $qdrant.search($, [k: 3, score_threshold: 0.7]) => $results
# Extract metadata for context
$results -> fan({ $.metadata.text }) -> .join("\n\n---\n\n") => $context
# Generate answer with retrieved context
"""
Answer this question using the provided context:
Question: {$question}
Context:
{$context}
""" -> $anthropic.promptBatch Upsert with Error Handling
Store multiple documents with partial failure recovery.
args: documents: list
use<ext:openai> => $openai
use<ext:qdrant> => $qdrant
# Embed all documents
$documents -> fan({
[
id: $.id,
vector: $.text -> $openai.embed,
metadata: [title: $.title, source: $.source]
]
}) => $items
# Batch insert with error handling
$items -> $qdrant.upsert_batch => $result
# Check for partial failure
$result.failed -> .empty -> !$ ? {
# Partial failure occurred
"Batch failed at {$result.failed}: {$result.error}" -> log
"Successfully stored {$result.succeeded} vectors before failure" -> log
error "Batch upsert incomplete"
} ! {
# Full success
"Successfully stored {$result.succeeded} vectors" -> log
}Collection Lifecycle Management
Create, populate, and manage vector collections.
use<ext:openai> => $openai
use<ext:qdrant> => $qdrant
# Create a new collection
$qdrant.create_collection("knowledge_base", [
dimensions: 1536,
distance: "cosine"
]) => $create_result
"Created collection: {$create_result.name}" -> log
# Store vectors (assumes $docs defined)
$docs -> fan({
[
id: $.id,
vector: $.text -> $openai.embed,
metadata: [title: $.title]
]
}) -> $qdrant.upsert_batch => $upsert_result
# Verify collection state
$qdrant.describe() => $info
"Collection has {$info.count} vectors with {$info.dimensions} dimensions" -> log
# List all collections
$qdrant.list_collections() => $collections
$collections -> seq({ $ -> log })
# Clean up when done
# $qdrant.delete_collection("knowledge_base")Tool Loop Integration
Vector search as an LLM tool within $anthropic.tool_loop.
---
args: user_query: string
---
use<ext:openai> => $openai
use<ext:qdrant> => $qdrant
use<ext:anthropic> => $anthropic
# Define search tool with closure annotation
^("Search the knowledge base for relevant information")
|^("Search query text") query: string| {
$query -> $openai.embed -> $qdrant.search($, [k: 5]) -> fan({
"ID: {$.id}\nScore: {$.score}\nContent: {$.metadata.text}"
}) -> .join("\n\n---\n\n")
} => $search_knowledge_base
# Define store tool with closure annotation
^("Store a new document in the knowledge base")
|^("Document ID") id: string, ^("Document text") text: string, ^("Document title") title: string| {
[
id: $id,
vector: $text -> $openai.embed,
metadata: [title: $title, text: $text]
] => $item
$item.vector -> $qdrant.upsert($item.id, $, [title: $item.metadata.title])
"Stored document {$item.id}"
} => $store_document
# Run tool loop with dict-form tools
$anthropic.tool_loop(
"Answer the user's question. Use search_knowledge_base to find relevant information. If the user provides new information to remember, use store_document.",
[
tools: [search_knowledge_base: $search_knowledge_base, store_document: $store_document],
max_turns: 10,
user_message: $user_query
]
) => $loop_result
$loop_result.contentSee Also
| Document | Description |
|---|---|
| Stream and Time-Domain Examples | Stream consumption, error recovery, and time-domain operators |
| Guide | Getting started tutorial |
| Cookbook | Reusable design patterns (state machines, dispatch, accumulators) |
| Troubleshooting | Common mistakes and fixes |
| Reference | Language specification |