Goal: let realtime handoff continue work in a specific existing Codex thread, not just a per-server scratch handoff thread.
Implement codex(server, prompt, thread_id?) for realtime.
server: target local or remote serverprompt: delegated task textthread_idoptional: existing thread/session to continue
If thread_id is present, the handoff router should resume that thread and send the turn there instead of creating a new handoff thread.
- Keeps the model interface simple and explicit.
- Reuses the existing realtime
codexdelegation path instead of teaching the model a separate resume-only tool first. - Makes “continue that session” a first-class handoff action.
- Preserves the current dynamic tools (
list_sessions,read_session,run_on_server) as discovery helpers.
Extend the built-in realtime codex function tool to accept:
serverrequiredpromptrequiredthread_idoptional
This likely means updating the realtime session tool definition in the codex websocket layer and its tests.
Extend the parsed RealtimeHandoffRequested payload to carry optional thread_id.
Today we already extract:
- transcript
- server
We would also extract:
thread_id
Update the handoff routing path in ServerManager so that when a handoff includes thread_id:
- build
ThreadKey(serverId:, threadId:) - call
resumeThread(...)before sending the turn - cache that key in
voiceHandoffThreads[serverId] - stream output from that resumed thread back into the realtime handoff
If no thread_id is supplied, keep the current behavior:
- reuse the cached handoff thread for that server, or
- create a new one
After a handoff resumes a specific thread, follow-up voice turns for that server should keep using that same resumed thread until the user switches context.
This avoids:
- resuming the same thread repeatedly
- falling back to an unrelated scratch thread on the next turn
Update the voice/realtime prompt so the model knows:
- use
list_sessionsorread_sessionto find the right thread when needed - pass
thread_idintocodex(...)when the user wants to continue a specific session
Desired flow:
- User says “continue that session on bigpc.”
- Realtime model uses
list_sessions/read_sessionif needed. - Realtime model calls
codex(server=\"bigpc\", prompt=\"...\", thread_id=\"thr_123\"). - Handoff event reaches iOS with
serverandthread_id. - iOS calls
thread/resumeforthr_123. - iOS sends the delegated turn into
thr_123. - iOS streams resulting assistant output back through
resolveHandoff(...). - iOS finishes with
finalizeHandoff(...).
thread/resumealready exists on the app-server side.thread/realtime/startis already thread-scoped, but realtime transport state is ephemeral.- The main missing work is passing
thread_idthrough the realtime handoff contract and honoring it in the iOS handoff router. - The main correctness risk is ensuring the resumed thread is subscribed and hydrated before streaming handoff output from it.