Examples
Learn Sigil through real-world code examples. Each example demonstrates key concepts and best practices.
Hello World
The simplest Sigil program:
fn main() {
let message! = "Hello, World!"
println(message)
}
Note the ! marker — it indicates that message is known data (computed locally).
Evidentiality Basics
Sigil tracks where data comes from. Here's how evidence markers propagate:
// Known: computed locally
let local! = 42
// Reported: from external source
let external~ = api.fetch("/data")
// Uncertain: might be absent
let maybe? = database.find(id)
// Combining evidence levels
let result~ = local + external // ! + ~ = ~
// Validation promotes evidence
let trusted! = external |validate!{ verify_signature() }
Morpheme Operators
Greek letter operators for data transformation:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// Filter (φ), transform (τ), reduce
let result = numbers
|φ{. % 2 == 0} // keep even: [2, 4, 6, 8, 10]
|τ{. * 2} // double: [4, 8, 12, 16, 20]
|Σ // sum: 60
// Sort (σ)
let sorted = users |σ·by{.name}
// First (α) and last (ω)
let first? = users |α
let last? = users |ω
Safe API Client
A type-safe HTTP client that enforces validation of external data:
struct User {
id: Uuid,
name: Str,
email: Email,
role: Role,
}
struct ApiClient {
base_url: Url!,
auth_token: Str!,
}
impl ApiClient {
// Returns reported data - caller must validate
async fn get_user(&self, id: Uuid) -> Result<User~> {
let response~ = http::get("{self.base_url}/users/{id}")
.header("Authorization", "Bearer {self.auth_token}")
.await?;
let user~: User~ = response.json()?;
Ok(user)
}
// Returns validated data - safe to use
async fn get_verified_user(&self, id: Uuid) -> Result<User!> {
let user~ = self.get_user(id).await?;
// Validate all fields
let verified! = user |validate!{
.id.is_valid() &&
.name.len() > 0 &&
.email.is_valid() &&
.role.is_known()
};
Ok(verified)
}
}
// Usage
async fn process_user(client: &ApiClient, id: Uuid) {
// This won't compile - can't use reported data directly
// let user~ = client.get_user(id).await?;
// database.insert(user); // ERROR: expected User!, got User~
// This works - data is verified
let user! = client.get_verified_user(id).await?;
database.insert(user); // OK: User!
}
Form Validation
Safe handling of user input with progressive validation:
struct RegistrationForm {
email: Str,
password: Str,
confirm_password: Str,
}
struct ValidatedRegistration {
email: Email!,
password_hash: Hash!,
}
fn validate_registration(form: RegistrationForm~) -> Result<ValidatedRegistration> {
// All form data is reported (user input)
let email~ = form.email;
let password~ = form.password;
let confirm~ = form.confirm_password;
// Validate email format
let valid_email? = email |validate?{ Email::parse(.) };
let email! = valid_email.ok_or(Error::InvalidEmail)?;
// Validate password requirements
let password! = password |validate!{
.len() >= 12 &&
.contains_uppercase() &&
.contains_number() &&
. == confirm
}.ok_or(Error::WeakPassword)?;
// Hash password (produces known data)
let hash! = crypto::hash(password);
Ok(ValidatedRegistration {
email,
password_hash: hash,
})
}
Data Pipeline
Processing data from multiple sources with evidence tracking:
struct SalesReport {
total: Decimal,
by_region: Map<Region, Decimal>,
confidence: Float,
}
async fn generate_report(date_range: DateRange!) -> SalesReport! {
// Fetch from multiple sources (all reported)
let db_sales~ = database.query_sales(date_range).await;
let api_sales~ = external_api.get_sales(date_range).await;
let csv_sales~ = import_csv("manual_entries.csv").await;
// Validate each source
let db_validated! = db_sales |validate!{ verify_db_integrity(.) };
let api_validated? = api_sales |validate?{ verify_api_response(.) };
let csv_validated? = csv_sales |validate?{ verify_csv_format(.) };
// Merge with evidence-aware aggregation
let all_sales = [db_validated, api_validated, csv_validated]
|φ{.is_some()}
|τ{.unwrap()};
// Calculate totals
let total! = all_sales |τ{.amount} |Σ;
let by_region! = all_sales
|group_by{.region}
|τ{(region, items) => (region, items |τ{.amount} |Σ)};
// Confidence based on data completeness
let sources_valid = [api_validated.is_some(), csv_validated.is_some()];
let confidence! = 0.6 + (sources_valid |φ{.} |count) * 0.2;
SalesReport { total, by_region, confidence }
}
Simple Agent
A basic agent with tool use:
agent Calculator {
execution: Daemon {
tools: [Tool::Calculator],
}
}
impl Calculator {
fn process(&self, query: Str~) -> Result<Str!> {
// Parse expression (reported input)
let expr? = Expression::parse(query)?;
// Evaluate (produces known result)
let result! = self.tools.calculator.eval(expr);
Ok("Result: {result}")
}
}
Agent with Memory
An agent that remembers past interactions:
agent PersonalAssistant {
memory: Engram {
instant: 4096,
episodic: true,
semantic: true,
},
learning: Gnosis {
adaptation_rate: 0.1,
}
}
impl PersonalAssistant {
async fn respond(&mut self, message: Str~) -> Str! {
// Check for similar past interactions
let context? = self.engram.episodic
|φ{.similarity(message) > 0.7}
|σ·by{.relevance}
|α;
// Generate response with context
let response! = match context {
Some(past) => self.generate_with_context(message, past),
None => self.generate_fresh(message),
};
// Store interaction for future reference
self.engram.store_episode(Episode {
input: message,
output: response.clone(),
timestamp: Time::now(),
});
response
}
}
Multi-Agent System
Multiple agents collaborating on a research task:
agent Researcher {
execution: Daemon { tools: [Tool::WebSearch, Tool::FileSystem] },
communication: Commune,
}
agent Analyst {
memory: Engram { semantic: true },
planning: Omen,
communication: Commune,
}
agent Writer {
subjectivity: Anima { personality: "clear, concise" },
communication: Commune,
}
async fn research_project(topic: Str~) -> Report! {
// Create agent swarm
let researcher = Researcher::new();
let analyst = Analyst::new();
let writer = Writer::new();
// Research phase
researcher ! Message::Task { action: "research", topic };
let findings~ = researcher ? Message::Result;
// Analysis phase
analyst ! Message::Task { action: "analyze", data: findings };
let analysis~ = analyst ? Message::Result;
// Writing phase
writer ! Message::Task { action: "write", content: analysis };
let draft~ = writer ? Message::Result;
// Validate final output
let report! = draft |validate!{
.word_count() >= 500 &&
.citations.len() > 0 &&
.has_conclusion()
};
report
}