session.list_sessionslists every loaded session across the workspaces the app knows about (pinned first, then newest). Passlimitto cap the count orworkspaceIdto narrow to one workspace.session.searchfinds sessions by title or transcript text.session.readreads recent messages from any session by ID, without opening it.session.openshows a session to you, when you ask to see it.
What did I say in the customer migration session?Find the session about the pricing page redesign and remind me what we decided.Open the onboarding bug chat and summarize the next steps.What did I ask you to do in session ses_abc123?
What happens
- The agent lists or searches sessions and matches by session ID, title, workspace, or topic words you provided.
- If there is one clear match, the agent reads that session’s transcript by ID and answers from the returned messages.
- If there are multiple likely matches, the agent asks which session you meant.
- If you asked to open the chat, the agent opens it after reading.
session.search, session.read) never changes what is on your screen. An agent only opens another session (session.open) when you ask to see it.
How agents manage other sessions
Agents address other sessions by id, and by default nothing on your screen changes. Showing you something is a separate, explicit step.- Read:
session.searchandsession.readreturn transcripts without opening anything. - Talk:
session.send { sessionId, text }submits a prompt to an existing session by id after validating its effective model through a connected renderer host. Missing host/catalog or stale models returnmodel_unavailablewithout writing a prompt.session.createcreates sessions and submits their first prompts. Both reportaccepted: trueonly after the engine accepts the asynchronous HTTP request, not when inference starts or completes. - Show:
session.openandworkbench.session.focusare the only actions that move your pane.session.send { reveal: true }sends first and then opens that session for you. - File:
session.rename,session.pin, andsession.archiveact by id and do not open the session (archiving the session you are looking at closes its tab).
composer.set_text, composer.send, and composer.stop are different: they type into, send from, or stop whichever composer you currently have focused. They are for “type this for me here”, never for reaching another session — if you switch panes while the agent is typing, the text goes to the pane you switched to. Agents are told to use session.send instead.
How agents manage other sessions
An agent can start sessions (session.create) and file idle ones away (session.archive). The rule is check status, then archive, and a warning always goes back through the channel the request came from: you get a dialog, an agent gets a structured result in its own conversation.
- Check status.
session.list_sessionsandsession.readreturnstatusand aworkingboolean for every session.workingis true while a turn, delegated task, permission request, or question is still open. - Archive once it is idle. Archiving a session with
working: falsecompletes immediately and preserves its context. If an agent tries to archive a session that is still working, nothing happens in the app: the agent receivestarget_workingwith the advice to ask you to stop it in the app if you want it closed, or to leave it running. A session that tries to archive itself, or its parent, from inside its own turn receivesself_archive_while_working: it should finish the turn so its conclusions can be reviewed; the reviewer archives. Restoring an archived session never restarts stopped work.
Model and reasoning effort
Every session is bound to a model, and agents can see and set it without opening the session or reading OpenWork’s storage:session.list_sessionsentries andsession.readresults carrymodel: { providerId, modelId, variant }.variantis the reasoning effort you see as the behavior pill in the composer (for examplelow,medium,high); it isnullwhen the provider default applies. Before a session has a model bound (nomodelat creation and no turn yet),modelisnull.session.createaccepts model ids or an exact case-insensitivealias/displayName, optionally qualified byproviderId, withvariantfor effort. All batch selections resolve throughmodels.listbefore any creation. Explicit model selection requires an existing renderer host even for headless callers; missing host, unavailable or ambiguous selections cause zero writes. Canonical ids go on both creation and the first prompt. ReturneddisplayName/providerNameare decorations; bindings round-trip by ids. Without any model selection, creation uses the engine default and does not require a renderer catalog.session.set_modelsaves a local next-send model override for one session; it does not update the engine binding or send a prompt.session.rebind_modelpreviews matching idle sessions that are not archived in one workspace withdryRun: true, then requires confirmation of that exact session set to save overrides. Both require a renderer host and leave global defaults unchanged.
Acceptance and partial failures
Asession.create receipt’s created entries contain accepted: true, never started: true. Catalog preflight does not guarantee later availability or inference success. On HTTP failure or timeout, the failure envelope retains result.created, result.failures, effects, and indexed issues with any known created sessionId. Workspace discovery (including its response body), catalog lookup, and the best-effort reload each have a 7-second timeout; each create and prompt request has a 10-second timeout. Failed discovery returns a structured workspaceId issue before any writes. Provider error reasons are redacted before being capped at 400 characters, and the combined error summary is also capped. A timed-out write may have reached the engine: inspect sessions before retrying; there is no automatic retry.
Creation never focuses or opens a session. Its best-effort workspace reload is not proof of sidebar visibility. Use session.read to inspect transcripts and session.list_sessions for observed activity. session.read.lastError is a sanitized snapshot of the latest assistant error in the inspected window, not a live event feed: pre-assistant failures can remain invisible, and null does not prove successful inference.
Current limits
- Session lookup is based on the sessions OpenWork has loaded for the current app and workspace context.
- Transcript reads return a bounded set of recent messages from the opened session. If an older part of a long chat is not returned, the agent should say that instead of guessing.
- This is not semantic search over every message yet. Clear titles, session IDs, workspace names, or topic clues help the agent find the right chat.
- The agent can only read sessions available to the current OpenWork app and user.
How to ask
Give the agent whatever clue you have: a session ID, title, person name, project name, workspace, or rough topic. For example:Use the OpenWork app UI to find the customer migration chat and tell me what I said about customer references.