Open source · agentic sandbox

Agents, contained.

A distributed, stateful runtime for agents and the apps they run in. Sandboxed, policy-checked, and safe for agents to change.

your infrastructure cluster · authenticated nodes policy · every call checked sandbox · lua · wasm · containers agents your app sqlqueueshttpllm one set of functions · one trace
Self-hosted· Sandboxed Lua + WASM· Deny by default· Stateful by design· Open source · MPL-2.0
·   one backend

No tool sprawl.

Your app and its agents share one runtime.

The routes, queues, workflows, and storage your app uses are the same functions agents call as tools.

Typical agent stackWippy
ToolsA connector server per serviceFunctions in the runtime
KeysCopied into every connectorDeclared once, read under policy
NetworkEach finds its own way outChecked per process
AccessWhatever each token allowsOne policy layer, every call

Boundaries, built in.

Policy

Deny by default

Every call is checked. No matching policy, no access.

Sandbox

Code stays in its box

Lua and WASM import only what their entry declares. Agent containers run locked down.

Egress

Network per process

Every dial and request is checked. Route each process direct, through a proxy, or over a tailnet.

Cluster

Nodes prove who they are

Signed handshakes on every connection; gossip is encrypted.

Agents that ship, safely.

Claude Code or Codex change the running system through a scoped surface.

Every change is versioned. Roll back in one call.

wippy · build session
·   actor model

Every agent is an actor.

Private state, one mailbox, nothing shared.

No locks, no races between agents. A crash stays contained, and a supervisor restarts it.

The same actor runs on one node or across the cluster. Durable ones can run on Temporal.

local funcs = require("funcs")

local function main()
    local asks = process.listen("ask", { message = true })
    local history = {}  -- private state, no locks

    while true do
        local msg = asks:receive()
        table.insert(history, msg:payload():data())
        local answer = funcs.call("app:think", history)
        process.send(msg:from(), "reply", answer)
    end
end
·   distribution

Scale your way.

Same code, one node or many.

  • ClusterAdd a node, it joins. Processes are addressed by name.
  • QueuesIn-memory, RabbitMQ, or SQS behind one consumer API.
  • TemporalRun durable work on your Temporal cluster.
  • MeshReach across networks over Tailscale or SOCKS5.
send by name → routed to the owner noderaft proc noderaft proc node proc · · · · gossip membership · · · ·
add a node, it joins · gossip membership · same code near or far

The whole stack, built in.

◆ wippy · one binary MPL-2.0 · self-hosted
Cluster
multi-node · gossip + Raft
Processes
supervised · isolated
Workflows
durable · DAG · Temporal
Registry
typed · versioned · rollback
Storage
SQL · vector · S3 · files
Real-time
WebSocket · SSE · queues
Security
capabilities · policies
Observability
tracing · OpenTelemetry
Lua + WASM
typed · LSP · tests
Networking
per-process egress
LLMs & agents
memory · tools · RAG · MCP
Live edit
change it running · roll back

Your control plane.

Keeper dashboard
keeper · dashboard
Keeper system monitor
keeper · system monitor
Dataflow replay
keeper · dataflow replay

Run it on your infrastructure.

One binary. Your agents and data stay on hardware you control.