Tutorial: Agents
Agents encapsulate AI behavior with scoped capabilities.
What Are Agents?
Agents are a way to organize:
- Tool usage
- Behavior (cells)
- Policy constraints (grants)
- Prompts (roles)
They compile to constructor-backed runtime records with callable methods.
Basic Agent
lumen
agent Greeter
cell greet(name: String) -> String
return "Hello, {name}!"
end
end
cell main() -> String
let greeter = Greeter()
return greeter.greet("World")
endAgent with Tools
lumen
use tool llm.chat as Chat
agent Assistant
use tool llm.chat as Chat
grant Chat
model "gpt-4o"
max_tokens 1024
cell respond(message: String) -> String / {llm}
role system: You are a helpful assistant.
role user: {message}
return Chat(prompt: message)
end
end
cell main() -> String / {llm}
let bot = Assistant()
return bot.respond("Hello!")
endMultiple Methods
lumen
use tool llm.chat as Chat
agent CodeHelper
use tool llm.chat as Chat
grant Chat model "gpt-4o"
cell explain(code: String) -> String / {llm}
role system: You are a code explainer.
role user: Explain this code:\n{code}
return Chat(prompt: code)
end
cell review(code: String) -> String / {llm}
role system: You are a code reviewer.
role user: Review this code for issues:\n{code}
return Chat(prompt: code)
end
cell fix(code: String, issue: String) -> String / {llm}
role system: You are a code fixer.
role user: Fix this issue in the code:\nIssue: {issue}\nCode:\n{code}
return Chat(prompt: "{issue}\n{code}")
end
endScoped Grants
Grants inside an agent are scoped to that agent:
lumen
use tool llm.chat as Chat
agent ConservativeBot
use tool llm.chat as Chat
grant Chat
model "gpt-4o"
max_tokens 100 # Very limited
temperature 0.1 # Very deterministic
agent CreativeBot
use tool llm.chat as Chat
grant Chat
model "gpt-4o"
max_tokens 4000 # More room
temperature 0.9 # More creative
cell main() -> String / {llm}
let conservative = ConservativeBot()
let creative = CreativeBot()
# Each uses its own constraints
let c1 = conservative.respond("Tell me a story")
let c2 = creative.respond("Tell me a story")
return c1 ++ "\n---\n" ++ c2
endAgent with State
lumen
record Conversation
messages: list[String]
end
agent ChatBot
use tool llm.chat as Chat
grant Chat model "gpt-4o"
cell chat(history: Conversation, message: String) -> Conversation / {llm}
role system: You are a helpful assistant.
let updated = history.messages ++ [message]
let response = Chat(prompt: updated)
return Conversation(messages: updated ++ [response])
end
endRole Prompts
Agents can define role prompts:
lumen
agent Expert
cell answer(question: String) -> String / {llm}
role system: |
You are an expert software engineer with 20 years of experience.
Provide detailed, accurate answers with code examples.
Be concise but thorough.
role user: {question}
return Chat(prompt: question)
end
endInheritance Pattern
While Lumen doesn't have agent inheritance, you can compose:
lumen
agent BaseAssistant
cell base_prompt() -> String
return "You are a helpful assistant."
end
end
agent SpecializedAssistant
cell system_prompt() -> String
return "You are a specialized assistant for X."
end
cell respond(message: String) -> String / {llm}
role system: {system_prompt()}
role user: {message}
return Chat(prompt: message)
end
endExample: Invoice Processor
lumen
use tool llm.chat as Chat
record Invoice
vendor: String
amount: Float
date: String
items: list[String]
end
agent InvoiceProcessor
use tool llm.chat as Chat
grant Chat
model "gpt-4o"
max_tokens 2000
cell extract(text: String) -> Invoice / {llm}
role system: |
Extract invoice data from text.
Return JSON with: vendor, amount, date, items.
role user: {text}
let result = Chat(prompt: text)
return parse_invoice(result)
end
cell validate(invoice: Invoice) -> result[Invoice, String]
if invoice.amount < 0
return err("Invalid amount")
end
if length(invoice.vendor) == 0
return err("Missing vendor")
end
return ok(invoice)
end
cell categorize(invoice: Invoice) -> String / {llm}
role system: Categorize this invoice into one of: Office, Travel, Software, Hardware, Services.
role user: Vendor: {invoice.vendor}, Items: {invoice.items}
return Chat(prompt: invoice.vendor)
end
end
cell main() -> String / {llm}
let processor = InvoiceProcessor()
let invoice = processor.extract("ACME Corp - $1,500 - 2024-01-15 - Office supplies")
match invoice
ok(inv) -> return processor.categorize(inv)
err(msg) -> return "Error: {msg}"
end
endBest Practices
- One responsibility per agent — Keep focused
- Use scoped grants — Limit capabilities appropriately
- Document with roles — Clear system prompts
- Validate inputs/outputs — Check before processing
- Handle errors — Use result types
Next Steps