Memory and behavior, committed together.
Svit is a research-stage Rust runtime for agents that need durable state and reusable code. It keeps structured memory, named Svit Lisp scripts, inbox state, buffered message intents, and runtime metadata in one serializable process. Every activation runs against a bounded working copy and either commits one complete next version or commits nothing.
One Svit owns one reason/act loop, one durable conversation thread, and one
serializable Process. The host chooses a Reasoner, mounts, and ports;
Everruns implements the current loop
behind the Svit API.
Important
Svit is runnable and tested, but it has no stable release and is not a proven hostile multi-tenant isolation boundary. Production use with untrusted code still needs an outer Wasm or OS process boundary.
- One process space. Memory, scripts, queues, metadata, and mounted resources use one absolute-path interface rather than unrelated agent tools.
- Atomic activations. Memory, script, and buffered message changes commit together. Syntax, runtime, validation, conversion, and limit failures roll back the complete activation.
- Durable reasoning. With persistence, process transactions and paged events survive restarts without materializing the full thread in every snapshot.
- Portable state. Processes can be snapshotted, restored, inspected, and forked into independently mutable children.
- Explicit authority. Guest Lisp has no ambient filesystem, network, environment, process, module loader, clock, randomness, or native-extension access. Hosts attach external authority through typed mounts and ports.
- Observable change. Commits report the paths they changed, while committed nodes and roots have structural content hashes for precise cache validation.
Create a Rust application and add Svit while its public API is still changing:
cargo new svit-quickstart
cd svit-quickstart[dependencies]
svit = { git = "https://github.com/everruns/svit", branch = "main" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }Replace src/main.rs with:
use svit::{Message, OpenAI, Reasoner, Svit, value};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut svit = Svit::builder("svit://local/quickstart")?
.memory("facts", value!({}))
.instructions(
"Write requested durable facts to the exact process path before replying.",
)
.reasoner(Reasoner::new("gpt-5.6-terra", OpenAI::from_env()?))
.build()
.await?;
let inbox = svit.inbox();
let mut outbox = svit.outbox();
svit.start()?;
inbox
.send(Message::user(
"Write blue to /memory/facts/release_color, then confirm it.",
))
.await?;
let reply = outbox.recv().await?;
drop(inbox);
svit.block().await?;
println!("{}", reply.text().unwrap_or_default());
println!("stored={:?}", svit.read("/memory/facts/release_color")?);
Ok(())
}Run it with an OpenAI API key:
OPENAI_API_KEY=... cargo runInbox::send commits a message before waking the loop. Outbox publishes
completed assistant messages. Events publishes committed path changes,
canonical conversation events, derived messages, and sanitized terminal
failures. Hosts inspect state through owned reads; they never receive a mutable
reference to the process tree.
For a complete live example, clone this repository and run the process-owned support agent:
OPENAI_API_KEY=... cargo run --locked -p svit-support-agent-svitHost
├── Reasoner
├── Inbox ─────────────┐
├── Outbox <───────────┤
├── Events <───────────┤
├── Ports │
└── Mount providers │
v
Svit
reason/act loop + thread
│
v
Process
state + scripts + limits
transactions + snapshots
The memory tree is the complete guest-visible namespace below /, not just the
/memory node:
/
├── thread/ bounded durable session metadata
├── memory/ durable application values
├── lib/ named Svit Lisp scripts
├── ports/ manuals for host-attached ports
├── inbox/ durable local input queue
├── mounts/ virtual host resources under explicit grants
├── tasks/ reserved in the current slice
├── children/ reserved in the current slice
└── system/ identity, API, limits, lineage, runtime, and outbox metadata
Rust callers, model tools, and Svit Lisp use the same path vocabulary:
discover(path) list immediate children
read(path) read one value
stat(path) inspect kind, access, locality, source, and content facts
write(path, value) commit a memory, script, or granted mount write
remove(path) commit a removal
exec(path, input) run a named /lib script
The model-facing exec tool can also run transient Svit Lisp source. A fresh,
restricted interpreter runs each activation. Successful activations validate
and commit memory, scripts, and buffered message intents once; failed
activations leave the process version and committed root unchanged.
External effects have a narrower guarantee. Port calls happen immediately and cannot be rolled back. Granted mount writes are delayed until process validation succeeds, but the external source cannot join the process transaction.
The default persistence-turso feature provides local Turso persistence. One
canonical ProcessTransaction stream records process mutations; a separate
paged EventLog retains conversation history. Resume verifies transaction
versions, hashes, mutations, and resulting root hashes without rerunning guest
code.
use svit::{OpenAI, Process, Reasoner, Svit, TursoProcessStore};
async fn build_persisted() -> Result<Svit, Box<dyn std::error::Error>> {
let store = TursoProcessStore::open("svit.db").await?;
let process = Process::builder("svit://local/persisted/demo")?.build()?;
let durable = store.create(process).await?;
Ok(Svit::persisted(durable)?
.reasoner(Reasoner::new("gpt-5.6-terra", OpenAI::from_env()?))
.build()
.await?)
}Use store.resume(address) to reopen a process. Snapshots preserve canonical
process state and thread metadata. Durable forks share an immutable history
prefix at the fork boundary and then commit independently; process-only forks
start a fresh child session.
| Feature | Purpose |
|---|---|
persistence-turso |
Local transactions, snapshots, resume, forks, queries, and history cuts |
turso-mount |
A bounded host-selected Turso query exposed as a virtual mount |
Use --no-default-features for the adapter-neutral runtime and persistence
contracts.
Ports are host-owned async capabilities. Ports::new() grants none. Add each
port deliberately and attach the resulting registry when building Svit:
use svit::{
HttpAllowlist, OpenAI, Ports, Reasoner, ReqwestHttpTransport, Svit,
};
let reasoner = Reasoner::new("gpt-5.6-terra", OpenAI::from_env()?);
let ports = Ports::new()
.http(
HttpAllowlist::new().allow("https://api.github.com/"),
ReqwestHttpTransport::new()?,
)
.llm(reasoner.clone())
.spawn(reasoner.clone());
let svit = Svit::builder("svit://local/explicit-ports")?
.reasoner(reasoner)
.ports(ports)
.build()
.await?;Here http can reach only the allowlisted origin and its path descendants,
llm uses the selected reasoner for nested model calls, and spawn uses it for
child Svit turns. A research host that intentionally accepts any HTTP(S)
destination must call http_unrestricted by name. Omit any registration the
process should not receive. Port descriptors appear under /ports, but
descriptors never carry authority and snapshots never serialize port
implementations.
Mounts project host-selected folders or values below /mounts without copying
their contents into the committed root. The root stores only a descriptor;
nodes resolve lazily through a host-owned provider. Providers are never
serialized, so a restored process fails closed until the host reattaches them.
Lampa is the interactive reference host for one persisted Svit:
OPENAI_API_KEY=... cargo run --locked -p lampaLampa shows the conversation beside the complete memory tree, mounts the current
directory read-only at /mounts/cwd, and persists each instance in its own
database. It explicitly registers unrestricted http plus model-backed llm
and spawn ports as a research host. Reuse an instance name to resume it:
OPENAI_API_KEY=... cargo run --locked -p lampa -- --instance research-oneUse --mount name=path or --mount-rw name=path to attach folders and
LAMPA_DATA_DIR to select the storage root.
Implemented now:
- process-owned reasoning with a durable local inbox, thread, and outbox;
- transactional memory and named Svit Lisp scripts;
- bounded values, execution, diagnostics, snapshots, restore, and forks;
- local Turso persistence with validated transaction replay;
- lazy folder, value, and materialized-query mounts;
- explicit host ports and pure local
jqandsearchfunctions; - VAST version preconditions, conflicts, and bounded retry receipts;
- deterministic examples and adversarial invariant tests.
Not implemented:
- remote message delivery, scheduling, timers, retries, or global routing;
- authenticated process identity, authorization, or secrets;
- distributed ownership, migration, or durable control receipts;
- exactly-once external effects;
- production Wasm/OS isolation or formal hostile-tenant isolation evidence.
The public vision describes the broader research direction, not functionality already promised by this implementation.
Svit validates persistent values and snapshots, enforces configured limits, uses a fresh restricted interpreter for every activation, caps diagnostics, and rolls back failed activations. These controls are executable invariants, not a proof of hostile multi-tenancy. Ketos uses wall-clock deadlines and estimated interpreter memory rather than deterministic fuel and an allocator byte cap.
Do not report vulnerabilities in public issues. Follow
SECURITY.md for private reporting and the current support
policy.
| Resource | Purpose |
|---|---|
| Vision | Product model and research direction |
| Examples | Runnable end-to-end scenarios |
| Svit Lisp contract | Versioned guest-language surface |
| Control protocol | VAST semantics and wire contract |
| Security policy | Security model, limitations, and reporting |
| Changelog | Unreleased and released changes |
| Svit skill | Usage guidance for Svit-aware models |
Internal engineering decisions and executable claims live in the OKF v0.2
knowledge/ bundle.
just --list
just build
just test
just examples
just check
just pre-prRead CONTRIBUTING.md and AGENTS.md before
changing runtime behavior. Behavioral and security claims require executable
evidence and the corresponding knowledge update.
Svit is available under the MIT License. See NOTICE for
third-party attribution.
