omi-cli is built so an LLM-driven harness can drive it without a wrapper
layer. This page documents the stable contract.
The JSON contract
Pass--json (a global flag, before the subcommand) and the CLI behaves
like a strict tool:
- stdout receives a single JSON document and only a JSON document. No spinners, no progress messages, no decorative output.
- stderr receives any error as a JSON object:
{"error": "...", "detail": "..."}. - exit code signals what happened.
Exit codes
These codes are part of the contract — they won’t shift between minor
versions. Branch on them in your harness without parsing English errors.
Authentication: API key vs browser OAuth
The CLI supports both — but for agents specifically, the API-key path is almost always the right call:
API keys are long-lived, scoped, and don’t need a browser — perfect for
agents. The browser OAuth flow exists for humans on a laptop, uses a
loopback callback with PKCE, and stores short-lived Firebase ID tokens that
auto-refresh between calls.
omi auth login so a malformed value still fails fast with exit 1.
Retry behavior
Transient failures are retried automatically before the CLI surfaces an error:- 5xx — exponential backoff with jitter (initial 0.5s, cap 8s).
- 429 — honors the server’s
Retry-Afterheader when present (capped at 60s so a misconfigured upstream can’t pin your agent forever); falls back to jitter otherwise. TheRetry-Aftercap means a 429 with a one-hour hint becomes a one-minute wait — your agent gets exit4quickly enough to decide whether to back off itself. - Transport errors (DNS failures, dropped TCP) — retried up to 4 attempts.
detail field for rate-limit errors looks like:
dev:conversations, dev:memories, dev:memories_batch)
matches the backend’s rate-limit policy IDs so you can map them to your own
backoff strategies.
Worked example: Python harness
Handling rate limits in your harness
Tips
- One JSON document per invocation. Don’t try to stream — the CLI doesn’t emit incremental output. Run it again for the next page.
- Use
--profileto isolate environments. A staging profile + a prod profile saves you from accidentally writing to prod with a test script. - Use
--api-base http://localhost:8080for local backend testing. --verboseis safe in JSON mode. Debug output goes to stderr, stdout stays valid JSON.- Pipe stdin with
--text -foromi conversation create— handy when the content is generated by another tool and you don’t want to shell-escape it.