Surfaces
The three ways to talk to an agent โ TUI, dashboard, and the daemon's RPC API.
The same daemon serves three surfaces, backed by the same agents and sessions. You can start a conversation in one and finish it in another; async jobs spawned in either show up in both.
TUI โ otters chat
Terminal-first. Full streaming, keyboard-driven, with slash commands:
/quit,/clear,/help,/session/jobs [status]โ async jobs in this chat session/job <id>โ full state + tail of stdout/stderr/cancel <id>โ cancel a running job
A bottom-bar strip shows running jobs scoped to the session (updated
every 2 s). In-flight tool calls grow a live log preview when the
model is mid-job_watch / job_wait / job_status so you can see
what the model is seeing.
otters prompt <name> "..." is the one-shot variant for scripts and
pipelines โ same agent, streams the reply to stdout, exits.
Dashboard โ browser UI
The daemon ships a browser dashboard on the HTTP port. otters info
prints the URL (default http://127.0.0.1:5500). The dashboard surfaces:
- Image catalog โ every agent image in the local store, with a
run-from-image dialog that lets you override
MODELand everyENVwithout an Agentfile edit. Per-version Run button on the image-detail page does the same per tag. - Async jobs โ
/jobs/<id>streams live stdout / stderr. The chat view inlines a log preview under each running async tool call. - Chat โ same conversation model as the TUI. Sessions are shared.
Agents that need configuration at start-up (auth tokens, base URLs)
are easiest to launch from the dashboard: pick the image card, hit
Run, fill the ENV overrides in the dialog.
Programmatic โ Connect/gRPC API
Each surface above is a thin client over the daemon's Connect/gRPC API. For embedding agents in another Go program, two entry points:
pkg/agentโ the runtime SDK. Wraps the daemon RPCs in a typed Go API. Stream tokens, observe tool calls, inject context.- Direct Connect/gRPC โ when you're not in Go, or when the SDK's shape doesn't fit. Schema lives in openotters/openotters/api.
Per-agent authentication is a JWT minted by the daemon at agent-create time. See agent-scoped JWTs for the auth model.
Sessions are shared
Every conversation has a stable session id. otters chat mints
cli:chat:<uuid>; the dashboard's New session button mints
gui:chat:<uuid>. Both end up labelled the same way on every async
job they spawn, so otters jobs ls filters cleanly across both
surfaces.