Agents and tools
Run bounded tool loops with typed inputs, callbacks, and recoverable tool errors.
Lisp·LLM primitives·Rust runtime
Sema is a Scheme-like Lisp with built-in agents, typed tools, budgets, replay, and tracing. It runs on a Rust bytecode VM and builds to one standalone executable.
MIT · macOS, Linux, and Windows
The defining difference
Model calls, tools, conversations, and agents are language values. The runtime owns the repetitive work around them, so the source stays focused on the program you meant to write.
deftool connects a description and input schema to an ordinary Sema function. defagent declares the prompt, tools, and turn limit; agent/run handles calls and tool results. llm/with-budget. (deftool get-weather
"Get weather for a city"
{:city {:type :string}}
(lambda (city)
(http/get f"https://weather.test/${city}")))
(defagent guide
{:system "Give a short forecast."
:tools [get-weather]
:max-turns 3})
(llm/with-cassette
"weather.jsonl" {:mode :auto}
(lambda ()
(llm/with-budget
{:max-cost-usd 0.10}
(lambda ()
(agent/run guide
"Weather in Oslo?")))))The language
Sema keeps Scheme's lexical scope, functions, macros, and tail calls, then adds the data forms people expect in current programs.
(define tickets
[{:id 101 :priority :high}
{:id 102 :priority :low}])
(define urgent-ids
(->> tickets
(filter
#(equal? (:priority %) :high))
(map :id)))
(match urgent-ids
([] "nothing urgent")
([id & _] f"start with ticket ${id}"))sema binary. The runtime, in one screen
These forms wrap ordinary functions. They compose, nest, and clean up when the scope exits.
(llm/with-budget limits f)cap tokens or known-price cost for a block(llm/with-cache {:ttl 3600} f)reuse responses during development(llm/with-cassette path opts f)record and replay provider traffic(llm/with-fallback providers f)try an ordered provider chain(with-span "ingest" attrs body...)emit OpenTelemetry spans around a run(checkpoint :result value)journal work and resume completed phasesWhat it is for
Start with a script. Add tools, structure, persistence, or an interactive notebook without changing the language or runtime.
Run bounded tool loops with typed inputs, callbacks, and recoverable tool errors.
Turn unstructured model output into validated maps, lists, and scalar values.
Split long work into phases, record checkpoints, bound fan-out, and resume a run.
Develop in shared-state cells, inspect rich output, then run the same code as a script.
Then ship it
sema build traces imports, bundles declared assets, and writes a standalone executable. The target machine does not need Sema, Cargo, or another language runtime.
$ sema build weather.sema -o weather
traced imports and bundled assets
built ./weather
$ scp weather server:
$ ssh server ./weather Oslo
runs without a Sema installationProvider choice
Sema auto-configures providers from environment variables. Your tools, agents, budgets, and traces stay the same whether a run uses a hosted model, a local model, or an ordered fallback chain.
See all providers(llm/with-fallback
[:anthropic :openai :ollama]
(lambda ()
(agent/run guide question)))Start with one file
Try it in the browser, follow the quickstart, or give the concise language guide to your coding agent.