Caleb Kim
in
Caleb Kim in
Caleb Kim3PO
01 CONTEXT02 SOLUTION03 UNDER THE HOOD04 DECISIONS05 REFLECTION
Caleb Kim3PO·CASE STUDY
CASE STUDY · BUILD — DESIGNED & CODED

3PO

PROTOTYPE SOLO · DESIGN + BUILD

A voice-first AI agent that connects to my Hermes agent, reads my screen on demand, and writes to my Obsidian vault.

The voice-first interface — no keyboard for core interactions.
TL;DR — A SCREENER CAN STOP HERE

3PO is a voice-first macOS companion with a British-butler persona, built on OpenAI's Realtime API. Seven tools — notes to my Obsidian vault, web search, screen vision, Gmail search/draft/send, Drive search — with permissions designed so the dangerous things are structurally impossible. A working local prototype: real voice conversations, real tools, on my Mac.

7VOICE TOOLS
3OAUTH SCOPES — DELETION IMPOSSIBLE
1,718LINES — ONE PYTHON PROCESS
ROLESolo — design + build
TIMELINEApr 2026 → ongoing
TEAMSolo
TOOLSOpenAI Realtime API · gpt-4o (vision) · Gmail + Drive APIs · PyWebView · Python
01 — CONTEXT

Latency was killing the interaction model

I tried talking to my main agent (Hermes) through a Discord voice channel and the latency was killing the interaction model. I also had a recurring annoyance — sending screenshots to different chat models whenever something on my screen confused me — that turned every quick question into a multi-step process. I wanted a voice-first agent with screen vision and constrained permissions, sitting between me and my main agent.

✦ NORTH STAR

“What should be a model, and what should be code?”

02 — SOLUTION

Seven tools, and permissions as product design

Seven tools live directly in the Python server — notes, web search, screen vision, Gmail search/draft/send, Drive search. Gmail's OAuth scopes make deletion structurally impossible, and sending is two-step: the model drafts, a separate explicit instruction sends. On startup 3PO reads three vault files and knows my projects before I say a word.

The Obsidian vault graph 3PO reads from
The vault it wakes up inside — job reports, project boards, research notes. Three of these files ride along on every session.
03 — UNDER THE HOOD

The same screens, flipped over

The hardest problem was screen capture — Realtime has no vision, so describe_screen is a dual-model trick: a screencapture subprocess, a separate synchronous vision call, and the description injected back as a tool result. macOS ties Screen Recording permission to the responsible process, which meant building a proper .app bundle just to be allowed to look.

FRONTENDInline HTML/CSS/vanilla JS — no framework
BACKENDPython: aiohttp + websockets bridge + sounddevice (24 kHz PCM16)
AIOpenAI Realtime (server-VAD) + whisper-1 + separate gpt-4o vision call
INTEGRATIONSGoogle OAuth2 — gmail.readonly · gmail.compose · drive.readonly
KEY SCREEN A · SCREEN VISION
3PO listening with screen awareness on, over a spec doc
Voice Query → Screen Capture → GPT-4o Vision Call → Spoken Response.
KEY SCREEN B · BARGE-IN
The 3PO window — waveform centerpiece and mono state label
Interrupting the agent mid-sentence, locally — no mic audio streams to OpenAI while it speaks.
Voice Query → Screen Capture → GPT-4o Vision Call → Spoken Response.
04 — DECISIONS

What I said no to

✕ REJECTEDServer-VAD streaming interruptSending mic audio to OpenAI during AI speech created echo feedback — it interrupted and listened to itself. A local RMS gate + response.cancel won.
✕ REJECTEDFull Gmail scopeDeletion made structurally impossible via scopes; two-step send keeps a human in the loop.
✕ REJECTEDScreen awareness ON by defaultPrivacy-first: it stays OFF until deliberately toggled, every session.
✕ REJECTEDThe gold/black themeFully built, then reversed — replaced with the cooler Slate & Ice palette and a hand-processed ink avatar.
A NOTE ON HONESTY

“A working local prototype — single-user, not deployed. No echo cancellation on the mic capture, so barge-in over speakers is a tuning problem, not a solved one.”

05 — REFLECTION

What the build taught me

Failure modes of AI tools are architectural, not just probabilistic — the model needs structural evidence a tool works before it calls it reliably. Permission design is product design: scopes are a hard technical guarantee, not a policy promise. And latency shapes the whole interaction model — a 2–4 second round-trip feels fine in chat and completely wrong in voice.

The complete agent in use, end to end.
SAY HELLO Like what you see? Let's talk. bycalkim@gmail.com →
UP NEXT FormaLIVE Founding designer — patient platform built 0 → 1. →
LAST DEPLOYED AUG 2026 · NYC
ESC
↑↓ navigate↵ openESC close