Skip to content

feat: BYOK mode — bring your own API key for shared agent sessions #1

Description

@gosunuts

Summary

Optional mode where external users bring their own API key (Anthropic, OpenAI, Google) to chat through a shared agent-frontend instance. The host provides infrastructure (bridge + Portal tunnel); each visitor provides their own credentials and pays their own API costs. No accounts, no shared keys, no cost splitting.

Motivation

Currently the agent-frontend requires the host to run a local agent (OMP/Claude Code/Codex). This limits sharing: friends can watch the host's session but can't have their own private conversations. BYOK turns the frontend from "remote access to my agent" into "a shared AI gateway where everyone brings their own key":

  • Friends don't need to install OMP, Claude Code, or any CLI agent
  • Everyone uses their own API key — no shared costs, no trust boundary violation
  • The host just provides the URL (Portal tunnel + bridge)
  • Feels like a self-hosted ChatGPT alternative with zero accounts

UX design (the critical part)

This feature lives or dies on the key-entry UX. It's the trust moment — users are handing their API credentials to a URL.

Onboarding flow (first visit)

  1. Provider selection cards (not a dropdown — tappable tiles):
    • Claude (Anthropic)
    • GPT (OpenAI)
    • Gemini (Google)
  2. Trust messaging before key input:
    • "Your key never leaves this server. No logs, no storage, no sharing."
    • "Transmitted over an encrypted tunnel (E2EE)"
    • "Server operator cannot see your key"
  3. Key input with provider-specific placeholder format
  4. Get-a-key link to each provider's console (friction removal)
  5. Instant validation — tiny API call to verify the key works before accepting
  6. Clear feedback: "✓ Connected — claude-sonnet-4-5" or "✗ Invalid key — try again"

Returning visit

  • If key saved in localStorage (user opt-in "Remember on this device"): auto-connect
  • Settings panel: masked key display (last 4 chars), "Change key", "Forget key"

Security design

  • Key travels from browser → WebSocket → bridge (inside Portal's E2EE tunnel — relay sees only ciphertext)
  • Bridge holds key in memory per session — never written to disk, never logged
  • Session termination → adapter shutdown → key dropped from memory
  • Host sees "someone is using the bridge" but cannot see key values
  • "Forget key" button: clears localStorage and terminates the session

Bridge modes

# Current: host runs a local agent
bun agent-bridge.ts --agent omp

# BYOK: visitors bring their own keys
bun agent-bridge.ts --mode byok

# Hybrid: host uses local agent, visitors can BYOK
bun agent-bridge.ts --mode hybrid

Technical design

The existing adapter architecture supports this directly:

// Adapters already accept API keys
export class ClaudeCodeAdapter implements AgentAdapter {
  constructor(apiKey?: string) {
    this.client = new Anthropic({ apiKey });
  }
}

// Bridge: accept key from WebSocket, create per-session adapter
websocket.message(ws, msg) {
  if (msg.type === "set_api_key") {
    const adapter = createAdapter(msg.provider, msg.apiKey);
    // Create session with this adapter
  }
}

Frontend changes:

  • Onboarding screen (provider cards → key input → validation)
  • Settings panel (change key, forget key, remember toggle)
  • Key stored in localStorage only with explicit user consent

What this enables

  • Share your Portal URL with a friend → they paste their Anthropic key → instant Claude chat
  • Team shares one bridge URL → everyone uses their own keys → private conversations
  • Community demo: share URL at a meetup → attendees try AI with their own keys

Scope

  • Bridge: --mode byok / --mode hybrid
  • Frontend: onboarding flow (provider cards, key input, validation)
  • Frontend: settings panel (key management)
  • Adapters: accept runtime-provided keys (not just env vars)
  • Validation: instant key check with provider-specific error messages
  • Trust messaging in the UI
  • Documentation: security model explanation

Target

Milestone: v0.7.0 (after session management and frontend refactor are merged)

Non-goals

  • No key storage on the server (memory only)
  • No multi-key management (one key per session)
  • No usage tracking or billing (that's the provider's job)
  • No proxying for multiple users through one key (each session uses its own)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions