PAL Runtime · the Personal Agentic Layer for builders

Agents that finish, stay contained, and stay yours.

An open-source runtime for the agents you build. Runs that survive a crash, code that runs in a microVM, spend that is capped before the model is called, and a receipt for every run. In your own cloud.

git clone https://github.com/dshakes/lantern.git && cd lantern && make demo

Docker, no API key: the demo replays recorded model answers.

Three outcomes

01 · It finishes

A crash doesn’t start the run over.

Every step is written to the run’s journal as it finishes. If the process dies, a recovery sweep picks the run up again: finished steps come back from the journal, and only the unfinished step runs again.

  • Side effects carry an idempotency key from run, step and attempt, so a retried model call is billed once.
  • A distributed lock makes sure only one worker resumes a run.
Durable execution
Steps 1 and 2 are journaled, the process crashes in step 3, the recovery sweep re-acquires the lock, steps 1 and 2 are replayed from the journal and step 3 runs again with the same idempotency key, so it is billed once.Steps 1 and 2 are journaled, the process crashes in step 3, the recovery sweep re-acquires the lock, steps 1 and 2 are replayed from the journal and step 3 runs again with the same idempotency key, so it is billed once.

02 · It’s contained

Untrusted code runs in a microVM. Keys stay outside.

Agent code runs in a Firecracker or Kata microVM with its own kernel. In broker mode the VM has no network card at all: its only way out is a broker on the host, which checks each request against the allowlist and adds the credential there.

  • Requests to hosts off the allowlist are refused and audited.
  • Injected credentials never enter the VM, its logs or its audit trail.

Broker mode is opt-in and Firecracker-only1.

Egress and secrets
A tool call reaches code in a microVM with no network card. Over vsock it reaches the host broker, which applies the allowlist and adds the key; keys stay on the host. An allowed host goes through, any other host is refused and audited.A tool call reaches code in a microVM with no network card. Over vsock it reaches the host broker, which applies the allowlist and adds the key; keys stay on the host. An allowed host goes through, any other host is refused and audited.

03 · It’s yours

In your cloud, next to your data.

Run the control plane wherever suits you. The data plane runs in your VPC with the sandboxes and the run data. It dials out to the control plane and work comes back down that same connection, so you open no inbound ports.

  • EKS, GKE, AKS or a plain host.
  • Apache-2.0, every line of it.
Architecture
The control plane, run wherever you deploy it, holds the API, console, scheduling and routing. The data plane in your VPC, with microVM sandboxes and run data, dials out to it; runs come back over that connection. No inbound ports.The control plane, run wherever you deploy it, holds the API, console, scheduling and routing. The data plane in your VPC, with microVM sandboxes and run data, dials out to it; runs come back over that connection. No inbound ports.

Budgets

A budget before the first token.

Cap what an agent may spend. Over the cap, the run is refused before the bill, and the model is never called.

A run request meets the budget check (forecast and daily caps). Over the cap it is refused with 402, no model call, costing nothing. Under the cap it is routed by capability and the usage is recorded.A run request meets the budget check (forecast and daily caps). Over the cap it is refused with 402, no model call, costing nothing. Under the cap it is routed by capability and the usage is recorded.
const lantern = new LanternClient({
  baseUrl: "http://localhost:8080",
  apiKey: process.env.LANTERN_API_KEY,
});

await lantern.agents.create({ name: "triage" });
await lantern.budgets.upsert("triage", {
  maxCostUsdPerDay: 25,
  hardFail: true,
});

await lantern.runs.create({ agent: "triage", input });

TypeScript shown; Python and Go SDKs too. Models are named by capability (auto, reasoning-large), never by vendor.

402 Payment RequiredPOST /v1/runs
{
  "error": "agent budget limit reached: daily spend would reach $25.0318 exceeding limit $25.0000",
  "reason": "daily spend would reach $25.0318 exceeding limit $25.0000"
}
No model call is made. The fields and wording are the handler’s; the dollar amounts are an example2.

What you’d otherwise build.

A sandbox is one part. Production agents need the rest, and most teams end up writing it themselves.

Without a runtime

  • A job queue, retry logic and a dedup table so a crash doesn’t double-charge
  • A VM fleet, an egress proxy and a secrets vault for agent code
  • Per-tenant spend metering and a kill switch
  • A model client with provider failover
  • An audit log you can prove nobody edited

With PAL Runtime

  • Durable runs. Journaled steps, crash-resume, idempotency keys.
  • Sandboxes. Firecracker or Kata, egress allowlist, secrets by reference.
  • Budgets. Daily and per-run caps, 402 before the call.
  • Routing. Ask for a capability; failover across providers.
  • Receipts. Signed, verifiable offline.

Security and trust

Built for more than one tenant from day one.

Tenant isolation

Every row carries a tenant, every internal call carries it too, and row-level security policies cover every tenant table3.

Trust boundaries

Internal gRPC ports accept a tenant only from callers holding the service token, and refuse to start in production without it.

Secrets by reference

Code refers to lantern.secret/…; the value is resolved at execution time and never lands in logs, traces or run state.

Signed receipts

A finished run gets an Ed25519-signed receipt over its event journal; anyone can verify it, and any later edit breaks the signature4.

Traced end to end

OpenTelemetry spans on every request and step, tagged with tenant, run and step.

Open to audit

Apache-2.0, Go and Rust, with tests and linters gating every change in CI.

Security model

Measured

Pause an idle agent. Fork a busy one.

An idle sandbox is snapshotted and stopped, giving its compute back, and wakes on the next request. Forks share one memory snapshot instead of copying it.

634ms

to snapshot a 128 MiB sandbox

138ms

to restore it

<160ms

per fork, three forks on one snapshot

  1. Indicative: one jailed Firecracker run, 1 vCPU and 128 MiB per VM, nested KVM on an M4 Max laptop, not bare metal. Methodology →

Proof, not promises

pal runs on PAL Runtime.

The personal agent we use every day runs on the same layer. If it is good enough to answer for us, it is ready to run your agents.

  • Apache-2.0
  • Firecracker / Kata microVMs
  • Go + Rust
  • Tests in CI
git clone https://github.com/dshakes/lantern.git && cd lantern && make demo
  1. 1.Without broker mode the allowlist is enforced inside the VM by a proxy, and secrets you vend to the workload do enter the guest. Full comparison.
  2. 2.Enforced today: per-agent daily cost, runs and tokens, and a tenant-wide daily cost cap. Workflow runs also stop mid-run at a per-run cap and at per-tool limits.
  3. 3.Policies are in place on every tenant table; enforcement is switched on per environment.
  4. 4.Ed25519 once a signing key is configured; development falls back to HMAC.