Modo ChatGPT, Submodo Work — Protocolo
As duas formas de iniciar o submodo work (direto pela aba e via handoff), execution target local_executor, e o que muda no payload
Modo ChatGPT, Submodo Work — Protocolo
Part of openai-research. Fixed nomenclature: see the hub glossary.
The two ways to start
- Direct (Work tab at the top of ChatGPT mode): o composer mode é persistido por conversa (
home-composer-mode, enum interno['chat', 'work', 'codex']) com resolver de gating (workOnlyModeEnabled,workModeAllowed, denied → work). Com a aba work ativa,isEverydayWorkMode = true. - Via handoff (from the chat submode): o modelo do chat chama a tool
handoff(prompt, reason)→ cria o thread/work. (O caso "crie uma task no modo work…" — ver voice-and-tasks.)
What changes in the payload (/f/conversation)
local_function_signatures: [{name: 'handoff', params: [{name: 'prompt', required: true, type: {description: 'A brief instruction describing what Work mode should do for the user.', type: 'string'}}, {name: 'reason', required: true, type: {description: 'A short user-facing reason why continuing in Work mode would help.', type: 'string'}}], type: 'kwargs'}]— with the full server-provided description ("Redirect the user's request from ChatGPT to Work mode when Work mode is the better execution environment…" — verbatim text in flow-a-tool-protocol and flow-a-manual-step-by-step). Always offered in the ChatGPT mode (chat submode included — the handoff is the bridge from chat to work); the model calls it only when the task needs executionconversation_execution_target:
{
"kind": "local_executor",
"cwd": "<diretório da conversa>",
"installation_id": "<app installation id>",
"mcp_servers": {},
"selected_capability_roots": []
}
- O target persiste na
metadata.conversation_execution_targetda primeira user message — os turns seguintes derivam dele (jVrlê da última user message) model/thinking_effort: defaults do submodo (ex.: "5.5 High")
Execution
When the model calls handoff, the app executes the agent locally via the embedded app-server (Resources/codex) — the UI "Full access" is this executor scope (cwd, capability roots, local MCP servers, up to 256). Codex threads: codex://threads/{id}; thread compact via /responses/compact (see codex-flow-protocol).
Execution location: local vs cloud (the sidebar label)
The thread hover card shows execution-location: local ("Runs on your computer", sidebar.thread.hoverCard.executionLocation.local) vs cloud ("Runs in the cloud"). Feature flags gate each: workLocalAccess, workCloudAccess, codexLocalAccess (plus localBackend). Observed: a Codex mode thread (started in the Codex tab, thread_source: user) is listed in the ChatGPT mode as "Work — Runs on your computer" — the modes share the same local thread store (state_5.threads); the sidebar differentiates conversations by conversation_origin (tpp = tasks vs non-tpp) and the label by execution location. "Work cloud/remote" = the site-side equivalent (needs workCloudAccess; not exercised in this research).
Tasks (origin tpp)
conversation_origin: 'tpp' marca as tasks do Work — o filtro da sidebar (chats = origin ≠ tpp; tasks = origin === tpp) e Pqr(): origin tpp → backend codex. Creation via POST /wham/tasks with prior_conversation when it comes from the chat (see voice-and-tasks).
TypeScript types (payloads of the work submode)
// ── handoff (the local function signature that starts work) ──────────────
export interface HandoffParams {
prompt: string // required — brief instruction for Work
reason: string // required — user-facing reason
}
export type HandoffSignature = import('./flow-a-tool-protocol').LocalFunctionSignature & {
name: 'handoff'
params: [
{ name: 'prompt'; required: true; type: { description: 'A brief instruction describing what Work mode should do for the user.'; type: 'string' } },
{ name: 'reason'; required: true; type: { description: 'A short user-facing reason why continuing in Work mode would help.'; type: 'string' } },
]
}
// ── the execution target (persisted in the first user message metadata) ──
export interface LocalExecutionTarget {
kind: 'local_executor'
cwd: string
installation_id: string
mcp_servers: Record<string, unknown> // {} observed for the plain chat handoff
selected_capability_roots: unknown[]
}
export interface RemoteExecutionTarget {
kind: 'remote' // the site-side equivalent (workCloudAccess) — not exercised
[key: string]: unknown
}
export type ExecutionTarget = LocalExecutionTarget | RemoteExecutionTarget
// ── persistence + labels ─────────────────────────────────────────────────
export interface FirstUserMessageMetadata {
conversation_execution_target: ExecutionTarget
}
export type ConversationOrigin = 'tpp' | 'non-tpp' | string // 'tpp' = Work tasks (sidebar)
export type ExecutionLocationLabel = 'local' | 'cloud'
export interface ExecutionLocationFlags {
workLocalAccess: boolean
workCloudAccess: boolean
codexLocalAccess: boolean
localBackend: boolean
}
Cross-references
- Chat submode (the focus): chat-submode-protocol
- Shared codex backend: codex-flow-protocol
- Architecture: chatgpt-desktop-architecture
- Live full-loop evidence: work-runtime-trace
- The tool contract (the handoff is the canonical client-executed tool): flow-a-tool-protocol
- Flow definitions: flow-definitions (work is not a flow — it is a surface; the flows A/B describe attestation/PoW)