---
name: harbor-orbit
user-invocable: false
description: Provides workspace-scoped runtime primitives (`hrbr.storage`, `hrbr.cache`, `hrbr.db`, `hrbr.ai`, `hrbr.tools`, `hrbr.jobs`, and app-handler `hrbr.state`) inside Harbor exec, jobs, and apps. Use this before saying you cannot persist, query, cache, hold app state, or invoke reusable jobs — Harbor's `hrbr` global is the path. Never store secrets / API keys / PII in any workspace primitive.
---

# Harbor Orbit Runtime

## Index

1. Use When / Do Not Use When: choose runtime primitives instead of product lifecycle APIs.
2. Information Spec: exact `hrbr.*` namespaces inside exec, jobs, and app handlers.
3. Behavior Contract: storage/cache/db/state/tool/AI selection rules.
4. Canonical Sequence: CLI snippets for one-off exec verification.
5. Minimal Examples: storage and cache patterns.
6. Appendix: how Orbit relates to `defineJob({...})`, `deployApp({...})`, and `cli-mcp`.

## Use when

- The agent needs to save a generated artifact (report, summary, JSON, markdown) the workspace can fetch later.
- The agent needs short-lived memoized state across runs (research cache, last-digest, run breadcrumbs) — always with a TTL.
- The agent needs structured queryable workspace records (`hrbr.db.*`).
- The agent needs to discover Harbor tools from inside a run (`hrbr.tools.*`).
- The agent needs Harbor-managed AI inference (`hrbr.ai.run`, `hrbr.ai.embed`, `hrbr.ai.classify`).
- The agent needs a shareable/signed URL for a stored artifact (`hrbr.storage.url`).
- The agent is authoring a deployApp direct route handler and needs app-local hot/session state (`hrbr.state.*`).

## Do not use when

- The user wants to call a third-party SaaS source — see `harbor-plugins`.
- The user wants product lifecycle work outside one-off execution.
- The user wants a routed UI.
- The user wants broad local filesystem or local CLI control.
- The agent wants to put API keys, credentials, OAuth tokens, or PII in storage / cache / db. Never.

## Information spec

The actual `hrbr.*` runtime surface available inside `hrbr exec` and published jobs:

```txt
   namespace        methods                                            notes
   ─────────        ───────                                            ─────
   hrbr.storage     put(key, body, opts), get(key), list({prefix}),    durable workspace files
                    delete(key), url(key)                              url() returns a shareable link
   hrbr.cache       set(key, value, ttl_seconds), get(key),             short-lived exec/job memoization
                    delete(key)                                         TTL defaults to 3600s; pass it explicitly
   hrbr.db          query(sql, params), exec(sql, params),              workspace-scoped SQL
                    first(sql, params), batch(statements)
   hrbr.tools       search(query, opts), describe(tool_id),             in-run discovery
                    namespaces()
   hrbr.ai          run(model, input), generate(input), summarize,      Harbor-managed access
                   embed, classify, rerank, models(opts)
   hrbr.jobs        <camelJobName>(input)                               invoke reusable jobs
   hrbr.state       get(key), set(key, value, opts), append, delete     app-handler hot state only
```

`hrbr` is the canonical workspace-scoped runtime global. `orbit.*` remains
a legacy alias for older exec/job primitive snippets, and top-level `jobs.*`
remains a legacy alias for `hrbr.jobs.*` promoted job invocation.
`hrbr.state` is available inside app-local deployApp route handlers, not one-off
exec or reusable job runs. There is no `hrbr.workspace.*`, `hrbr.apps.*`,
`hrbr.usage.*`, or `hrbr.health.*` runtime namespace. Product lifecycle APIs
live outside the exec runtime; never write `hrbr.jobs.create(...)`,
`hrbr.jobs.publish(...)`, `hrbr.apps.publish(...)`, or `orbit.jobs.publish(...)`
inside exec.

Reusable job and app creation use authoring surfaces, not runtime namespaces:
write one top-level `defineJob({...})` or `deployApp({...})` file and publish
it through `hrbr exec -f`. Runtime code can invoke
existing jobs through `hrbr.jobs.<name>(input)`.

`hrbr.cache.set` accepts an optional `ttl_seconds` argument and the runtime defaults omitted TTL to 3600 seconds, but agents should pass TTL explicitly. Cache is for short-lived state, not persistence. Runtime bounds are 60 seconds minimum and 30 days maximum; if the agent is tempted to use a longer lifetime, stop and pick `hrbr.storage` or `hrbr.db` instead.

`hrbr.storage` is the only durable artifact store. Pass `content_type` on `put` so consumers can read MIME-typed content. Use `hrbr.storage.url(key)` for shareable links instead of returning raw bytes. Use `hrbr.storage.list({ prefix })` to enumerate saved artifacts.

## Behavior contract

