Orbit Runtime (Beta)
Workspace primitives: storage, cache, db, AI, tool discovery, sockets.
Beta
This surface is in beta. Shape and limits may shift before v1. Track changes in the Changelog.
Inside hrbr exec, every Function handler, and every App route, you have
access to the Orbit runtime — the set of workspace primitives Harbor
provides for state, AI inference, structured data, and live updates.
Marketing calls this "Shared Memory". Internally everything is orbit.*.
| Primitive | Purpose | Use when |
|---|---|---|
orbit.storage | Key/value blob store with signed URLs | Save a generated artifact (report, summary, HTML) |
orbit.cache | TTL'd memoized cache | Short-lived state across runs (last-digest, breadcrumbs) |
orbit.db | Structured queryable rows | Workspace records you want to filter/sort |
orbit.ai | Harbor-managed model inference | run, embed, classify |
orbit.tools | Discover Harbor tools mid-run | An agent function deciding which plugin to call next |
orbit.socket | Signed WebSocket URLs + broadcast | Live updates pushed from a job to a viewer |
Never put OAuth tokens, API keys, or PII in orbit.storage, orbit.cache,
or orbit.db. They are workspace-readable. Credentials live in the
encrypted vault, not the runtime primitives.
orbit.storage
// Put + read
await orbit.storage.put("weekly-report.md", body, { contentType: "text/markdown" });
const body = await orbit.storage.get("weekly-report.md");
// Signed URL for sharing
const url = await orbit.storage.url("weekly-report.md", { expiresIn: "7d" });Backed by R2 in Cloud, filesystem in OSS. Signed URLs are workspace-scoped and time-bound.
orbit.cache
// First call computes; subsequent calls within TTL hit the cache
const trending = await orbit.cache.fetch(
"trending-issues",
() => sentryMcp.listIssues({ since: "1d" }),
{ ttl: "10m" },
);Backed by KV in Cloud. Always set a TTL — there's no eviction policy.
orbit.db
// Schema-less per-table rows (workspace-scoped collections)
await orbit.db.feedback.insert({
id: crypto.randomUUID(),
subject: input.subject,
body: input.body,
created: new Date().toISOString(),
});
const recent = await orbit.db.feedback.where({ }).orderBy("created", "desc").limit(50).all();Backed by D1 in Cloud. For now: typed via your handler's input/output, no migrations required. Indexes can be added per-collection in the dashboard.
orbit.ai
const draft = await orbit.ai.run({
model: "anthropic/claude-3.7-sonnet", // or "openai/gpt-4.1", etc.
prompt: `Summarise this Sentry issue:\n${JSON.stringify(issue)}`,
maxTokens: 400,
});
const embedding = await orbit.ai.embed({ text: issue.message });
const verdict = await orbit.ai.classify({
text: issue.message,
labels: ["regression", "flake", "user error"],
});Billed against the workspace plan. Routed through Cloudflare AI Gateway in Cloud; the OSS path needs your own model provider creds (see Open Source → SDK → orbit.ai).
orbit.tools
// Search inside a run — useful when an agent doesn't know which plugin
// to use yet
const tools = await orbit.tools.search("file a ticket about a build failure");
// → [{ tool_id: "linear-mcp.create_issue", description: ..., schema: ... }, ...]Same FTS-backed index the dashboard uses, but available from inside the isolate so an agent can introspect mid-run.
orbit.socket
// In a Function: stream progress updates to a viewer
const ws = await orbit.socket.publish("report-progress");
for (const item of items) {
await processItem(item);
await ws.send({ done: items.indexOf(item) + 1, total: items.length });
}Get a signed WebSocket URL with orbit.socket.url("report-progress").
Useful for App routes that show live progress of a backing Function.
What's not here
orbit.ui— no such thing. The App UI templates are/sdk/orbit, an authoring import for Apps and Functions. They're not available insidehrbr exec. See Apps.