Chapter 08 Partial · M2 native homes, M3 runtime users

# Logging in (still one click).

Per-agent credentials sound expensive in clicks. They do not have to be. Solo desktop can default to brokered convenience. Strict agents, Teams, and Cloud should default to separate provider homes.

01
User→Desktop UI
Clicks "Log into Claude for Sales".
02
Desktop UI→Engine
`POST /v1/agents/Sales/providers/anthropic/login` (new scoped route).
03
Engine→claude CLI
Spawn as `hou_sales` inside the Linux runtime.
04
claude CLI→Engine
Prints login URL on stdout.
05
Engine→Desktop shell
Pushes URL to the host shell via the runtime bridge.
06
Desktop shell→System browser
Opens the URL.
07
User→Anthropic
Logs in.
08
Anthropic→Provider callback
Completes the CLI-owned OAuth flow. Houston does not control this callback.
09
Provider→claude CLI
CLI detects completion through its own callback or polling path.
10
claude CLI→Anthropic
Exchanges provider-owned code and saves token in the agent provider home.
11
Engine→Login state
Observes CLI success, verifies provider status, records login state.
12
Engine→Desktop UI
WS event "Sales logged in". UI updates.
13
Houston OAuth→Desktop shell
Only Houston-owned OAuth flows use `houston://...` deep links.

One click for the user. Provider tokens stay inside the provider CLI flow. Houston only forwards the login URL out of the runtime and observes success.

## What you already have

Houston already has host-side OAuth plumbing for Google sign-in via Supabase. A click in the UI starts a Houston-owned OAuth flow. The system browser does the work. A custom URL scheme (`houston://...`) brings the result back into the app.

Provider CLI logins are different. The current provider login route is global (`/v1/providers/:name/login`). The future scoped route should start a provider login for one agent home, but it should not pretend Houston owns Anthropic or OpenAI callback URLs.

## The new piece: host-to-runtime bridge

When the engine lives inside a Linux runtime (Chapter 3), the host UI must bridge two things: opening provider login URLs printed by a CLI, and delivering Houston-owned deep links back to the engine. Do not mix those flows.

Two things to get right:

- Only loopback. The runtime's HTTP port is bound to host loopback only. Same posture as today's native engine.
- Provider token stays in the provider home. Houston forwards provider login URLs and observes status. It does not shuttle provider tokens over the bridge.
- Houston-owned OAuth still uses deep links. Supabase and future Houston-branded OAuth can pass short-lived codes through `houston://...`. That is not the provider CLI path.

## What about provider CLI callback URLs?

The Claude Code CLI and the Codex CLI each open their own hosted OAuth flow. We don't control their callback URL. We capture it by:

1. Spawning the CLI inside the runtime.
2. Reading the login URL it prints to stdout.
3. Asking the host shell to open that URL.
4. Waiting for the CLI subprocess to finish the exchange.

No `houston://` hijack belongs in the common provider path; the CLI handles its own callback. The deep link is only for Houston OAuth flows such as Supabase.

## Per agent vs broker

Two flavors, both compatible with the same plumbing. The honest defaults differ by deployment.

### Desktop solo user: broker by default

One provider login for the whole desktop profile. Houston can seed or broker agent provider homes for convenience. This is acceptable for a solo user who treats agents as slices of one trust boundary.

It is not acceptable for "two clients, two legal boundaries." Desktop needs a visible strict mode per agent or per workspace, before Teams exists.

### Teams or Cloud: per-agent by default

Each agent gets its own provider home and its own login state. It may still be the same human account, but tokens and tool grants are not shared by default. This is the mode the regulated-industry pitch leans on.

What works today

Single-account Anthropic, OpenAI, and Composio logins work today, but they are machine-wide. The current engine route is global, not agent-scoped. M2 should add per-agent provider homes on native hosts. M3 should move those homes under per-agent Linux users if the runtime ships.

Where to look in the code

Today's provider login route: `engine/houston-engine-server/src/routes/providers.rs`. Today's Supabase OAuth deep-link handler: `app/src-tauri/src/commands/auth.rs` (host side). New bridge: `app/houston-tauri/runtime/bridge.rs` (new). CLI spawn for per-agent: same site as Chapter 7, `engine/houston-terminal-manager/src/cli_process.rs` with the `HOME` override.

← Previous
Keeping agents apart
Next →
External triggers