1. **Pick the smallest right primitive.** Storage for durable artifacts. Cache for short-lived exec/job memoization (TTL). DB for queryable rows. State for app hot/session state. AI for inference. Tools for in-run discovery.
2. **TTL every cache set.** `hrbr.cache.set(key, value, ttl_seconds)` — pass a positive integer TTL explicitly, between 60 seconds and 30 days. Omitted TTL defaults to 3600 seconds at runtime, but explicit TTL keeps agent intent clear.
3. **Never store secrets.** Do not put API keys or machine credentials, OAuth tokens, or PII in any workspace primitive. Use Harbor's encrypted credential/source setup instead.
4. **Do not invent namespaces.** If the agent considers `hrbr.workspace.list()`, `hrbr.jobs.publish(...)`, or `hrbr.apps.route(...)` inside exec — stop. Those lifecycle APIs do not exist in exec. Use `hrbr inspect` for control-plane reads and `hrbr exec -f <file>` for `defineJob({...})` / `deployApp({...})` authoring.
5. **Return compact results.** Don't return entire blob bodies; return keys, urls, or counts. After `hrbr.storage.put`, follow with `hrbr.storage.list({ prefix })` or return the `url()` so the caller can verify.
6. **For app hot paths, choose one app responsibility per route.** Use `hrbr.state` for app-local UI/session state. Use `hrbr.db`, `hrbr.storage`, `hrbr.ai`, `hrbr.tools`, or job-backed routes for workspace work. Do not mix `hrbr.state` with workspace primitives in the same app handler; split routes or move workspace work into a job.

## Canonical sequence

```bash
# Storage: write + list (verify the artifact is saved)
hrbr exec '
await hrbr.storage.put("reports/summary.json", JSON.stringify({ ok: true }), { content_type: "application/json" });
return await hrbr.storage.list({ prefix: "reports/" });
'

# Storage: shareable URL
hrbr exec 'return await hrbr.storage.url("reports/summary.json", { expires_in: 3600 })'

# Cache with TTL (TTL is required)
hrbr exec '
await hrbr.cache.set("digest:last-run", { at: new Date().toISOString() }, 300);
return await hrbr.cache.get("digest:last-run");
'

# DB query
hrbr exec 'return await hrbr.db.query("select id, title from notes where archived = ? limit 10", [false])'

# AI inference
hrbr exec 'return await hrbr.ai.run("@cf/meta/llama-3-8b-instruct", { prompt: "Summarize Harbor in one sentence." })'

# In-run tool discovery
hrbr exec 'return await hrbr.tools.search("create issue")'

# App route runtime primitives live inside deployApp route handlers, not top-level exec.
# See harbor-apps for the full deployApp({...}) app route example.
```

## Minimal examples

Save a report and confirm it is listed:

```bash
hrbr exec '
const key = "reports/weekly-" + new Date().toISOString().slice(0,10) + ".md";
await hrbr.storage.put(key, "# Weekly\n\nAll green.", { content_type: "text/markdown" });
const listed = await hrbr.storage.list({ prefix: "reports/" });
const url = await hrbr.storage.url(key, { expires_in: 3600 });
return { key, url, count: listed.length };
'
```

Memoized research with TTL fallback:

```bash
hrbr exec '
const cached = await hrbr.cache.get("research:harbor");
if (cached) return { source: "cache", cached };
const fresh = await exaMcp.webSearchExa({ query: "Harbor execution layer", numResults: 5 });
await hrbr.cache.set("research:harbor", fresh, 600);
return { source: "fresh", count: fresh.results?.length ?? 0 };
'
```

## Appendix: Authoring Surfaces

Orbit is the runtime primitive set. It is not the lifecycle surface.

- Use `harbor-exec` for one-off traced TypeScript that can call `hrbr.storage`, `hrbr.cache`, `hrbr.db`, `hrbr.ai`, `hrbr.tools`, and `hrbr.jobs`.
- Use `harbor-jobs` for `defineJob({...})` files. Job `run(input)` code may use Orbit primitives, and created jobs are invoked through `hrbr.jobs.<camelName>(input)`.
- Use `harbor-apps` for `deployApp({...})` files. App route handlers choose one responsibility per route: app-local `hrbr.state`, workspace primitives, static HTML, or declared job calls.
- Use `hrbr inspect` or `cli-mcp` `inspect` for auth, workspace, source, tool, app, and job control-plane inspection.

`cli-mcp` has the same separation at the protocol level: it exposes one
`inspect` tool for control-plane code and one task-backed `exec` tool for
Harbor Cloud execution. Individual `hrbr.*` inspect helpers are methods behind
`inspect`, not separate MCP tools. Likewise, Orbit primitives are methods
behind the runtime `hrbr` global, not lifecycle APIs.

## Done criteria

- Every `hrbr.cache.set` call passes an explicit `ttl_seconds` between 60 seconds and 30 days. No omitted, zero, or null TTLs in agent-authored examples.
- Every `hrbr.storage.put` call passes `content_type`, and writes are verified via `hrbr.storage.list({ prefix })` or `hrbr.storage.url(key)`.
- The agent did not invent `hrbr.workspace.*`, `hrbr.jobs.publish/create`, `hrbr.apps.*`, `hrbr.usage.*`, or `hrbr.health.*` inside exec.
- No API keys, credentials, OAuth tokens, or PII were placed in cache, storage, or db.
- Returned results are compact (keys, urls, counts) — not raw blob bodies.
- App handlers are measured with `x-hrbr-app-duration-ms` and
  `x-hrbr-app-dispatch-ms` before claiming performance wins.
