Managing Sessions
Create, open, list, archive, and permanently clean up Sessions
agent.sessions is the local collection entry point. A session may choose a Workspace as its initial directory, and may switch it later.
Create and open
const created = await agent.sessions.create({
workspace,
});
const task_session = await agent.sessions.create({
workspace,
origin: { type: "task", task_id: "daily-report" },
});
const existing = await agent.sessions.get("session-id-from-list", "work");
const existing_task = await agent.sessions.get(task_session.id, "task");create() always generates the Session ID internally. To reopen an existing Session, obtain its ID from
list() or another persisted reference and pass it to get(session_id, origin_type = "work").
origin.type may be any non-empty string and may carry additional JSON metadata. get() reads only the
requested partition and never scans other origins.
A Workspace is the session's current directory, not its identity. It is a persisted configuration field
on the session, sharing the set() handle with model:
const session = await agent.sessions.create({ workspace: repo_a });
await session.set({ workspace: repo_b }); // move to another repo with history intact
await session.set({ workspace: null }); // leave the project contextOnly workspace_id is written to disk; the host resolves and injects the instance through
get(..., { workspace }). Passing a Workspace to get() different from the persisted one is
also not an error; it becomes the new current directory:
const reopened = await agent.sessions.get(session.id, "work", { workspace: repo_c });Switching does not migrate existing messages, attachments, or tool results; those belong to the directory they happened in. A running turn keeps the previous directory, and the change applies from the next step checkpoint. A session without a Workspace is valid: it has no file tools and no shell, while plain model conversation still works.
The agent's own session
The agent itself is a session, obtained with agent.session(); its session_id equals the agent's id
and its role is origin.type = "agent". It does not appear in the default work partition list.
See Agent session.
Observe new sessions
Local hosts can use agent.sessions.on_created() to observe new sessions, including work sessions started with session_start and the agent's own session when first created:
const unsubscribe_created = agent.sessions.on_created(async (session) => {
session.subscribe((mutation) => publish_mutation(session.id, mutation));
publish_session(await session.get_info());
});
// Release the listener when the host exits or replaces the agent.
unsubscribe_created();The notification runs after initialization. The SDK waits for listeners before returning the new session, so hosts can subscribe to messages and runtime changes before the first prompt(). Restoring an existing session does not emit it. Listener failures are logged without undoing the persisted session. This is an in-process notification; load the initial directory with list().
Desktop adds new work sessions to their Workspace in Works and receives subsequent title, message, and execution updates.
List and search
const page = await agent.sessions.list({
origin_type: "work",
limit: 30,
query: "repo",
});
for (const item of page.items) {
render_session_row(item);
}
if (page.has_more) {
const next_page = await agent.sessions.list({
limit: 30,
cursor: page.next_cursor,
query: "repo",
origin_type: "work",
});
}list() defaults to the work partition. Pass origin_type to list another partition. List items are lightweight summaries, not complete Messages. Common fields are session_id, origin, title, preview_text, message_count, model_label, updated_at, and executing. cursor is opaque: return it to the SDK unchanged.
query is a lightweight contains filter for a session picker. It is not a full-text search language.
Archive and clean up
await agent.sessions.archive({ id: "repo-analysis", origin_type: "task" });
const archived_page = await agent.sessions.archived({ origin_type: "task", limit: 30 });
const removed = await agent.sessions.clean_archive();
console.log(removed.removed_session_ids);Archiving removes a Session from the active list without immediately destroying it. A running Session cannot be archived; wait for its Turn or call stop() first.
clean_archive() permanently deletes every archived Session. Treat it as an explicit empty-trash action and require user confirmation in a UI.
For local maintenance, remove(session_id, origin_type = "work") permanently deletes one active Session's Agent-owned data. clear_messages(session_id, origin_type = "work") clears only its messages. Power-owned data is not deleted implicitly; call the owning Power when a workflow also needs to remove domain data.
UI guidance
- Use lightweight
list()summaries for the sidebar. - After selection, call
get()and then loadmessages(). - Render
executing: trueas the runtime state; do not guess from timestamps. - Remove an archived item from the active list and reload archived data after success.
A Session title can be empty. The presentation layer should fall back to session_id or a product-defined placeholder.