Observability

The log lines worth knowing, and what they tell you.

Everything goes to stdout, so docker logs is the whole interface. Every line for a call carries its bridge id, which makes one call one filter:

docker logs agent_server --tail 100
docker logs agent_server 2>&1 | grep 48c7ad0bc30f     # one call
docker logs -f agent_server                            # follow

There are no metrics endpoints. Ship stdout to wherever you keep logs.

At boot

The whole configuration is printed, including variables that are set but not read — usually a rename:

[env] ---- agent server configuration ----
[env]   APP_GRPC_LISTEN_PORT   50052   # gRPC port; host is 127.0.0.1
[env]   ULAI_GRPC_API_KEY      set len=64 sha256:57a4cbf1
[env]   GEMINI_PROJECT_ID      (unset)   # NOT READ — the client sends it per call
[env]   NOT READ BY THIS PROCESS: APP_ENV APP_NAME SERVICE_HTTP_PORT
[env]   (set in the environment but nothing here looks at them — usually a rename)
[env] ---- end agent server configuration ----

Secrets are shown as a length and a hash, never a value.

Also at boot:

aibackend: realtime = gemini-live (default)
aibackend: classify = gemini-live (default)
[grpc] agentsession.v1 listening on [::]:50052 (AgentBridge served; AgentSession/AgentDispatch served)

Per call

LineMeans
[bridge] join: bridge=… agent_id=… participant=…The agent has a seat.
[AIRoute] ai_project=… creds=supplied (N bytes)The profile carried a key. The one to check first.
using the profile supplied with the requestNo database lookup happened.
[gemini] connected, greeting deferredThe backend handshake succeeded.
greeting primedThe agent is about to speak.
[ulai] roster: N other participant(s) in roomWho else is there.
call ended: reason=… duration=…ms played=…msHow it ended, and how much was heard.

[AIRoute] never prints a credential. It shows creds=supplied (2347 bytes) or creds=engine default — the latter meaning the profile carried none, which is now a refusal.

Turn accounting

played=…ms is not duration=…ms. It is how much agent audio the caller actually heard, and it differs from wall-clock by every second of silence, ringing and caller speech. It is the number that reflects what was delivered.

The same distinction appears per turn: a turn-ended event carries how much of that turn was heard before it was cut.

Audio

With AUDIO_NOTHING=true set on this host, the chain is cut down to the denoiser and says so loudly:

[AUDIO] AUDIO_NOTHING=true — pure RNNoise (preprocessor + foreground gate disabled)

That line in production is almost always a mistake — see configuration.

Prompts

PROMPT_LOG=on logs the system instruction at connect. Useful exactly once, when an agent is behaving oddly and you want to see what it was actually told. Noisy forever after, and it puts the prompt in your log store.