OAra Labs | Docs

Reference

Tokens and the open web API

The daemon serves a REST API and a WebSocket. Both are how Beacon and the iOS app talk to it, and both will answer anyone who can reach the port. One token stands between those two facts, and it is worth knowing exactly what it does before you expose anything.

Check first

oara token show on the daemon's machine answers the only question that matters. Here is what an unprotected install says — verbatim, from a fresh one:

oara token showno token set
oara token show
No web API token is set — the web API is OPEN (no auth).
Set one with: oara token rotate
(env file: ~/.config/prometheus/env, var: PROMETHEUS_API_TOKEN)

It says OPEN rather than something softer, and that is the right word. With no token, anything that can reach port 8005 can drive your agent — read conversations, run tools, start coding runs.

On by default is not open by default web.enabled ships as true, but the daemon mints a PROMETHEUS_API_TOKEN into the env file on first start when none is set. So a normal install is authenticated without you doing anything. The open state above is reachable — by clearing the variable deliberately — and oara token show is how you find out which one you are in.

Setting and rotating

oara token rotatedaemon host
oara token rotate
Generates a new token, writes it to ~/.config/prometheus/env, and prints it once.

Rotating invalidates the old token immediately. Every client holding the old one stops working until you give it the new one, which in practice means Beacon on each machine and the iOS app on each device.

A running daemon may not pick it up A process that read the token from its environment at startup keeps the old value for its lifetime — the operating system gives no way to change a running process's environment. If your deployment sets the token as an environment variable rather than letting the daemon read the env file, a rotation needs a restart. Plan for that before you rotate rather than during.

The two transports authenticate separately

This is the detail that produces confusing half-working states. REST sends the token as a bearer header. The WebSocket sends it in the first frame of the handshake. They are different code paths, and it is entirely possible for one to succeed while the other fails — Beacon's Connection settings panel tests each independently for exactly this reason.

PortWhatAuth
8005REST API — web.api_portBearer header
8010WebSocket — web.ws_portFirst frame of the handshake

If chat loads but nothing streams, suspect the WebSocket. If nothing loads at all, suspect REST or the address itself.

Where the token lives

~/.config/prometheus/env, mode 0600, on the daemon's machine. Not in prometheus.yaml — that file gets copied between machines and pasted into issues, which is the whole reason for the split. See Configuration.

On the client side, Beacon stores it in your OS keychain rather than in a config file. The address is stored locally; the token is not written anywhere Beacon can read back as plain text.

Before you expose a port

Four things, in order, and the last one is the one people skip:

What a token does not do

It authenticates the transport. It is not a per-user identity, there are no roles, and there is no audit trail of who used it — one token, one level of access. If you need to revoke access for one person while keeping it for another, rotating is the only mechanism and it revokes everyone.

It also does not encrypt anything. The REST API is plain HTTP on a dev port; if you are carrying it across a network you do not control, put it inside something that does encrypt — which is another argument for a tailnet over a port forward.