Skip to content

Snowpea protocol ​

  • Protocol version: 1.25.0 (semver)
  • Source of truth: core/snowpea_core/server/protocol.py
  • Generator: uv run python scripts/gen_protocol.py
  • Bindings: sdk/src/protocol.ts (generated alongside this file — never hand-edit)

Transport ​

The daemon listens on a loopback-only port chosen at start-up and records it in $SNOWPEA_HOME/daemon.json as {port, pid, token, startedAt, protocolVersion}.

surfaceendpointpurpose
WebSocketws://127.0.0.1:<port>/wsJSON-RPC 2.0, bidirectional
HTTP GEThttp://127.0.0.1:<port>/healthliveness probe
HTTP GEThttp://127.0.0.1:<port>/protocol.jsonthis schema as JSON
HTTP GEThttp://127.0.0.1:<port>/versionserver and protocol versions

Every state-changing method lives on the WebSocket only; the HTTP endpoints are read-only operational helpers.

Handshake ​

Immediately after connecting, the client calls system.hello with the daemon token, its own clientVersion, and the protocolVersion it was built against. Any other method before a successful system.hello fails with unauthorized. A mismatched major version is rejected with protocol_incompatible.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "system.hello",
  "params": {
    "token": "<contents of $SNOWPEA_HOME/token>",
    "clientVersion": "0.1.0",
    "protocolVersion": "1.25.0"
  }
}

Server capabilities advertised in the system.hello result:

  • approvals
  • audio
  • batchedFileTools
  • checkpoints
  • commands
  • hostToolParallel
  • hostTools
  • llmSample
  • llmTimings
  • lsp
  • mcp
  • onceOnlyScope
  • pageActionAlways
  • providerModelsError
  • readOnlyDelegation
  • sessionAttachments
  • sessionContinue
  • sessionSetAgent
  • sessions
  • setAgentGuardTurn
  • settings
  • setup
  • siteFrameActions
  • siteMemory
  • siteRecipes
  • snapshotSupersede
  • standingOrders
  • tabReadAlways
  • toolInvokeGuard
  • tools
  • update
  • webSearch

Method index ​

methoddirectionsummary
agent.bindChannelclient → serverRoute a gateway channel to a named agent.
agent.createclient → serverDefine a named agent from a description.
agent.deleteclient → serverDelete a named agent.
agent.listclient → serverList the named agents that are defined.
agent.spawnclient → serverRun a named agent on a task.
approval.askclient → serverEscalate one host action through the approval pipeline. The approver's approval.request carries tool, args with detail nested under args.detail and the site under args.site, note = reason, site, and scopeHint 'site' when a site is known. A local dev server navigation (tool 'repl.navigate', args.reasonCode 'localDevServer', args.url, args.project) gets scopeHint 'project': a 'project' answer stores a rule for the session's project and the URL's origin that only such asks match.
approval.listclient → serverList tool calls still waiting for a decision.
approval.requestserver → clientAsk the client to approve a tool call.
approval.respondclient → serverAnswer a pending approval and unblock the turn.
audio.capabilitiesclient → serverReport what voice input and output can do on this machine.
audio.installclient → serverInstall a local voice engine (or one of its voices) and re-run detection.
audio.record.startclient → serverStart recording the microphone.
audio.record.stopclient → serverStop the recording and return the wav it wrote.
audio.speakclient → serverSynthesise speech, optionally playing it on the daemon's machine.
audio.transcribeclient → serverTranscribe recorded audio to text.
audio.voicesclient → serverList the voices one speech engine offers here.
backend.setclient → serverChoose where a session's tools execute: local, docker or ssh.
checkpoint.deleteclient → serverDelete one checkpoint, or all checkpoints for a session.
checkpoint.diffclient → serverShow what restoring a checkpoint would change from the current workdir.
checkpoint.listclient → serverList restore checkpoints for a session, newest first.
checkpoint.restoreclient → serverRestore files to their before-turn state, optionally through later turns.
command.listclient → serverList the slash commands available to a session.
command.runclient → serverRun a slash command; the only execution path for them.
file.completeclient → serverComplete file and directory paths under a session workdir.
gateway.bindclient → serverAttach the daemon to a chat platform channel.
gateway.listclient → serverList live gateway bindings.
gateway.syncclient → serverReconcile the messenger bindings with settings.gateway.
gateway.unbindclient → serverDetach a gateway binding.
job.cancelclient → serverCancel a scheduled job.
job.deleteclient → serverDelete a job, its schedule and run history; optionally its run sessions.
job.listclient → serverList scheduled jobs and their next run times.
job.nextRunForClientclient → serverWhen a host should be awake for its routines (addendum 11).
job.previewclient → serverRead a schedule spec without saving anything (1.10.0): its kind and when a job with it would first fire. An unreadable spec is invalid_params with job.schedule's message.
job.runNowclient → serverFire a scheduled job immediately.
job.scheduleclient → serverSchedule a prompt to run unattended.
job.updateclient → serverChange an existing job (addendum 12).
llm.sampleclient → serverOne tool-less model call for a session's browser host (1.14.0): no tools, no history, nothing written to the transcript except a usage event. The session's host only ('unauthorized' otherwise); 'unavailable' when no model can answer; with schema, 'invalid_output' when the answer does not validate.
lsp.catalogclient → serverList every registered language server, regardless of whether it has started.
lsp.statusclient → serverReport every language server the daemon has started and its state.
mcp.addclient → serverWrite an MCP server into the project or global .mcp.json and start it.
mcp.catalogclient → serverThe curated MCP servers a client can offer as presets.
mcp.listclient → serverList every configured MCP server with its scope, state and tools.
mcp.reloadclient → serverRestart one MCP server, or every configured one.
mcp.removeclient → serverDelete an MCP server entry and stop the server.
mcp.testclient → serverProbe a saved MCP server or an unsaved draft and report its tools.
mcp.updateclient → serverMerge a patch into an existing MCP server entry.
memory.deleteclient → serverForget one stored memory.
memory.ingestclient → serverRemember visited pages in the browser namespace, once per url and text.
memory.listclient → serverList stored memories by scope, newest first.
memory.searchclient → serverRecall stored memories matching a query.
memory.writeclient → serverStore a memory with tags.
permission.allowlist.addclient → serverPromote a pattern from ask to allow.
permission.allowlist.listclient → serverList stored allowlist patterns.
permission.allowlist.removeclient → serverDelete an allowlist pattern by id.
provider.configureclient → serverStore settings and credentials for a provider.
provider.listclient → serverList chat providers and whether they are configured.
provider.loginWebclient → serverStart a browser-based login flow for a provider.
provider.modelsclient → serverAsk a vendor's endpoint which models it serves.
provider.removeclient → serverForget a configured provider, typically a named local server.
provider.testclient → serverSend one short completion to check a provider and model.
question.listclient → serverList questions the agent is still waiting on.
question.requestserver → clientAsk the client to put a question to the human.
question.respondclient → serverAnswer a pending question and unblock the turn.
session.artifactsclient → serverFiles the session saved for the user under its workspace's artifacts/.
session.attachclient → serverMake this connection the origin of a session (approvals, host tools).
session.attachmentsclient → serverFiles the user attached in this session, with the path of the original bytes the agent may use (1.23.0). A delegated child reports its root's.
session.closeclient → serverClose a session and release its resources.
session.compactclient → serverSummarise the conversation so far and replace the history with it.
session.continueclient → serverContinue a chat session on the system's behalf, e.g. after a human hand-back (1.8.0). A running turn gets the note at its next model call (like session.notice); otherwise a turn starts whose input is the [system] note, with turn.started initiator 'system' and no message.user. Same callers as session.setAgent; subagent and scheduled sessions are refused with 'invalid_params'. One system start per session per 10 s, and an idempotencyKey is honoured once; a call inside the 10 s window keeps its note as a notice (queued: true).
session.createclient → serverOpen a session rooted at a working directory.
session.deleteSavedclient → serverDelete saved sessions.
session.interruptclient → serverStop the running turn as soon as possible.
session.listclient → serverList live or saved sessions.
session.noticeclient → serverQueue a [system] line for the model's next call.
session.promptclient → serverSend user text to a session and start a turn. Events: turn.started {turnId, prompt, queued}, then message.user {text, attachments, refs, steered: false}, then the model's output. message.user.text is what the user typed; a page attachment is listed as {kind: page, name, url, title} and only the model sees the rendered page. A steered prompt emits message.user {steered: true} + turn.dequeued {reason: steered}; a queued one emits turn.queued first.
session.renameclient → serverSet a session's title.
session.resumeclient → serverReplay the events a disconnected client missed.
session.setActiveclient → serverMark the session the user is looking at as the active one: a messenger with gateway.<platform>.shareActive posts its questions and approvals to the owner's chat. session.prompt and session.steer from a client do the same. Subagent and scheduled sessions are refused with 'invalid_params'.
session.setAgentclient → serverRun a session as an agent definition, or as none (addendum 17). Only the session's origin connection, a browser session's hostToolsFrom host, or a non-browser surface (for a session it originated or that is not a browser session) may call it; others get 'unauthorized'.
session.setBrowserProviderclient → serverPer-session opt-in to core's own browser; never global (addendum 9).
session.setEffortclient → serverPin how hard a session's model may think, or clear the pin.
session.setModeclient → serverSwitch a session between plan, accept and auto.
session.setModelclient → serverPin a session to a model profile, or clear the pin.
session.steerclient → serverInject a user message into a running turn at its next tool round.
session.toolContentclient → serverA host tool result's content blocks with image bytes; results with images are kept on disk.
settings.getclient → serverRead global or project settings, with secrets masked.
settings.setclient → serverDeep-merge a patch into global or project settings and persist it.
setup.applyDefaultsclient → serverApply the profile's defaults for everything optional; idempotent.
setup.catalogclient → serverThe setup wizard's vendor, search, browser, tools and gateway catalogs.
setup.statusclient → serverWhat setup still needs; for the browser profile only a tested provider is required.
site.deleteclient → serverSite memory (1.9.0): delete one entry, or every entry of an origin, in one browser profile. Same callers as site.list.
site.getclient → serverSite memory (1.9.0): the entries stored for an origin in the caller's browser profile; with path, only those whose urlPattern matches it, most specific first; with pageType, only that one. Stale entries are included, flagged. Browser host clients only; entries are untrusted page-derived data and core never puts them in a prompt.
site.listclient → serverSite memory (1.9.0): one browser profile's remembered sites, by origin, for a settings UI. A browser client sees its own profile; any other owner client names one with hostToolsFrom.
site.markclient → serverSite memory (1.9.0): 'ok' counts a success, sets lastVerified and clears stale; 'stale' counts a failure and flags the entry until the next put. Browser host clients only.
site.markPartclient → serverSite memory (1.15.0): count one use of a flow or recipe of an entry without a put. The entry's successCount, failureCount, stale and lastVerified are untouched, so this never counts as verification. 'not_found' for an unknown entry, flow or recipe. Browser host clients only.
site.putclient → serverSite memory (1.9.0): upsert an entry by (origin, pageType). Core checks the schema, refuses XPath, values on login fields and strings that look like personal data or credentials, and enforces 24 KB per entry (16 KB before 1.15.0) and 30 entries per origin ('invalid_params' naming the field); past 1,000 origins the least recently verified origin is dropped. A put clears stale and counts as a success. Browser host clients only.
skill.createclient → serverWrite a new SKILL.md, generated from a brief or supplied verbatim.
skill.installclient → serverInstall a skill from a path, URL or registry.
skill.listclient → serverList installed skills.
skill.readclient → serverRead a skill's SKILL.md.
skill.reloadclient → serverReload skills from disk without restarting.
skill.removeclient → serverDelete an installed skill or plugin.
skill.searchclient → serverSearch available skills.
skill.writeclient → serverSave a skill's SKILL.md verbatim.
system.checkUpdateclient → serverReport whether a newer snowpea release exists; cached for 24h.
system.healthclient → serverLiveness probe; answers as long as the daemon serves requests.
system.helloclient → serverAuthenticate a connection and agree on the protocol version.
system.infoclient → serverReport the daemon's version, pid, port, start time and home.
system.reloadSettingsclient → serverRe-read settings.json and rebind the daemon's in-memory state.
system.restartclient → serverShut the daemon down so the next launch runs the newly installed version.
system.shutdownclient → serverAsk the daemon to shut down gracefully.
system.updateclient → serverUpgrade snowpea in a detached subprocess and report progress.
team.guide.deleteclient → serverDelete a team guide from the project or global home.
team.guide.getclient → serverRead a team guide for a project or session.
team.guide.listclient → serverList every team guide visible in a project.
team.guide.setclient → serverWrite a team guide to the project or global home.
team.startclient → serverSplit a task across parallel workers.
team.statusclient → serverInspect a team's task board.
tool.invokeserver → clientAsk the client to run one of its host tools.
tool.listclient → serverList the tools registered for a session.
tool.progressclient → serverNotification: progress of a running tool.invoke, re-emitted as tool.progress.
tool.registerclient → serverRegister tools this connection runs itself (host tools).
tool.unregisterclient → serverRemove some of this connection's host tools.
usage.summaryclient → serverToken totals from stored usage events, grouped by provider, model, session or day.
web.searchclient → serverWeb search for a browser host (1.11.0): the web_search tool's provider chain, settings, caps and timeouts, for the host's own fallback when its search page is blocked. Browser host clients (with a clientId) only; 'unavailable' with details.reason when no provider can answer. Results are untrusted web content.

Methods ​

agent.bindChannel ​

Direction: client → server

Route a gateway channel to a named agent.

Params

fieldtyperequireddescription
channelstringyesGateway channel that will reach the agent.
credentialsRefstring | nullnoCredential entry the platform account uses; defaults to the platform name, e.g. 'telegram' for channel 'telegram:123'.
namestringyesAgent to bind.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

agent.create ​

Direction: client → server

Define a named agent from a description.

Params

fieldtyperequireddescription
descriptionstringyesNatural-language brief the daemon turns into an agent.
namestring | nullnoName for the agent; when omitted the daemon takes the generated one.
namedbooleannoAlso register a persistent named instance: its own session, the memory namespace agent:<name>, and rows that survive a daemon restart.

Result

fieldtyperequireddescription
namestringyesName assigned to the new agent.
pathstring | nullnoWhere the definition was written.

agent.delete ​

Direction: client → server

Delete a named agent.

Params

fieldtyperequireddescription
namestringyesAgent to delete.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

agent.list ​

Direction: client → server

List the named agents that are defined.

Params

No params (send {}).

Result

fieldtyperequireddescription
agents({ active?: boolean | null; agentId?: string | null; agents?: string[]; bindings?: string[]; channel?: string | null; channels?: string[]; description?: string; hasGuide?: boolean | null; jobs?: string[]; kind?: string; name: string; namespace?: string | null; parentSessionId?: string | null; path?: string | null; sessionId?: string | null; source?: string; stages?: Record<string, string>; status?: string | null; task?: string | null; })[]noDefined named agents.

agent.spawn ​

Direction: client → server

Run a named agent on a task.

Params

fieldtyperequireddescription
modelstring | nullnoRun this one spawn on a specific model: a models.profiles id, a 'vendor:model' pair, or a bare vendor. Outranks the agent's own assignment; null uses the configured routing.
namestringyesAgent to run.
sessionIdstring | nullnoParent session, when spawned from one.
taskstringyesTask handed to the agent.

Result

fieldtyperequireddescription
agentIdstringyesId correlating the subagent.* events.

approval.ask ​

Direction: client → server

Escalate one host action through the approval pipeline. The approver's approval.request carries tool, args with detail nested under args.detail and the site under args.site, note = reason, site, and scopeHint 'site' when a site is known. A local dev server navigation (tool 'repl.navigate', args.reasonCode 'localDevServer', args.url, args.project) gets scopeHint 'project': a 'project' answer stores a rule for the session's project and the URL's origin that only such asks match.

Params

fieldtyperequireddescription
argsRecord<string, unknown>noAction details to show.
callIdstring | nullnoThe tool.invoke callId, if any.
detailRecord<string, unknown> | nullnoWhat the running code is about to do, e.g. {origin, element, action}; shown with the approval and merged into its args.
forceAskbooleannoAlways ask a person: the mode matrix may only deny (plan still denies write, send and config; a read is asked) and never auto-allows, not even in auto mode. The allowlist still applies unless risk is 'payment'. For any client's destructive or irreversible actions.
permission"read" | "write" | "exec" | "network" | "send" | "config" | "delegate" | "secret"yesPermission class of the escalated action.
reasonstringyesWhat will happen, shown to the person approving.
riskstring | nullnoRisk hint shown with the approval; default from the permission. 'payment' also means: the allowlist is never consulted and the answer is never stored beyond this one call (scope is coerced to 'once').
sessionIdstringyesSession whose tool call is running.
sitestring | nullnoOrigin of the page, e.g. https://github.com; derived from detail.origin or args.url if omitted.
toolstringyesHost tool asking; the allowlist is keyed by it.

Result

fieldtyperequireddescription
bystringnoWho decided: 'user' (a person answered), 'allowlist', 'mode' (the mode matrix), 'readOnly' (a read-only delegation refuses changes and never asks; 1.14.0), or 'timeout' / 'interrupted' (denied without an answer).
decision"allow" | "deny"yesallow or deny.
scope"once" | "session" | "project" | "always" | "site"noScope the answer applies to; always 'once' for payment. 'project' only for project-safe actions (repl.files, a localDevServer repl.navigate); 'always' for a page action only for repl.tabs, repl.clipboard and (1.13.0) repl.read and repl.attach, others are kept to 'once'. For args.onceOnly (1.12.0) the scope the person picked, which core never stores: the host may keep it on its side.

approval.list ​

Direction: client → server

List tool calls still waiting for a decision.

Params

fieldtyperequireddescription
sessionIdstring | nullnoScope the listing to one session; omit for the global set.

Result

fieldtyperequireddescription
requests({ args?: Record<string, unknown>; guard?: string | null; note?: string; requestId: string; risk?: string; scopeHint?: "once" | "session" | "project" | "always" | "site"; sessionId: string; site?: string | null; timeoutSec?: number; tool: string; })[]noApprovals still pending.

approval.request ​

Direction: server → client

Ask the client to approve a tool call.

Params

fieldtyperequireddescription
argsRecord<string, unknown>noArguments it wants to use.
guardstring | nullnoWhy this is asked whatever the mode (1.24.0): 'agent-switch' for a call in the rest of a turn session.setAgent {guardTurn} guarded. Such an answer is never remembered.
notestringnoExtra warning shown with the prompt, e.g. "modifies snowpea configuration".
requestIdstringyesId to answer with approval.respond.
riskstringnoRisk hint for the UI.
scopeHint"once" | "session" | "project" | "always" | "site"noScope the UI should preselect.
sessionIdstringyesSession whose turn is blocked.
sitestring | nullnoOrigin (scheme://host) a 'site' scope would store the answer for (1.6.0).
timeoutSecnumbernoSeconds before the request auto-denies.
toolstringyesTool the model wants to run.

Result

fieldtyperequireddescription
decision"allow" | "deny"yesThe human's decision.
reasonstringnoWhy the human refused; quoted back to the model as the tool's refusal so the next turn can answer it (M15b §1).
scope"once" | "session" | "project" | "always" | "site"noHow long the decision applies.

approval.respond ​

Direction: client → server

Answer a pending approval and unblock the turn.

Params

fieldtyperequireddescription
decision"allow" | "deny"yesallow runs the tool, deny ends the turn.
reasonstringnoWhy the human refused; quoted back to the model as the tool's refusal so the next turn can answer it (M15b §1).
requestIdstringyesRequest being answered.
scope"once" | "session" | "project" | "always" | "site"noHow long the decision applies.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

audio.capabilities ​

Direction: client → server

Report what voice input and output can do on this machine.

Params

No params (send {}).

Result

fieldtyperequireddescription
autoSpeakbooleannoTrue when replies are spoken without being asked.
playbooleannoTrue when the daemon can play audio itself.
playersstring[]noAudio players found on PATH.
reasonsRecord<string, string>noPer-capability explanation of why it is off.
recordbooleannoTrue when the microphone can be recorded.
recordersstring[]noRecorders found on PATH.
sttstring | nullnoTranscription backend in use, or null when there is none.
sttEffectivestring | nullnoThe engine actually in use, or null when none is pinned or it is missing.
sttLanguagestringno'auto' (the engine detects, or the reply language decides) or the BCP-47 tag audio.stt.language forces.
sttLanguageSourcestringnoWhich rung decided it: setting | reply | detect. 'detect' means the engine works it out itself and nothing had to choose.
sttPinnedbooleannoTrue when audio.stt.provider names an engine. False means unset, which means voice input is off: there is no fallback chain.
sttProvidersstring[]noEvery usable transcription backend, preferred first.
ttsbooleannoTrue when speech synthesis is available.
ttsEffectivestring | nullnoThe speech engine actually in use, or null.
ttsPinnedbooleannoTrue when audio.tts.provider names an engine.
ttsProviderstring | nullnoSpeech backend in use.
ttsProvidersstring[]noEvery usable speech backend, preferred first.
voicestring | nullnoConfigured voice, when one is set.

audio.install ​

Direction: client → server

Install a local voice engine (or one of its voices) and re-run detection.

Params

fieldtyperequireddescription
enginestringyesEngine id from the setup catalog: faster-whisper (or local-whisper), piper, edge-tts. A system package (espeak-ng, say, powershell) answers ok=false with a hint instead.
voicestring | nullnoInstall one of the engine's voices rather than the engine itself, e.g. piper's ko_KR-kss-medium. Same staged progress; installing a voice does not select it.
warmupbooleannoWhen true, download first-run assets only — Supertonic's ONNX models — with staged progress, without reinstalling the package.

Result

fieldtyperequireddescription
enginestringyesEngine that was attempted, after id normalisation.
hintstring | nullnoWhat to do instead, when ok is false: the platform's own install command for a system package, or why the attempt could not run.
logstringnoTail of the installer's combined output, newest last; may be empty.
okbooleanyesTrue when the engine is installed and now detected.
voicestring | nullnoThe voice that was installed, when the request named one.

audio.record.start ​

Direction: client → server

Start recording the microphone.

Params

fieldtyperequireddescription
sessionIdstring | nullnoSession the recording belongs to.

Result

fieldtyperequireddescription
mimestringnoMedia type of the recording.
pathstringyesWav file being written, or the finished recording.
providerstring | nullnoBackend that transcribed it.
recordingbooleanyesTrue while capture is still running.
textstring | nullnoTranscript, when 'stop' was asked to transcribe.

audio.record.stop ​

Direction: client → server

Stop the recording and return the wav it wrote.

Params

fieldtyperequireddescription
sessionIdstring | nullnoSession that is recording.
transcribebooleannoAlso transcribe the recording and return its text.

Result

fieldtyperequireddescription
mimestringnoMedia type of the recording.
pathstringyesWav file being written, or the finished recording.
providerstring | nullnoBackend that transcribed it.
recordingbooleanyesTrue while capture is still running.
textstring | nullnoTranscript, when 'stop' was asked to transcribe.

audio.speak ​

Direction: client → server

Synthesise speech, optionally playing it on the daemon's machine.

Params

fieldtyperequireddescription
languagestring | nullnoBCP-47 language for voice selection; defaults to the stt language setting.
playbooleannoPlay on the daemon's machine instead of returning only a path.
providerstring | nullnoSpeech backend to use for this call only. When set, the pinned voice-out engine is not required — settings screens use this to preview before saving.
sessionIdstring | nullnoSession the audio belongs to.
textstringyesWhat to say.
voicestring | nullnoVoice id; defaults to the setting.

Result

fieldtyperequireddescription
mimestringyesMedia type of that file.
pathstringyesAudio file the speech was written to.
playedbooleannoTrue when the daemon played it.
providerstringyesBackend that synthesised it.
voicestring | nullnoVoice that was used.

audio.transcribe ​

Direction: client → server

Transcribe recorded audio to text.

Params

fieldtyperequireddescription
datastring | nullnoBase64 (or data-URI) audio.
languagestring | nullnoBCP-47 hint for the backend.
mimestring | nullnoMedia type of the audio, e.g. audio/wav.
pathstring | nullnoAudio file on the daemon's machine.
sessionIdstring | nullnoSession the audio belongs to.

Result

fieldtyperequireddescription
providerstringyesBackend that produced the transcript.
textstringyesWhat the backend heard.

audio.voices ​

Direction: client → server

List the voices one speech engine offers here.

Params

fieldtyperequireddescription
enginestringyesEngine id, e.g. supertonic, piper, edge-tts.
languagesstring[]noFilter a large catalogue to these BCP-47 tags; empty uses ko and en plus the session's reply language. Ignored by engines with few voices.

Result

fieldtyperequireddescription
voices({ gender?: string | null; id: string; installed?: boolean; label: string; language?: string; sample?: boolean; sizeBytes?: number | null; })[]noInstalled voices first, then by language and id.

backend.set ​

Direction: client → server

Choose where a session's tools execute: local, docker or ssh.

Params

fieldtyperequireddescription
configRecord<string, unknown>noBackend settings, e.g. container or SSH target.
kind"local" | "docker" | "ssh"yesWhere tools execute.
sessionIdstringyesSession whose execution backend changes.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

checkpoint.delete ​

Direction: client → server

Delete one checkpoint, or all checkpoints for a session.

Params

fieldtyperequireddescription
idstring | nullnoCheckpoint to delete; omitted deletes the whole session set.
sessionIdstringyesSession whose checkpoints are deleted.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

checkpoint.diff ​

Direction: client → server

Show what restoring a checkpoint would change from the current workdir.

Params

fieldtyperequireddescription
idstringyesCheckpoint id.
pathsstring[] | nullnoOptional subset of relative paths to diff.
sessionIdstringyesSession whose checkpoint is inspected.
throughbooleannoTrue means restore to before this turn, considering this and all later turns in the session.

Result

fieldtyperequireddescription
files({ binary?: boolean; changedSince?: boolean; patch: string; path: string; restorable?: boolean; })[]noPer-file diffs.

checkpoint.list ​

Direction: client → server

List restore checkpoints for a session, newest first.

Params

fieldtyperequireddescription
sessionIdstringyesSession whose checkpoints are listed.

Result

fieldtyperequireddescription
checkpoints({ createdAt: string; files?: ({ afterSha?: string | null; beforeSha?: string | null; path: string; restorable?: boolean; size?: number; skipped?: "too_large" | "excluded" | "unreadable" | null; source: "tool" | "shell"; status: "modified" | "created" | "deleted"; })[]; id: string; kind: "turn" | "restore"; prompt?: string; sessionId: string; turnId?: string | null; workdir: string; })[]noCheckpoints, newest first.

checkpoint.restore ​

Direction: client → server

Restore files to their before-turn state, optionally through later turns.

Params

fieldtyperequireddescription
dryRunbooleannoReport what would happen without writing files.
forcebooleannoRestore even when a file changed since capture.
idstringyesCheckpoint id.
pathsstring[] | nullnoOptional subset of relative paths to diff.
sessionIdstringyesSession whose checkpoint is inspected.
throughbooleannoTrue means restore to before this turn, considering this and all later turns in the session.

Result

fieldtyperequireddescription
checkpointIdstring | nullnoRestore checkpoint id, null for dry-run or no writes.
restoredstring[]noPaths restored.
skipped({ path: string; reason: "changed_since" | "not_restorable" | "missing_blob" | "excluded"; })[]noPaths that were not restored and why.

command.list ​

Direction: client → server

List the slash commands available to a session.

Params

fieldtyperequireddescription
sessionIdstring | nullnoScope the listing to one session; omit for the global set.

Result

fieldtyperequireddescription
commands({ argsSchema?: Record<string, unknown>; name: string; source?: string; summary: string; })[]noAvailable slash commands.

command.run ​

Direction: client → server

Run a slash command; the only execution path for them.

Params

fieldtyperequireddescription
argsstringnoRaw argument string, as typed after the name.
namestringyesCommand name without the leading slash.
sessionIdstringyesSession to run the command in.

Result

fieldtyperequireddescription
turnIdstringyesId of the started turn; turn.done carries it back.

file.complete ​

Direction: client → server

Complete file and directory paths under a session workdir.

Params

fieldtyperequireddescription
limitnumber | nullnoMaximum entries to return (default 30, max 200).
querystringnoPartial path to match.
sessionIdstring | nullnoSession whose workdir to complete in.
workdirstring | nullnoWorkdir to complete in when no session is set.

Result

fieldtyperequireddescription
entries({ kind: "file" | "dir"; path: string; size?: number | null; })[]noMatching paths, best first.
truncatedbooleannoTrue when more matches exist than returned.

gateway.bind ​

Direction: client → server

Attach the daemon to a chat platform channel.

Params

fieldtyperequireddescription
channelIdstring | nullnoRestrict the binding to one chat, channel or room.
credentialsRefstringyesName of the credential to use: a key in credentials.json or an env var.
platformstringyesChat platform key: telegram, discord or slack.
targetRecord<string, unknown>yesWhat the conversation talks to: {'agent': name}, {'session': id} or {'new_session': {'workdir': path, 'mode': mode}}.
userIdstring | nullnoPlatform user allowed to answer approvals from chat.

Result

fieldtyperequireddescription
bindingIdstringyesId used to unbind later.

gateway.list ​

Direction: client → server

List live gateway bindings.

Params

No params (send {}).

Result

fieldtyperequireddescription
bindings({ bindingId: string; channelId?: string | null; credentialsRef?: string; platform: string; source?: string; state?: "active" | "inactive"; target: string; userId?: string | null; })[]noLive gateway bindings.

gateway.sync ​

Direction: client → server

Reconcile the messenger bindings with settings.gateway.

Params

No params (send {}).

Result

fieldtyperequireddescription
addedstring[]noPlatforms that started listening.
keptstring[]noPlatforms that were already listening.
removedstring[]noPlatforms whose auto binding was dropped.

gateway.unbind ​

Direction: client → server

Detach a gateway binding.

Params

fieldtyperequireddescription
bindingIdstringyesBinding to remove.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

job.cancel ​

Direction: client → server

Cancel a scheduled job.

Params

fieldtyperequireddescription
jobIdstringyesTarget job.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

job.delete ​

Direction: client → server

Delete a job, its schedule and run history; optionally its run sessions.

Params

fieldtyperequireddescription
deleteRunsbooleannoAlso delete the sessions its runs opened, with their workspaces, as session.deleteSaved does. A run still in progress is left alone.
jobIdstringyesJob to delete, with its schedule and run history.

Result

fieldtyperequireddescription
deletedSessionsnumbernoRun sessions deleted with it.
jobIdstringyesThe deleted job.

job.list ​

Direction: client → server

List scheduled jobs and their next run times.

Params

No params (send {}).

Result

fieldtyperequireddescription
jobs({ catchUpWindowMinutes?: number; channel?: string | null; createdVia?: "rpc" | "tool"; enabled?: boolean; fingerprint?: string | null; held?: { scheduledAt: string; status: "waiting_for_host" | "missed"; } | null; jobId: string; kind?: "cron" | "once" | "interval"; lastRunAt?: string | null; lastStatus?: "ok" | "error" | "denied_by_timeout" | null; meta?: Record<string, unknown> | null; mode?: "plan" | "accept" | "auto"; nextRunAt?: string | null; originSessionId?: string | null; owned?: boolean; ownerClientId?: string | null; spec: string; state?: "scheduled" | "running" | "cancelled"; task: string; })[]noKnown jobs.

job.nextRunForClient ​

Direction: client → server

When a host should be awake for its routines (addendum 11).

Params

fieldtyperequireddescription
clientIdstringyesA host's clientId (a browser profile).

Result

fieldtyperequireddescription
nextRunAtstring | nullnoEarliest run that needs this client's host: a held (waiting_for_host) occurrence or the next firing of a job whose hostToolsFrom is this clientId; null when none.

job.preview ​

Direction: client → server

Read a schedule spec without saving anything (1.10.0): its kind and when a job with it would first fire. An unreadable spec is invalid_params with job.schedule's message.

Params

fieldtyperequireddescription
specstringyesA schedule spec, read exactly as job.schedule reads it (1.10.0).

Result

fieldtyperequireddescription
kind"cron" | "once" | "interval"yesWhat the spec turned into.
nextRunAtstring | nullnoUTC ISO-8601 time a job with this spec would first fire if saved now. A spec that would never fire is invalid_params, as for job.schedule.
normalizedstring | nullnoThe parsed schedule: the cron expression for 'cron', 'every <n>s' for 'interval', 'once at <UTC ISO>' for 'once'.

job.runNow ​

Direction: client → server

Fire a scheduled job immediately.

Params

fieldtyperequireddescription
jobIdstringyesTarget job.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

job.schedule ​

Direction: client → server

Schedule a prompt to run unattended.

Params

fieldtyperequireddescription
agentstring | nullnoNamed agent that runs the task.
channelstring | nullnoGateway channel that receives the output.
metaRecord<string, unknown> | nullnoOpaque data for the host, at most 4 KB of JSON (1.23.0). Only a connection whose system.hello said clientKind 'browser' with a clientId may set it; the job is then owned by that clientId: only it may update, cancel, delete or run it now, see its meta, and no agent tool can change or cancel it.
mode"plan" | "accept" | "auto"noPermission mode for the unattended run.
sessionTemplate{ agent?: string | null; catchUpWindowMinutes?: number; hostToolsFrom?: string | null; hostWaitSec?: number; mode?: "plan" | "accept" | "auto" | null; } | nullnoSession setup for each run, incl. host tools (1.7.0).
specstringyesCron expression or natural-language schedule.
taskstringyesPrompt run on each firing.
workdirstring | nullnoWorking directory for the run; defaults to the daemon's home.

Result

fieldtyperequireddescription
fingerprintstring | nullnoFor a job with meta, the fingerprint its runs' tool.invoke job will carry (1.23.0). Seal this value; do not recompute it.
jobIdstringyesId of the scheduled job.
nextRunAtstring | nullnoUTC ISO-8601 time of the first firing.

job.update ​

Direction: client → server

Change an existing job (addendum 12).

Params

fieldtyperequireddescription
enabledboolean | nullnoFalse pauses the job (no next firing); true resumes it from now on its schedule.
jobIdstringyesJob to change.
schedulestring | nullnoA new schedule spec, parsed like job.schedule's spec; the next run is recomputed.
sessionTemplate{ catchUpWindowMinutes?: number | null; hostWaitSec?: number | null; } | nullnoTemplate fields to change.

Result

fieldtyperequireddescription
catchUpWindowMinutesnumbernoHow long a held run waits for its host before it is missed.
channelstring | nullnoChannel that receives the output.
createdVia"rpc" | "tool"no'rpc' for job.schedule, 'tool' for schedule_create or /schedule (1.23.0).
enabledbooleannoFalse once the job is cancelled or has run out.
fingerprintstring | nullnoThe fingerprint tool.invoke job carries; only the owner sees it.
held{ scheduledAt: string; status: "waiting_for_host" | "missed"; } | nullnoThe newest occurrence when it is waiting for its host or was missed (addendum 12); null otherwise.
jobIdstringyesJob id.
kind"cron" | "once" | "interval"noHow the spec repeats: a cron rule, a one-shot, or a fixed interval.
lastRunAtstring | nullnoUTC ISO-8601 time of the last firing, null before the first.
lastStatus"ok" | "error" | "denied_by_timeout" | nullnoHow the last run ended.
metaRecord<string, unknown> | nullnoThe job's meta; only the owner connection sees it.
mode"plan" | "accept" | "auto"noPermission mode for the run.
nextRunAtstring | nullnoUTC ISO-8601 time of the next firing.
originSessionIdstring | nullnoTUI/chat session that also receives every result.
ownedbooleannoTrue for a job with meta: only its owner may change, run or delete it.
ownerClientIdstring | nullnoThe owning browser clientId; only the owner sees it.
specstringyesSchedule as given.
state"scheduled" | "running" | "cancelled"noCurrent job state.
taskstringyesPrompt run on each firing.

llm.sample ​

Direction: client → server

One tool-less model call for a session's browser host (1.14.0): no tools, no history, nothing written to the transcript except a usage event. The session's host only ('unauthorized' otherwise); 'unavailable' when no model can answer; with schema, 'invalid_output' when the answer does not validate.

Params

fieldtyperequireddescription
inputstringyesPage-derived text; sent as the user message, fenced and marked untrusted.
maxTokensnumbernoOutput token cap, at most 4096.
modelCategory"fast" | "default"no'fast' = browser.fastModel (then models.categories.fast, then the session's model); 'default' = the session's model.
schemaRecord<string, unknown> | nullnoJSON Schema the answer must match. With it the model is told to answer JSON only, and an answer that does not validate is 'invalid_output'.
schemaAfterInputbooleannoPut the schema instruction after the fenced input (with task) instead of in the system message, for a schema that varies per call (1.21.0).
sessionIdstringyesSession whose provider settings and bill this call uses; its host only.
systemstring | nullnoInstructions the host wrote.
taskstring | nullnoTrusted per-call instruction from the host, placed after the fenced input, so system + page stay a prefix several samples of one page share (1.21.0).

Result

fieldtyperequireddescription
jsonunknownnoThe validated JSON value, when a schema was given.
modelstringyes'vendor:model' that answered.
textstring | nullnoThe answer, when no schema was given.
usage{ inputTokens?: number; outputTokens?: number; }yesTokens the call used.

lsp.catalog ​

Direction: client → server

List every registered language server, regardless of whether it has started.

Params

No params (send {}).

Result

fieldtyperequireddescription
servers({ disabled: boolean; extensions?: string[]; id: string; installHint?: string | null; installable: boolean; languageIds?: string[]; })[]noOne row per registered server id.

lsp.status ​

Direction: client → server

Report every language server the daemon has started and its state.

Params

No params (send {}).

Result

fieldtyperequireddescription
servers({ id: string; languageId?: string; pid?: number | null; root: string; state: "starting" | "ready" | "broken" | "stopped"; })[]noOne row per (server, root) pair.

mcp.add ​

Direction: client → server

Write an MCP server into the project or global .mcp.json and start it.

Params

fieldtyperequireddescription
argsstring[] | nullnoArguments, argv style; never a shell string.
commandstring | nullnoExecutable for a stdio server.
cwdstring | nullnoWorking directory for a stdio server.
disabledboolean | nullnoKeep the entry but never start the server.
envRecord<string, string> | nullnoEnvironment for the child process.
forcebooleannoOverwrite an existing entry and accept the security findings.
headersRecord<string, string> | nullnoHTTP headers sent with every request.
namestringyesServer name; ^[a-zA-Z0-9_-]{1,64}$.
permission"read" | "write" | "exec" | "network" | "send" | "config" | "delegate" | "secret" | nullnoPermission tag for the server's tools; stored in settings.
presetstring | nullnoCatalog id copied before the explicit fields are applied.
scope"project" | "global"noWhich file to write: $SNOWPEA_HOME/.mcp.json (global, the default since 1.23.0, so every project sees it) or the project's .mcp.json.
sessionIdstring | nullnoSession whose workdir to use.
testbooleannoProbe the server before saving; nothing is written if it fails.
timeoutSecnumber | nullnoStartup cap, in seconds.
toolTimeoutSecnumber | nullnoPer-call cap, in seconds.
toolsExcludestring[] | nullnoNever register these tools of the server.
toolsIncludestring[] | nullnoRegister only these tools of the server.
type"stdio" | "http" | "sse" | nullnoForce a transport instead of inferring it.
urlstring | nullnoEndpoint for an http or sse server.
workdirstring | nullnoProject directory for scope=project.

Result

fieldtyperequireddescription
errorstring | nullnoWhy the server did not start.
okbooleannoTrue when the entry was written.
pathstringyesFile the entry was written to.
state"stopped" | "starting" | "ready" | "error"noState of the server after the write.
tools({ description?: string; name: string; })[]noTools the probe found, so a client can offer a picker.
warningsstring[]noSecurity findings that --force accepted.

mcp.catalog ​

Direction: client → server

The curated MCP servers a client can offer as presets.

Params

No params (send {}).

Result

fieldtyperequireddescription
entries({ description?: string; entry?: Record<string, unknown>; homepage?: string; id: string; label: string; needs?: string[]; transport: "stdio" | "http" | "sse"; })[]noCurated servers, in display order.

mcp.list ​

Direction: client → server

List every configured MCP server with its scope, state and tools.

Params

fieldtyperequireddescription
sessionIdstring | nullnoSession whose workdir to read.
workdirstring | nullnoProject directory; defaults to the session's, then the daemon's.

Result

fieldtyperequireddescription
servers({ args?: string[]; command?: string | null; cwd?: string | null; disabled?: boolean; envKeys?: string[]; error?: string | null; headerKeys?: string[]; name: string; permission?: "read" | "write" | "exec" | "network" | "send" | "config" | "delegate" | "secret"; plugin?: string | null; scope: "project" | "global" | "plugin" | "settings"; state?: "stopped" | "starting" | "ready" | "error"; timeoutSec?: number | null; toolCount?: number; toolTimeoutSec?: number | null; tools?: ({ description?: string; name: string; })[]; toolsExclude?: string[]; toolsInclude?: string[]; transport: "stdio" | "http" | "sse"; url?: string | null; })[]noOne row per configured server, project entries winning.

mcp.reload ​

Direction: client → server

Restart one MCP server, or every configured one.

Params

fieldtyperequireddescription
namestring | nullnoServer to restart; all of them when absent.
sessionIdstring | nullnoSession whose workdir to use.
workdirstring | nullnoProject directory to rediscover from.

Result

fieldtyperequireddescription
okbooleannoTrue when the reload ran.
serversstring[]noServers that were restarted.

mcp.remove ​

Direction: client → server

Delete an MCP server entry and stop the server.

Params

fieldtyperequireddescription
namestringyesServer name.
scope"project" | "global" | nullnoWhich file to rewrite; omitted, the one that declares it.
sessionIdstring | nullnoSession whose workdir to use.
workdirstring | nullnoProject directory for scope=project.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

mcp.test ​

Direction: client → server

Probe a saved MCP server or an unsaved draft and report its tools.

Params

fieldtyperequireddescription
argsstring[] | nullnoArguments, argv style; never a shell string.
commandstring | nullnoExecutable for a stdio server.
cwdstring | nullnoWorking directory for a stdio server.
disabledboolean | nullnoKeep the entry but never start the server.
envRecord<string, string> | nullnoEnvironment for the child process.
headersRecord<string, string> | nullnoHTTP headers sent with every request.
namestring | nullnoSaved server to probe.
permission"read" | "write" | "exec" | "network" | "send" | "config" | "delegate" | "secret" | nullnoPermission tag for the server's tools; stored in settings.
scope"project" | "global" | "plugin" | "settings" | nullnoScope of the saved server.
sessionIdstring | nullnoSession whose workdir to use.
timeoutSecnumber | nullnoStartup cap, in seconds.
toolTimeoutSecnumber | nullnoPer-call cap, in seconds.
toolsExcludestring[] | nullnoNever register these tools of the server.
toolsIncludestring[] | nullnoRegister only these tools of the server.
type"stdio" | "http" | "sse" | nullnoForce a transport instead of inferring it.
urlstring | nullnoEndpoint for an http or sse server.
workdirstring | nullnoProject directory for scope=project.

Result

fieldtyperequireddescription
elapsedMsnumbernoHow long the probe took.
errorstring | nullnoSpawn or protocol error, verbatim.
okbooleanyesTrue when the server answered tools/list.
state"stopped" | "starting" | "ready" | "error"yesready when the probe succeeded, error otherwise.
tools({ description?: string; name: string; })[]noWhat the server exposes.

mcp.update ​

Direction: client → server

Merge a patch into an existing MCP server entry.

Params

fieldtyperequireddescription
namestringyesServer name.
patch{ args?: string[] | null; command?: string | null; cwd?: string | null; disabled?: boolean | null; env?: Record<string, string> | null; headers?: Record<string, string> | null; permission?: "read" | "write" | "exec" | "network" | "send" | "config" | "delegate" | "secret" | null; timeoutSec?: number | null; toolTimeoutSec?: number | null; toolsExclude?: string[] | null; toolsInclude?: string[] | null; type?: "stdio" | "http" | "sse" | null; url?: string | null; }noKeys to change; anything absent is kept.
scope"project" | "global" | nullnoWhich file to rewrite; omitted, the one that declares it.
sessionIdstring | nullnoSession whose workdir to use.
workdirstring | nullnoProject directory for scope=project.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

memory.delete ​

Direction: client → server

Forget one stored memory.

Params

fieldtyperequireddescription
beforestring | nullnoWith source: UTC ISO time; forget visits before it.
idstring | nullnoMemory id to forget.
source"browser" | nullno"browser" forgets browsing memories instead: those of url (a page, or a whole site when it has no path), those visited before before, or all (1.7.0).
urlstring | nullnoWith source: the page or site.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

memory.ingest ​

Direction: client → server

Remember visited pages in the browser namespace, once per url and text.

Params

fieldtyperequireddescription
items({ text?: string; title?: string; url: string; visitedAt?: string | null; })[]yesVisited pages to remember.
sessionIdstring | nullnoSession they came from, if any.

Result

fieldtyperequireddescription
addednumbernoPages stored.
removednumbernoFor memory.delete by source: how many.
skippednumbernoPages already stored (same url and text).

memory.list ​

Direction: client → server

List stored memories by scope, newest first.

Params

fieldtyperequireddescription
limitnumbernoMaximum number of entries.
projectstring | nullnoProject root to use instead of a session's, so a CLI in a checkout can list that project's memories without opening a session.
querystring | nullnoFree-text filter; omit to list newest first.
scope"project" | "global" | "agent" | "all" | nullnoWhich scopes to list: "project", "global", "agent" or "all" (default).
sessionIdstring | nullnoSession whose project and agent scopes to resolve; omit for global only.

Result

fieldtyperequireddescription
entries({ createdAt?: string; id: string; project?: string; scope?: "project" | "global" | "agent" | "all"; tags?: string[]; text: string; })[]noMatching memories, newest or best first.

Direction: client → server

Recall stored memories matching a query.

Params

fieldtyperequireddescription
limitnumbernoMaximum number of hits.
namespacestring | nullnoMemory namespace to search; defaults to "default". Never crosses namespaces.
querystringyesFree-text query.

Result

fieldtyperequireddescription
hits({ id: string; project?: string; scope?: "project" | "global" | "agent" | "all"; score?: number; tags?: string[]; text: string; })[]noMatches, best first.

memory.write ​

Direction: client → server

Store a memory with tags.

Params

fieldtyperequireddescription
namespacestring | nullnoMemory namespace to write into; defaults to "default".
tagsstring[]noTags for later filtering.
textstringyesText to remember.

Result

fieldtyperequireddescription
idstringyesId of the stored memory.

permission.allowlist.add ​

Direction: client → server

Promote a pattern from ask to allow.

Params

fieldtyperequireddescription
patternstringyesGlob or command prefix promoted from ask to allow.
scope"session" | "project" | "always"noWhere the pattern is stored.
workdirstring | nullnoAbsolute folder of the project to use (its .snowpea/settings.json). Default: the caller's most recent session's workdir (1.7.0).

Result

fieldtyperequireddescription
patternIdstringyesId used to remove the pattern later.

permission.allowlist.list ​

Direction: client → server

List stored allowlist patterns.

Params

fieldtyperequireddescription
hostToolsFromstring | nullnoOnly this browser profile's global entries (plus project entries); omit for every entry (addendum 8).
scope"session" | "project" | "always" | nullnoFilter by scope; omit for all.
workdirstring | nullnoAbsolute folder of the project to use (its .snowpea/settings.json). Default: the caller's most recent session's workdir (1.7.0).

Result

fieldtyperequireddescription
patterns({ createdAt?: string | null; hostToolsFrom?: string | null; origin?: string | null; pattern: string; patternId: string; reasonCode?: string | null; scope: "session" | "project" | "always"; tool?: string | null; })[]noStored allowlist entries.

permission.allowlist.remove ​

Direction: client → server

Delete an allowlist pattern by id.

Params

fieldtyperequireddescription
hostToolsFromstring | nullnoWhen given, a global entry is removed only if it belongs to this browser profile (addendum 8).
patternIdstringyesPattern to delete.
workdirstring | nullnoAbsolute folder of the project to use (its .snowpea/settings.json). Default: the caller's most recent session's workdir (1.7.0).

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

provider.configure ​

Direction: client → server

Store settings and credentials for a provider.

Params

fieldtyperequireddescription
configRecord<string, unknown>noVendor-specific settings, including credentials.
vendorstringyesVendor to configure.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

provider.list ​

Direction: client → server

List chat providers and whether they are configured.

Params

No params (send {}).

Result

fieldtyperequireddescription
providers({ authMethods?: string[]; authStatus?: "unconfigured" | "active" | "expired"; baseUrl?: string; configured?: boolean; custom?: boolean; default?: boolean; defaultBaseUrl?: string; defaultModel?: string; label?: string; models?: string[]; preset?: string; supportsEffort?: boolean; variant?: string; vendor: string; })[]noKnown chat providers.

provider.loginWeb ​

Direction: client → server

Start a browser-based login flow for a provider.

Params

fieldtyperequireddescription
methodstringyesLogin flow to start: 'browser_pkce' or 'google_oauth' (browser), 'device_code' or 'google_adc' (headless), 'oauth_pkce' (OpenRouter). 'web' or an empty value picks the best flow this machine can complete.
vendorstringyesVendor to log into.

Result

fieldtyperequireddescription
expiresInSecnumber | nullnoSeconds until the code or session expires, when known.
okbooleannoTrue when the call succeeded.
status"await_user" | "done" | "failed"no'await_user' once userCode/verificationUri are ready and polling has started in the background; 'done' or 'failed' if the flow finished synchronously before this response was sent.
userCodestring | nullnoShort code the user types in, for device-code flows.
verificationUristring | nullnoURL to open to approve the login.
verificationUriCompletestring | nullnoverificationUri with the code already embedded, when known.

provider.models ​

Direction: client → server

Ask a vendor's endpoint which models it serves.

Params

fieldtyperequireddescription
vendorstring | nullnoVendor to query; defaults to the configured one.

Result

fieldtyperequireddescription
currentstringnoModel this vendor uses today.
detailstringnoOne line naming the source, for a picker to show.
errorstring | nullnoWhy the live listing could not be used, when source is not 'live' (1.17.0); absent when the vendor answered or publishes no listing.
modelsstring[]noModel ids the vendor's endpoint reports. Whatever the source, models[0] is the recommended default (a ChatGPT account's first-priority model, the newest chat model for an API key), so a picker can take current or models[0].
sourcestringnoWhich rung answered: live (the vendor's endpoint), settings (providers.<vendor>.models), cache (the last good listing) or curated (this build's list, merged with models.dev).
vendorstringyesVendor the listing came from.
visionRecord<string, boolean>noWhich of the listed models can be sent images, when that is known. A model missing from this map is unknown rather than text-only, so a picker draws no badge for it instead of a negative one.

provider.remove ​

Direction: client → server

Forget a configured provider, typically a named local server.

Params

fieldtyperequireddescription
vendorstringyesProvider to forget: its credentials, its model profiles and the agent assignments that used them.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

provider.test ​

Direction: client → server

Send one short completion to check a provider and model.

Params

fieldtyperequireddescription
modelstring | nullnoModel; defaults to the vendor's default.
providerstringyesVendor to test.

Result

fieldtyperequireddescription
errorstring | nullnoWhy it failed.
latencyMsnumbernoRound-trip time of the test call.
modelstringnoModel the request used.
modelEchostring | nullnoModel name the server reported, when it did.
okbooleanyesTrue when a one-line completion came back.
providerstringyesVendor tested.
replystring | nullnoThe model's reply, trimmed.

question.list ​

Direction: client → server

List questions the agent is still waiting on.

Params

fieldtyperequireddescription
sessionIdstring | nullnoScope the listing to one session; omit for the global set.

Result

fieldtyperequireddescription
requests({ questions?: ({ allowOther?: boolean; header?: string; multi?: boolean; options?: ({ description?: string; label: string; preview?: string; })[]; question: string; secret?: boolean; })[]; requestId: string; sessionId: string; timeoutSec?: number; })[]noQuestions still waiting for an answer.

question.request ​

Direction: server → client

Ask the client to put a question to the human.

Params

fieldtyperequireddescription
questions({ allowOther?: boolean; header?: string; multi?: boolean; options?: ({ description?: string; label: string; preview?: string; })[]; question: string; secret?: boolean; })[]noThe questions, in the order they were asked.
requestIdstringyesId to answer with question.respond.
sessionIdstringyesSession whose turn is blocked.
timeoutSecnumbernoSeconds before the batch gives up.

Result

fieldtyperequireddescription
answers({ selected?: string[]; text?: string | null; })[]noOne entry per question, in question order.

question.respond ​

Direction: client → server

Answer a pending question and unblock the turn.

Params

fieldtyperequireddescription
answers({ selected?: string[]; text?: string | null; })[]noOne entry per question, in question order; empty declines the batch.
requestIdstringyesBatch being answered.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

session.artifacts ​

Direction: client → server

Files the session saved for the user under its workspace's artifacts/.

Params

fieldtyperequireddescription
sessionIdstringyesTarget session.

Result

fieldtyperequireddescription
artifacts({ mimeType?: string | null; modifiedAt: string; name: string; path: string; size: number; })[]noFiles under artifacts/, newest first.
workspaceDirstringyesThe session workspace.

session.attach ​

Direction: client → server

Make this connection the origin of a session (approvals, host tools).

Params

fieldtyperequireddescription
hostToolsFromstring | nullnoRe-point the session's host tools to this clientId (or surface id). It must name an open connection whose clientKind is 'browser'. Persisted; emits sessions.changed (reason 'host').
localestring | nullnoThe client's UI language as a BCP 47 tag (1.7.0), as on session.create. Kept in memory only, so a client re-sends it after a daemon restart; omitted leaves the session's current locale.
sessionIdstringyesSession this connection becomes the origin of (1.6.0).

Result

fieldtyperequireddescription
hostToolsstring[]noHost tools the session now sees.
hostToolsFromstring | nullnoThe session's hostToolsFrom after the call; older cores omit it.
sessionIdstringyesThe attached session.

session.attachments ​

Direction: client → server

Files the user attached in this session, with the path of the original bytes the agent may use (1.23.0). A delegated child reports its root's.

Params

fieldtyperequireddescription
sessionIdstringyesTarget session.

Result

fieldtyperequireddescription
attachments({ byPath?: boolean; messageId?: string | null; mime: string; name: string; path: string; size: number; })[]noThis session's attachments, oldest first.

session.close ​

Direction: client → server

Close a session and release its resources.

Params

fieldtyperequireddescription
sessionIdstringyesTarget session.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

session.compact ​

Direction: client → server

Summarise the conversation so far and replace the history with it.

Params

fieldtyperequireddescription
instructionsstring | nullnoExtra guidance for the summary, e.g. 'keep the API design decisions'.
sessionIdstringyesSession whose history to compact.

Result

fieldtyperequireddescription
afternumbernoEstimated tokens the history holds now.
beforenumbernoEstimated tokens the history held before.
summaryCharsnumbernoLength of the summary in characters.

session.continue ​

Direction: client → server

Continue a chat session on the system's behalf, e.g. after a human hand-back (1.8.0). A running turn gets the note at its next model call (like session.notice); otherwise a turn starts whose input is the [system] note, with turn.started initiator 'system' and no message.user. Same callers as session.setAgent; subagent and scheduled sessions are refused with 'invalid_params'. One system start per session per 10 s, and an idempotencyKey is honoured once; a call inside the 10 s window keeps its note as a notice (queued: true).

Params

fieldtyperequireddescription
idempotencyKeystring | nullnoThe same key twice: the second call is a no-op.
notestringyesThe [system] line the model sees, e.g. 'the tab is back'.
reasonstringnoWhy the session continues, e.g. 'handback'.
sessionIdstringyesA chat session the caller may drive.

Result

fieldtyperequireddescription
duplicateboolean | nullnoTrue when idempotencyKey was already used.
queuedboolean | nullnoTrue when a turn was running and the note joins its next model call.
startedbooleanyesTrue when a new system-initiated turn started.
turnIdstring | nullnoThe turn that started, if any.

session.create ​

Direction: client → server

Open a session rooted at a working directory.

Params

fieldtyperequireddescription
agentstring | nullnoNamed agent whose persona to load.
browserMemoryboolean | nullnoRecall also searches pages the browser ingested. Default: on when a browser client (clientKind 'browser') creates the session (1.7.0).
denyExecboolean | nullnoWhen true, refuse exec-tagged tools without prompting (headless CI).
effort"low" | "medium" | "high" | "max" | nullnoReasoning effort for this session; null follows the settings.
hostToolsFromstring | nullnoWhose host tools this session sees: a connection's clientId (or surface id). Default: the creating connection (1.6.0).
localestring | nullnoThe client's UI language as a BCP 47 tag, e.g. 'ko-KR' (1.7.0). With agent.replyLanguage 'auto', text the core writes for this session (/init, /ralph and delegated briefs) is in this language before any guess from what the user typed. Ignored when not a language tag.
maxConcurrentnumber | nullnoOverride for concurrent subagents.
mode"plan" | "accept" | "auto" | nullnoStarting mode; defaults to the project setting.
modelstring | nullnoModel id; defaults to the provider's default.
originSurfacestring | nullnoSurface that owns approvals for this session (TUI, gateway, ...).
providerstring | nullnoChat provider vendor; defaults to configured.
workdirstringyesAbsolute path the session operates in.

Result

fieldtyperequireddescription
delegationbooleannoWhether the session starts in delegation mode (the lead hands the work to its team): the session pin, else agents.delegateByDefault.
sessionIdstringyesId of the new session.
workspaceDirstring | nullnoSession workspace with tmp/ and artifacts/ (1.7.0).

session.deleteSaved ​

Direction: client → server

Delete saved sessions.

Params

fieldtyperequireddescription
allbooleannoDelete saved sessions from every directory.
deleteWorkspacebooleannoAlso delete each session's workspace ($SNOWPEA_HOME/sessions/<date>_<id>: tmp/, artifacts/, downloads) — it can hold page text the user deleted the chat to get rid of. false keeps it (1.7.0).
sessionIdstring | nullnoDelete one saved session.
workdirstring | nullnoDelete saved sessions rooted here.

Result

fieldtyperequireddescription
deletednumberno

session.interrupt ​

Direction: client → server

Stop the running turn as soon as possible.

Params

fieldtyperequireddescription
sessionIdstringyesTarget session.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

session.list ​

Direction: client → server

List live or saved sessions.

Params

fieldtyperequireddescription
hostToolsFromstring | nullnoOnly sessions owned by this client (a browser profile's clientId); omit for every session (addendum 8).
includeClosedbooleannoInclude persisted closed sessions.
includeUnhostedbooleannoWith hostToolsFrom: also return sessions with no host (IDE, TUI, CLI), which a browser shows in every profile.
kindsstring[] | nullnoOnly sessions of these kinds; omit for every kind. A surface that shows human threads asks for ["chat"] (CORE-session-kind).
workdirstring | nullnoOnly sessions rooted here.

Result

fieldtyperequireddescription
sessions({ agent?: string | null; browserProvider?: "host" | "local" | null; contextUsed?: number; contextWindow?: number | null; createdAt: string; effort?: "low" | "medium" | "high" | "max" | null; hostToolsFrom?: string | null; jobId?: string | null; kind?: "chat" | "scheduled" | "subagent" | "agent"; lastActivityAt?: string | null; lastPrompt?: string | null; mode: "plan" | "accept" | "auto"; model?: string | null; originSurface?: string | null; parentSessionId?: string | null; pendingApprovals?: number; pendingQuestions?: number; provider?: string | null; running?: boolean; seq?: number; sessionId: string; status?: "idle" | "running" | "awaiting_approval" | "awaiting_question" | "error"; title?: string | null; turnStartedAt?: string | null; workdir: string; workspaceDir?: string | null; })[]noEvery live session.

session.notice ​

Direction: client → server

Queue a [system] line for the model's next call.

Params

fieldtyperequireddescription
sessionIdstringyesSession to tell.
textstringyesSomething that happened outside a tool call (a popup opened, a download finished). Reaches the model as a [system] line before its next call; it starts no turn (1.7.0).

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

session.prompt ​

Direction: client → server

Send user text to a session and start a turn. Events: turn.started {turnId, prompt, queued}, then message.user {text, attachments, refs, steered: false}, then the model's output. message.user.text is what the user typed; a page attachment is listed as {kind: page, name, url, title} and only the model sees the rendered page. A steered prompt emits message.user {steered: true} + turn.dequeued {reason: steered}; a queued one emits turn.queued first.

Params

fieldtyperequireddescription
attachments({ data?: string | null; kind?: "file" | "image" | "text" | "page"; mimeType?: string | null; name?: string | null; path?: string | null; selection?: string | null; size?: number | null; snapshot?: string | null; text?: string | null; title?: string | null; url?: string | null; })[] | nullnoFiles or images to include.
sessionIdstringyesSession to prompt.
textstringyesUser text; a leading '/' is parsed as a slash command.
whenBusy"queue" | "steer" | nullnoIf a turn is running: 'queue' waits for it, 'steer' folds this prompt into it at the next tool round. Default: the agent.busy setting (1.7.0).

Result

fieldtyperequireddescription
turnIdstringyesId of the started turn; turn.done carries it back.

session.rename ​

Direction: client → server

Set a session's title.

Params

fieldtyperequireddescription
sessionIdstringyesSession to rename.
titlestringyesNew title; empty clears it (1.7.0).

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

session.resume ​

Direction: client → server

Replay the events a disconnected client missed.

Params

fieldtyperequireddescription
afterSeqnumber | nullnoReplay only events with a greater seq.
localestring | nullnoThe client's UI language as a BCP 47 tag (1.7.0), as on session.create. Kept in memory only, so a client re-sends it after a daemon restart; omitted leaves the session's current locale.
sessionIdstringyesSession to resume.

Result

fieldtyperequireddescription
delegationbooleannoWhether delegation mode is in force: the session pin, else the default.
effortstring | nullnoReasoning effort pinned on the session.
events({ kind: string; payload?: Record<string, unknown>; seq: number; sessionId: string; ts: string; })[]noMissed events in seq order.
mode"plan" | "accept" | "auto" | nullnoThe session's permission mode as restored, so a surface that resumes adopts it instead of keeping the mode it launched with.
modelstring | nullnoModel id in use.
providerstring | nullnoChat provider vendor in use.
sessionIdstringyesSession that was resumed.

session.setActive ​

Direction: client → server

Mark the session the user is looking at as the active one: a messenger with gateway.<platform>.shareActive posts its questions and approvals to the owner's chat. session.prompt and session.steer from a client do the same. Subagent and scheduled sessions are refused with 'invalid_params'.

Params

fieldtyperequireddescription
sessionIdstringyesTarget session.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

session.setAgent ​

Direction: client → server

Run a session as an agent definition, or as none (addendum 17). Only the session's origin connection, a browser session's hostToolsFrom host, or a non-browser surface (for a session it originated or that is not a browser session) may call it; others get 'unauthorized'.

Params

fieldtyperequireddescription
agentstring | nullnoAgent definition to run as from the next model call: its prompt (persona layer), tools allowlist ('*' = all) and max_tool_rounds. null clears it.
guardTurnbooleannoGuard the running turn (1.24.0): from now on every call that is not a read (read-only web tools included) and every mcp__ call is asked with forceAsk semantics — plan still denies; no mode, allowlist or cached answer allows it; approval.ask answers come back as 'once'. It covers sessions delegated from this one (also ones started later), a steer, and turns the agent queues for itself, and ends when the person's own next prompt starts a turn. No turn running: no effect.
sessionIdstringyesSession to switch.

Result

fieldtyperequireddescription
agentstring | nullnoAgent now in force.
guardedbooleannoTrue when a running turn is now guarded (guardTurn).
sessionIdstringyesThe session.

session.setBrowserProvider ​

Direction: client → server

Per-session opt-in to core's own browser; never global (addendum 9).

Params

fieldtyperequireddescription
provider"host" | "local"yes'host': only the Snowpea browser (the default for browser sessions; with no browser attached, browser tools fail with host_unavailable). 'local': the user explicitly allows core's own browser for this session only.
sessionIdstringyesSession whose browser tools to point (addendum 9).

Result

fieldtyperequireddescription
browserProvider"host" | "local"yesWhat it uses now.
sessionIdstringyesThe session.

session.setEffort ​

Direction: client → server

Pin how hard a session's model may think, or clear the pin.

Params

fieldtyperequireddescription
effort"low" | "medium" | "high" | "max" | nullnoOne of 'low', 'medium', 'high', 'max'. Null clears the pin and lets agent.effortBy / agent.effort decide again.
sessionIdstringyesSession to pin.

Result

fieldtyperequireddescription
effort"low" | "medium" | "high" | "max" | nullnoEffective reasoning effort after the change, clamped to what the model offers; null when the model has no effort setting.
effortSource"session" | "model" | "vendor" | "default"yesRule that decided it: the session pin, a model or vendor rule, or the default.
efforts("low" | "medium" | "high" | "max")[] | nullnoTiers the session's model offers; [] means it has no effort setting.
pinned"low" | "medium" | "high" | "max" | nullnoThe session's own pin; null when it follows the settings.
sessionIdstringyesSession that was pinned.

session.setMode ​

Direction: client → server

Switch a session between plan, accept and auto.

Params

fieldtyperequireddescription
mode"plan" | "accept" | "auto"yesNew permission mode.
sessionIdstringyesSession to change.

Result

fieldtyperequireddescription
mode"plan" | "accept" | "auto"yesMode now in effect.

session.setModel ​

Direction: client → server

Pin a session to a model profile, or clear the pin.

Params

fieldtyperequireddescription
modelstring | nullnoA models.profiles id, a 'vendor:model' pair, or a bare vendor name. Null or 'inherit' clears the pin and lets the configured routing decide.
sessionIdstringyesSession to pin.

Result

fieldtyperequireddescription
modelstring | nullnoModel id now in effect.
pinnedbooleannoFalse when the pin was cleared.
providerstring | nullnoVendor now in effect.

session.steer ​

Direction: client → server

Inject a user message into a running turn at its next tool round.

Params

fieldtyperequireddescription
sessionIdstringyesSession with a running turn.
textstringyesUser message injected at the running turn's next tool-round boundary; with no turn running it starts one like session.prompt (1.6.0).

Result

fieldtyperequireddescription
okbooleannoTrue when accepted.
startedbooleannoTrue when no turn was running and a new one started.

session.toolContent ​

Direction: client → server

A host tool result's content blocks with image bytes; results with images are kept on disk.

Params

fieldtyperequireddescription
callIdstringyestool.result callId whose content to fetch.
sessionIdstringyesSession the tool ran in.

Result

fieldtyperequireddescription
callIdstringyesThe call.
content({ contentRef?: string | null; data?: string | null; mediaType?: string | null; text?: string | null; type: "text" | "image"; })[]noThe content blocks, images with their bytes.

settings.get ​

Direction: client → server

Read global or project settings, with secrets masked.

Params

fieldtyperequireddescription
scope"global" | "project"no"global" reads $SNOWPEA_HOME/settings.json; "project" reads <workdir>/.snowpea/settings.json.
workdirstring | nullnoProject root; required when scope is "project".

Result

fieldtyperequireddescription
settingsRecord<string, unknown>yesThe effective settings document. Fields named api_key, token, refresh_token or password are masked as '***'.

settings.set ​

Direction: client → server

Deep-merge a patch into global or project settings and persist it.

Params

fieldtyperequireddescription
patchRecord<string, unknown>yesFields to deep-merge into the existing settings.
scope"global" | "project"no"global" writes $SNOWPEA_HOME/settings.json; "project" writes <workdir>/.snowpea/settings.json.
workdirstring | nullnoProject root; required when scope is "project".

Result

fieldtyperequireddescription
settingsRecord<string, unknown>yesThe effective settings document. Fields named api_key, token, refresh_token or password are masked as '***'.

setup.applyDefaults ​

Direction: client → server

Apply the profile's defaults for everything optional; idempotent.

Params

fieldtyperequireddescription
profile"default" | "browser"noWhich defaults to apply.

Result

fieldtyperequireddescription
appliedstring[]noSetting keys this call filled in because they were unset (absent or null).
skippedstring[]noProfile keys left alone because settings.json already holds a value.
status{ configuredProviders?: string[]; existingInstall?: boolean; optional?: ({ defaultApplied?: boolean | null; done: boolean; id: string; title: string; })[]; required?: ({ defaultApplied?: boolean | null; done: boolean; id: string; title: string; })[]; }yessetup.status after applying.

setup.catalog ​

Direction: client → server

The setup wizard's vendor, search, browser, tools and gateway catalogs.

Params

No params (send {}).

Result

fieldtyperequireddescription
browser({ active?: boolean; default?: boolean; defaultModel?: string; defaultModelSource?: string; description?: string; id: string; installHint?: string | null; installable?: boolean; key: string; label: string; recommended?: boolean; tags?: string[]; tier: string; })[]noBrowser-control providers.
gateway({ active?: boolean; default?: boolean; defaultModel?: string; defaultModelSource?: string; description?: string; id: string; installHint?: string | null; installable?: boolean; key: string; label: string; recommended?: boolean; tags?: string[]; tier: string; })[]noChat gateways (telegram, discord, slack), all off.
search({ active?: boolean; default?: boolean; defaultModel?: string; defaultModelSource?: string; description?: string; id: string; installHint?: string | null; installable?: boolean; key: string; label: string; recommended?: boolean; tags?: string[]; tier: string; })[]noWeb-search providers, ddgs first.
stt({ active?: boolean; default?: boolean; defaultModel?: string; defaultModelSource?: string; description?: string; id: string; installHint?: string | null; installable?: boolean; key: string; label: string; recommended?: boolean; tags?: string[]; tier: string; })[]noSpeech-to-text choices; active reflects what is usable on this machine.
tools({ active?: boolean; default?: boolean; defaultModel?: string; defaultModelSource?: string; description?: string; id: string; installHint?: string | null; installable?: boolean; key: string; label: string; recommended?: boolean; tags?: string[]; tier: string; })[]noTool categories and their default on/off state.
tts({ active?: boolean; default?: boolean; defaultModel?: string; defaultModelSource?: string; description?: string; id: string; installHint?: string | null; installable?: boolean; key: string; label: string; recommended?: boolean; tags?: string[]; tier: string; })[]noText-to-speech choices; active reflects what is usable on this machine.
vendors({ active?: boolean; default?: boolean; defaultModel?: string; defaultModelSource?: string; description?: string; id: string; installHint?: string | null; installable?: boolean; key: string; label: string; recommended?: boolean; tags?: string[]; tier: string; })[]noLLM vendors.

setup.status ​

Direction: client → server

What setup still needs; for the browser profile only a tested provider is required.

Params

fieldtyperequireddescription
profile"default" | "browser"noWhich setup flow is asking (1.6.0).

Result

fieldtyperequireddescription
configuredProvidersstring[]noVendors with credentials or a local endpoint.
existingInstallbooleannoTrue when this home already has a configured provider from an earlier setup.
optional({ defaultApplied?: boolean | null; done: boolean; id: string; title: string; })[]noItems with a usable default.
required({ defaultApplied?: boolean | null; done: boolean; id: string; title: string; })[]noItems that must be done before first use.

site.delete ​

Direction: client → server

Site memory (1.9.0): delete one entry, or every entry of an origin, in one browser profile. Same callers as site.list.

Params

fieldtyperequireddescription
entryIdstring | nullnoOne entry; omitted = all of them.
hostToolsFromstring | nullnoThe browser profile (its clientId). Required from a UI client; a browser client may only name its own.
originstringyesOrigin.

Result

fieldtyperequireddescription
deletednumberyesEntries removed.

site.get ​

Direction: client → server

Site memory (1.9.0): the entries stored for an origin in the caller's browser profile; with path, only those whose urlPattern matches it, most specific first; with pageType, only that one. Stale entries are included, flagged. Browser host clients only; entries are untrusted page-derived data and core never puts them in a prompt.

Params

fieldtyperequireddescription
originstringyesOrigin, e.g. 'https://www.example.com'.
pageTypestring | nullnoOnly this page type.
pathstring | nullnoPath (and query) on the origin: only entries whose urlPattern matches.

Result

fieldtyperequireddescription
entries({ actions?: ({ frames?: ({ origin: string; path: string; selector: string; })[] | null; kind: "click" | "fill" | "select" | "toggle" | "submit"; locators: ({ by: "role" | "label" | "text" | "placeholder" | "testid" | "css"; name?: string | null; role?: string | null; value?: string | null; })[]; loginField?: boolean; name: string; })[]; createdAt: string; entryId: string; failureCount?: number; fingerprint?: string | null; flows?: ({ expect?: "page" | "update" | null; name: string; stats?: { lastRun?: string | null; missed?: number; ok?: number; } | null; steps?: (string | { action?: string | null; intent?: string | null; verb: "fill" | "click" | "select" | "enter"; })[]; })[]; landmarks?: string[]; lastVerified: string; origin: string; pageType: string; pitfalls?: string[]; recipes?: ({ fields: ({ attr?: string | null; name: string; selector: string; })[]; intent?: string | null; item: string; name: string; stale?: boolean; stats?: { day?: number | null; hits?: number; misses?: number; } | null; })[]; stale?: boolean; successCount?: number; summary?: string; urlPattern: string; })[]noMost specific urlPattern first; stale entries included, flagged.

site.list ​

Direction: client → server

Site memory (1.9.0): one browser profile's remembered sites, by origin, for a settings UI. A browser client sees its own profile; any other owner client names one with hostToolsFrom.

Params

fieldtyperequireddescription
cursorstring | nullnoFrom the previous page.
hostToolsFromstring | nullnoThe browser profile (its clientId). Required from a UI client; a browser client may only name its own.
limitnumbernoMost sites per page.
originstring | nullnoOnly this origin.

Result

fieldtyperequireddescription
cursorstring | nullnoPass back for the next page.
sites({ entries: number; failureCount?: number; lastVerified: string; origin: string; pageTypes?: string[]; stale: number; successCount?: number; })[]noSites, by origin.

site.mark ​

Direction: client → server

Site memory (1.9.0): 'ok' counts a success, sets lastVerified and clears stale; 'stale' counts a failure and flags the entry until the next put. Browser host clients only.

Params

fieldtyperequireddescription
detailstring | nullnoFor the UI and log only.
entryIdstringyesThe entry.
originstringyesOrigin of the entry.
outcome"ok" | "stale"yes'ok' = verified use; 'stale' = it failed.

Result

fieldtyperequireddescription
entry{ actions?: ({ frames?: ({ origin: string; path: string; selector: string; })[] | null; kind: "click" | "fill" | "select" | "toggle" | "submit"; locators: ({ by: "role" | "label" | "text" | "placeholder" | "testid" | "css"; name?: string | null; role?: string | null; value?: string | null; })[]; loginField?: boolean; name: string; })[]; createdAt: string; entryId: string; failureCount?: number; fingerprint?: string | null; flows?: ({ expect?: "page" | "update" | null; name: string; stats?: { lastRun?: string | null; missed?: number; ok?: number; } | null; steps?: (string | { action?: string | null; intent?: string | null; verb: "fill" | "click" | "select" | "enter"; })[]; })[]; landmarks?: string[]; lastVerified: string; origin: string; pageType: string; pitfalls?: string[]; recipes?: ({ fields: ({ attr?: string | null; name: string; selector: string; })[]; intent?: string | null; item: string; name: string; stale?: boolean; stats?: { day?: number | null; hits?: number; misses?: number; } | null; })[]; stale?: boolean; successCount?: number; summary?: string; urlPattern: string; }yesThe entry after the mark.

site.markPart ​

Direction: client → server

Site memory (1.15.0): count one use of a flow or recipe of an entry without a put. The entry's successCount, failureCount, stale and lastVerified are untouched, so this never counts as verification. 'not_found' for an unknown entry, flow or recipe. Browser host clients only.

Params

fieldtyperequireddescription
entryIdstringyesThe entry.
namestringyesThe flow's or recipe's name.
originstringyesOrigin of the entry.
outcome"ok" | "miss" | "stale"yesflow: ok (stats.ok+1, lastRun) | miss (stats.missed+1). recipe: ok (hits+1, day, not stale) | miss (misses+1) | stale (misses+1, stale).
part"flow" | "recipe"yesWhich list the part is in.

Result

fieldtyperequireddescription
entry{ actions?: ({ frames?: ({ origin: string; path: string; selector: string; })[] | null; kind: "click" | "fill" | "select" | "toggle" | "submit"; locators: ({ by: "role" | "label" | "text" | "placeholder" | "testid" | "css"; name?: string | null; role?: string | null; value?: string | null; })[]; loginField?: boolean; name: string; })[]; createdAt: string; entryId: string; failureCount?: number; fingerprint?: string | null; flows?: ({ expect?: "page" | "update" | null; name: string; stats?: { lastRun?: string | null; missed?: number; ok?: number; } | null; steps?: (string | { action?: string | null; intent?: string | null; verb: "fill" | "click" | "select" | "enter"; })[]; })[]; landmarks?: string[]; lastVerified: string; origin: string; pageType: string; pitfalls?: string[]; recipes?: ({ fields: ({ attr?: string | null; name: string; selector: string; })[]; intent?: string | null; item: string; name: string; stale?: boolean; stats?: { day?: number | null; hits?: number; misses?: number; } | null; })[]; stale?: boolean; successCount?: number; summary?: string; urlPattern: string; }yesThe entry after the count.

site.put ​

Direction: client → server

Site memory (1.9.0): upsert an entry by (origin, pageType). Core checks the schema, refuses XPath, values on login fields and strings that look like personal data or credentials, and enforces 24 KB per entry (16 KB before 1.15.0) and 30 entries per origin ('invalid_params' naming the field); past 1,000 origins the least recently verified origin is dropped. A put clears stale and counts as a success. Browser host clients only.

Params

fieldtyperequireddescription
entry{ actions?: ({ frames?: ({ origin: string; path: string; selector: string; })[] | null; kind: "click" | "fill" | "select" | "toggle" | "submit"; locators: ({ by: "role" | "label" | "text" | "placeholder" | "testid" | "css"; name?: string | null; role?: string | null; value?: string | null; })[]; loginField?: boolean; name: string; })[]; fingerprint?: string | null; flows?: ({ expect?: "page" | "update" | null; name: string; stats?: { lastRun?: string | null; missed?: number; ok?: number; } | null; steps?: (string | { action?: string | null; intent?: string | null; verb: "fill" | "click" | "select" | "enter"; })[]; })[]; landmarks?: string[]; lastVerified?: string | null; pageType: string; pitfalls?: string[]; recipes?: ({ fields: ({ attr?: string | null; name: string; selector: string; })[]; intent?: string | null; item: string; name: string; stale?: boolean; stats?: { day?: number | null; hits?: number; misses?: number; } | null; })[]; summary?: string; urlPattern: string; }yesThe entry; upserted by (origin, pageType).
originstringyesOrigin the entry belongs to.

Result

fieldtyperequireddescription
createdbooleanyesTrue when no entry for (origin, pageType) existed.
entryIdstringyesThe entry's id.

skill.create ​

Direction: client → server

Write a new SKILL.md, generated from a brief or supplied verbatim.

Params

fieldtyperequireddescription
contentstring | nullnoA complete SKILL.md body. When given, it is validated and written directly — no model turn runs.
descriptionstring | nullnoNatural-language brief. Used only when 'content' is omitted: the daemon starts the same generating turn '/skill create' runs and answers with a turnId rather than waiting for it.
forcebooleannoOverwrite an existing SKILL.md at the target.
namestringyesSkill name; also its directory and the future /<name>.
scope"project" | "global"noWhere to write the skill.
sessionIdstring | nullnoDraft mode only ('content' omitted): run the generating turn on this existing session instead of creating a headless one. Must be rooted at 'workdir'; invalid_params otherwise. Ignored when 'content' is given.
workdirstringyesProject directory the skill is written under (or read/create a session from).

Result

fieldtyperequireddescription
namestring | nullnoSkill name, once known.
pathstring | nullnoWhere the SKILL.md was written.
sessionIdstring | nullnoSet alongside turnId: the session the turn ran on — the caller's own 'sessionId', or a new headless one created for 'workdir'.
turnIdstring | nullnoSet instead of name/path when generation was started as a turn.

skill.install ​

Direction: client → server

Install a skill from a path, URL or registry.

Params

fieldtyperequireddescription
linkbooleannoLocal plugin directory only: install it as a symlink instead of a copy, so edits are live after skill.reload (development). skill.remove drops the link and leaves the directory alone.
sourcestringyesPath, URL or registry name to install from.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

skill.list ​

Direction: client → server

List installed skills.

Params

No params (send {}).

Result

fieldtyperequireddescription
skills({ downloads?: number; id?: string; installSpec?: string; installed?: boolean; kind?: "skill" | "agent" | "command" | "plugin"; name: string; rating?: number; source?: string; summary?: string; })[]noInstalled skills.

skill.read ​

Direction: client → server

Read a skill's SKILL.md.

Params

fieldtyperequireddescription
namestringyesSkill to read.
workdirstringyesProject directory to resolve a project-scoped skill in.

Result

fieldtyperequireddescription
contentstringyesIts full text.
pathstringyesWhere the SKILL.md was found.
scope"project" | "global"yes'project' or 'global', wherever it was found.

skill.reload ​

Direction: client → server

Reload skills from disk without restarting.

Params

No params (send {}).

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

skill.remove ​

Direction: client → server

Delete an installed skill or plugin.

Params

fieldtyperequireddescription
namestringyesInstalled plugin or skill to delete.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

Direction: client → server

Search available skills.

Params

fieldtyperequireddescription
querystringyesFree-text query over skill names and summaries.

Result

fieldtyperequireddescription
notIncluded({ label: string; reason?: string; })[]noHubs the registry has deliberately switched off (not failures). Clients should mention them quietly, never as an outage.
skills({ downloads?: number; id?: string; installSpec?: string; installed?: boolean; kind?: "skill" | "agent" | "command" | "plugin"; name: string; rating?: number; source?: string; summary?: string; })[]noMatching skills.
unavailablestring[]noSources that could not be reached, as ': <reason>'. Empty skills with a non-empty list means offline, not no match.

skill.write ​

Direction: client → server

Save a skill's SKILL.md verbatim.

Params

fieldtyperequireddescription
contentstringyesFull SKILL.md text to save.
namestringyesSkill to write.
scope"project" | "global"noWhere to write the skill.
workdirstringyesProject directory, when scope is 'project'.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

system.checkUpdate ​

Direction: client → server

Report whether a newer snowpea release exists; cached for 24h.

Params

fieldtyperequireddescription
forcebooleannoIgnore the 24h cache and ask the network right now.

Result

fieldtyperequireddescription
availablebooleanyesTrue when latest is strictly newer than current.
cachedbooleannoTrue when this came from $SNOWPEA_HOME/update-check.json.
channel"git" | "pypi"yesWhere the answer came from: 'pypi' or 'git'.
checkedAtstringyesUTC ISO-8601 timestamp of the answer.
currentstringyesVersion of the running daemon (snowpea_core.version).
errorstring | nullnoWhy the check could not complete; available is false whenever it is set.
lateststringyesNewest version found; equal to current when nothing is known.
releaseUrlstring | nullnoHuman page for the release, when one exists.
sourcestringyesWhat an installer would be handed to get 'latest'.

system.health ​

Direction: client → server

Liveness probe; answers as long as the daemon serves requests.

Params

No params (send {}).

Result

fieldtyperequireddescription
status"ok"noAlways 'ok' when the daemon answers.

system.hello ​

Direction: client → server

Authenticate a connection and agree on the protocol version.

Params

fieldtyperequireddescription
clientIdstring | nullnoId stable across restarts of this client install (1.6.0). Sessions a previous connection with the same clientId started re-bind to this one.
clientKindstring | nullnoWhat the client is, e.g. "tui", "desktop", "browser" (1.6.0).
clientVersionstringyesVersion string of the connecting client.
instanceIdstring | nullnoId of this run of the client (1.6.0).
keepAlivebooleannoKeep the daemon from its idle shutdown while this client is connected (1.6.0).
protocolVersionstringyesProtocol semver the client speaks; major must match.
tokenstringyesShared secret read from $SNOWPEA_HOME/token or daemon.json.

Result

fieldtyperequireddescription
capabilitiesstring[]noFeature flags this daemon supports.
protocolVersionstringyesProtocol semver the daemon speaks.
serverVersionstringyesVersion of the running daemon.

system.info ​

Direction: client → server

Report the daemon's version, pid, port, start time and home.

Params

No params (send {}).

Result

fieldtyperequireddescription
countersRecord<string, number>noLifecycle counters: sessions, jobs, gateway_bindings, named_agents.
homestringyesResolved SNOWPEA_HOME directory.
lifecycle{ reason?: string; reasons?: string[]; secondsUntilExit?: number | null; summary?: string | null; willExit?: boolean; } | nullnoIdle-shutdown status, omitted by older daemons.
pidnumberyesProcess id of the daemon.
platformstring | nullnoThe daemon machine's sys.platform (darwin, linux, win32), for engine and permission guidance that depends on where the core runs.
portnumberyesTCP port the daemon is listening on (127.0.0.1 only).
protocolVersionstringyesProtocol semver the daemon speaks.
restartRequiredbooleannoTrue once system.update finished; the daemon runs the old code until restarted.
startedAtstringyesUTC ISO-8601 timestamp of daemon start.
versionstringyesDaemon version.

system.reloadSettings ​

Direction: client → server

Re-read settings.json and rebind the daemon's in-memory state.

Params

No params (send {}).

Result

fieldtyperequireddescription
changedKeysstring[]noTop-level settings sections that changed, e.g. ['providers'].
reloadedbooleanyesTrue when settings.json differed from what the daemon held and the in-memory state was rebound; false when it was already current.

system.restart ​

Direction: client → server

Shut the daemon down so the next launch runs the newly installed version.

Params

No params (send {}).

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

system.shutdown ​

Direction: client → server

Ask the daemon to shut down gracefully.

Params

No params (send {}).

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

system.update ​

Direction: client → server

Upgrade snowpea in a detached subprocess and report progress.

Params

No params (send {}).

Result

fieldtyperequireddescription
commandstringyesThe command line that runs, or that has to be run by hand.
errorstring | nullnoWhy nothing was started; null on the happy path.
logstringyesAbsolute path of the file the upgrade writes its output to.
startedbooleanyesTrue when the upgrade subprocess was spawned.

team.guide.delete ​

Direction: client → server

Delete a team guide from the project or global home.

Params

fieldtyperequireddescription
scope"project" | "global"yesWhich copy to delete.
sessionIdstring | nullnoSession whose workdir to use when workdir is omitted.
teamstringyesTeam name, or 'default'.
workdirstring | nullnoProject directory.

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

team.guide.get ​

Direction: client → server

Read a team guide for a project or session.

Params

fieldtyperequireddescription
sessionIdstring | nullnoSession whose workdir to use when workdir is omitted.
teamstring | nullnoTeam to read; omit to use the effective team for this session.
workdirstring | nullnoProject directory.

Result

fieldtyperequireddescription
effectiveTeamstringyesTeam name the guide lookup used.
guide{ description?: string; path?: string | null; persona?: string; routing?: ({ agent: string; known?: boolean; when: string; })[]; source: "project" | "global"; team: string; } | nullnoThe guide, if one exists.

team.guide.list ​

Direction: client → server

List every team guide visible in a project.

Params

fieldtyperequireddescription
sessionIdstring | nullnoSession whose workdir to use when workdir is omitted.
workdirstring | nullnoProject directory.

Result

fieldtyperequireddescription
guides({ description?: string; path?: string | null; persona?: string; routing?: ({ agent: string; known?: boolean; when: string; })[]; source: "project" | "global"; team: string; })[]noEvery visible guide.

team.guide.set ​

Direction: client → server

Write a team guide to the project or global home.

Params

fieldtyperequireddescription
descriptionstring | nullnoOne-line summary.
personastringyesPersona body to store.
routing({ agent: string; when: string; })[]noRouting rules to store.
scope"project" | "global"yesWhere to write the guide.
sessionIdstring | nullnoSession whose workdir to use when workdir is omitted.
teamstringyesTeam name, or 'default' for sessions with no active team.
workdirstring | nullnoProject directory.

Result

fieldtyperequireddescription
guide{ description?: string; path?: string | null; persona?: string; routing?: ({ agent: string; known?: boolean; when: string; })[]; source: "project" | "global"; team: string; }yesThe guide that was written.

team.start ​

Direction: client → server

Split a task across parallel workers.

Params

fieldtyperequireddescription
nnumberyesNumber of workers to run in parallel.
sessionIdstringyesSession the team works under.
taskstringyesTask the team splits between workers.

Result

fieldtyperequireddescription
teamIdstringyesId to poll with team.status.

team.status ​

Direction: client → server

Inspect a team's task board.

Params

fieldtyperequireddescription
teamIdstringnoTeam to inspect; empty means the most recent one.

Result

fieldtyperequireddescription
state"running" | "done" | "failed" | "interrupted"noOverall state.
taskstringnoThe task the team was given.
tasks({ agentN?: number | null; assignee?: string | null; branch?: string; conflictHunks?: string; conflictSummary?: string; dependsOn?: string[]; note?: string; retries?: number; status?: "pending" | "queued" | "claimed" | "running" | "done" | "conflict" | "merged" | "failed"; taskId: string; title: string; })[]noTask board contents.
teamIdstringyesTeam that was inspected.
workersnumbernoHow many workers the run was started with.
worktreesstring[]noWorker worktrees that exist right now.

tool.invoke ​

Direction: server → client

Ask the client to run one of its host tools.

Params

fieldtyperequireddescription
argsRecord<string, unknown>noArguments from the model.
attachments({ byPath?: boolean; messageId?: string | null; mime: string; name: string; path: string; size: number; })[]noFiles the user attached in the root conversation (1.23.0), as session.attachments lists them: the paths a host may hand to a page upload.
callIdstringyesId of the tool call; tool.progress refers to it.
guardstring | nullno'agent-switch' while session.setAgent {guardTurn} guards this session or one it was delegated from (1.25.0): a host asks before its own acting tools, whatever tag they were registered with.
job{ createdVia: "rpc" | "tool"; fingerprint: string; id: string; meta?: Record<string, unknown> | null; ownerClientId?: string | null; runId: string; scheduledAt: string; trigger: "schedule" | "runNow"; } | nullnoThe scheduled run behind the root's running turn (1.23.0); set only when origin is 'schedule'. A delegated child reports its root's.
mode"plan" | "accept" | "auto"noThe session's mode. A code-running tool registered as 'read' must refuse mutations in plan mode itself and escalate the rest with approval.ask.
namestringyesHost tool name.
origin"human" | "agent" | "member" | "schedule" | "system" | nullnoWho started the root conversation's running turn (1.23.0): the session's own person, the agent, a schedule, another gateway group member or the system. A delegated child reports its root's.
parentSessionIdstring | nullnoThe session that spawned this one (a subagent's parent); null for a root session. A browser host shares the parent's agent tabs with it.
sessionIdstringyesSession whose turn called the tool.
turnIdstringnoTurn the call belongs to.
userTurn{ current?: boolean; messageId: string; steers?: string[]; text: string; } | nullnoThe root conversation's latest message the user typed, trusted (1.22.0); 'current' says whether it started the running turn. For a delegated child it is the root's, never the parent agent's task text; only the session's own person's words count (not an agent's, a schedule's or another group member's), and null until the person has typed one.
workdirstringnoThe session's project folder, absolute (Projects, 1.7.0).
workspaceDirstringnoThe session workspace (tmp/, artifacts/); the workdir when it has none.

Result

fieldtyperequireddescription
content({ contentRef?: string | null; data?: string | null; mediaType?: string | null; text?: string | null; type: "text" | "image"; })[] | nullnoRich result blocks. Images reach vision models as image input; text blocks are appended to output.
errorstring | nullnoError text when ok is false.
metaRecord<string, unknown> | nullnoExtra facts. meta.sensitive=true keeps the output out of the session store ([redacted]), memory and compaction summaries.
okbooleanyesFalse reports the call as a tool error.
outputstringnoText result the model reads.

tool.list ​

Direction: client → server

List the tools registered for a session.

Params

fieldtyperequireddescription
sessionIdstring | nullnoScope the listing to one session; omit for the global set.

Result

fieldtyperequireddescription
tools({ category: string; deferred?: boolean; description?: string; name: string; permissionTag: "read" | "write" | "exec" | "network" | "send" | "config" | "delegate" | "secret"; provider?: string; reason?: string; server?: string; source?: string; state?: "active" | "inactive"; })[]noRegistered tools.

tool.progress ​

Direction: client → server

Notification: progress of a running tool.invoke, re-emitted as tool.progress.

Params

fieldtyperequireddescription
callIdstringyesThe tool.invoke callId this progress belongs to.
messagestringnoProgress text; re-emitted as session.event tool.progress. Any tool.progress, an empty keepalive included, restarts the call's deadline (addendum 15).

Result

fieldtyperequireddescription
okbooleannoTrue when the call succeeded.

tool.register ​

Direction: client → server

Register tools this connection runs itself (host tools).

Params

fieldtyperequireddescription
tools({ agents?: string[] | null; category?: string | null; deferred?: boolean; description: string; inputSchema?: Record<string, unknown>; name: string; parallel?: "safe" | "never"; permission: "read" | "write" | "exec" | "network" | "send" | "config" | "delegate" | "secret"; timeoutMs?: number | null; })[]yesTools to add or replace for this connection; all-or-nothing.

Result

fieldtyperequireddescription
registeredstring[]noNames now registered.

tool.unregister ​

Direction: client → server

Remove some of this connection's host tools.

Params

fieldtyperequireddescription
namesstring[]yesThis connection's tools to remove.

Result

fieldtyperequireddescription
removedstring[]noNames actually removed.

usage.summary ​

Direction: client → server

Token totals from stored usage events, grouped by provider, model, session or day.

Params

fieldtyperequireddescription
groupBy"provider" | "model" | "session" | "day"noHow to group the totals.
sincestring | nullnoUTC ISO start (inclusive).
untilstring | nullnoUTC ISO end (exclusive).

Result

fieldtyperequireddescription
groupBystringyesThe grouping used.
inputTokensnumbernoSum over all rows.
outputTokensnumbernoSum over all rows.
rows({ calls?: number; inputTokens?: number; key: string; outputTokens?: number; })[]noTotals, largest first.

Direction: client → server

Web search for a browser host (1.11.0): the web_search tool's provider chain, settings, caps and timeouts, for the host's own fallback when its search page is blocked. Browser host clients (with a clientId) only; 'unavailable' with details.reason when no provider can answer. Results are untrusted web content.

Params

fieldtyperequireddescription
numnumbernoHow many results, 1-20 (default 10).
querystringyesWhat to search for.

Result

fieldtyperequireddescription
providerstringyesThe search provider that answered, e.g. 'ddgs'.
results({ snippet?: string; title: string; url: string; })[]no

Notifications ​

approval.pending ​

fieldtyperequireddescription
hostToolsFromstring | nullnoThe session's owning client (addendum 8). A browser profile shows only its own cards and those with null.
request{ args?: Record<string, unknown>; guard?: string | null; note?: string; requestId: string; risk?: string; scopeHint?: "once" | "session" | "project" | "always" | "site"; sessionId: string; site?: string | null; timeoutSec?: number; tool: string; }yesThe request now in the shared queue.

approval.resolved ​

fieldtyperequireddescription
bystringyesSurface or user that answered.
decision"allow" | "deny"yesThe decision that was recorded.
requestIdstringyesRequest that was resolved.

audio.install.progress ​

fieldtyperequireddescription
bytesDonenumber | nullnoBytes transferred so far.
bytesTotalnumber | nullnoTotal bytes, from Content-Length when the server sends one.
enginestringyesEngine being installed, always the bare id.
linestringnoOne line of the installer's output.
percentnumber | nullno0-100 within the stage, when it can be known.
stagestringnoresolve | download | extract | verify | install | check. 'install' is the package manager, 'verify' is the checksum, 'check' is the detection that runs afterwards.
stepnumberno1-based place of this stage in the sequence.
stepsnumbernoHow many stages this engine has in total.
voicestringnoSet when a voice of that engine is installing, e.g. ko_KR-kss-medium; empty for the engine itself. A surface keys its progress row on the pair, so an engine install and a voice install never share a row.

commands.changed ​

fieldtyperequireddescription
commands({ argsSchema?: Record<string, unknown>; name: string; source?: string; summary: string; })[]noThe command table as it stands now.
reasonstringnoWhy the table changed.

gateway.event ​

fieldtyperequireddescription
bindingIdstringyesBinding the event belongs to.
kindstringyesEvent kind, e.g. 'message' or 'error'.
payloadRecord<string, unknown>noKind-specific body.

job.event ​

fieldtyperequireddescription
jobIdstringyesJob the event belongs to.
kind"started" | "finished" | "failed" | "denied" | "deleted" | "updated" | "waiting_for_host" | "missed" | "notify"yesWhere the run got to. 'notify' (1.23.0) follows the finish of a job with meta, payload {status, sessionId, text}: its host shows the user a notification.
payloadRecord<string, unknown>noKind-specific body.

mcp.changed ​

fieldtyperequireddescription
errorstring | nullnoWhy the server is in the error state.
namestringyesServer name.
removedbooleannoTrue when the entry itself is gone.
scope"project" | "global" | "plugin" | "settings"noScope the server is declared in.
state"stopped" | "starting" | "ready" | "error"yesstopped, starting, ready or error.
toolCountnumbernoTools the server currently contributes.

provider.loginProgress ​

fieldtyperequireddescription
expiresInSecnumber | nullnoSeconds until the code or session expires, when known.
messagestring | nullnoOne line for humans.
methodstringyesLogin flow in progress, e.g. 'device_code' or 'oauth_pkce'.
phase"started" | "await_user" | "polling" | "done" | "failed"yesWhere the login got to.
userCodestring | nullnoShort code the user types in, for device-code flows.
vendorstringyesVendor being logged into.
verificationUristring | nullnoURL to open to approve the login.
verificationUriCompletestring | nullnoverificationUri with the code already embedded, when known.

question.pending ​

fieldtyperequireddescription
hostToolsFromstring | nullnoThe session's owning client (addendum 8). A browser profile shows only its own cards and those with null.
request{ questions?: ({ allowOther?: boolean; header?: string; multi?: boolean; options?: ({ description?: string; label: string; preview?: string; })[]; question: string; secret?: boolean; })[]; requestId: string; sessionId: string; timeoutSec?: number; }yesThe question now in the shared queue.

question.resolved ​

fieldtyperequireddescription
bystringyesSurface or user that answered.
requestIdstringyesQuestion that was resolved.

session.event ​

fieldtyperequireddescription
hostToolsFromstring | nullnoThe session's owning client (addendum 8); null for unhosted sessions.
kindstringyesEvent kind; see sessionEventKinds for the payload schema.
payloadRecord<string, unknown>noKind-specific body.
seqnumberyesMonotonic per-session sequence number.
sessionIdstringyesSession the event belongs to.
tsstringyesUTC ISO-8601 timestamp.

sessions.changed ​

fieldtyperequireddescription
browserProvider"host" | "local" | nullnoA browser session's browser: 'host' (Snowpea browser only) or 'local' (the user opted in to core's own browser); null for non-browser sessions.
hostToolsFromstring | nullnoThe session's owning client (addendum 8); null for unhosted sessions.
reasonstringyescreate, prompt, turn, renamed, close, ...
sessionIdstringyesSession that changed.
statusstring | nullnoIts status now, when known.
titlestring | nullnoIts title, when it has one.

settings.changed ​

fieldtyperequireddescription
keysstring[]noTop-level settings sections that changed, e.g. ['providers'].
scope"global" | "project"noWhich document was reloaded; "global" for $SNOWPEA_HOME/settings.json.

system.updateProgress ​

fieldtyperequireddescription
messagestringnoOne line for humans.
phase"started" | "done" | "failed"yesWhere the upgrade got to.

teams.changed ​

fieldtyperequireddescription
reasonstringyesWhy the guide list changed.
teamstring | nullnoTeam that changed, when known.

tool.cancel ​

fieldtyperequireddescription
callIdstringyesThe tool.invoke callId to stop.
sessionIdstringyesSession whose turn was interrupted.

session.event kinds ​

Every session event carries a monotonically increasing per-session seq. After a reconnect, session.resume(sessionId, afterSeq) replays anything missed.

kind agent.changed ​

fieldtyperequireddescription
agentstring | nullnoAgent definition now in force (prompt, tools, rounds); null for none.
kind"agent.changed"no

kind audio.spoken ​

fieldtyperequireddescription
kind"audio.spoken"no
mimestringnoMedia type of that file.
pathstringyesAudio file the speech was written to.
playedbooleannoTrue when the daemon played it.
providerstringnoBackend that synthesised it.
utterancestringnoreply = the turn's answer; ack = the opening acknowledgement the agent writes before its first tool call. A surface may label or skip an ack; one that does not know the field treats everything as a reply.
voicestring | nullnoVoice that was used.

kind backend.changed ​

fieldtyperequireddescription
backend"local" | "docker" | "ssh"yesWhere tools now execute.
kind"backend.changed"no

kind checkpoint.restored ​

fieldtyperequireddescription
checkpointIdstring | nullnoUndo checkpoint for the restore, null when none was written.
kind"checkpoint.restored"no
restoredstring[]noPaths restored.
skipped({ path: string; reason: "changed_since" | "not_restorable" | "missing_blob" | "excluded"; })[]noPaths skipped and their reasons.

kind checkpoint.updated ​

fieldtyperequireddescription
checkpoint{ createdAt: string; files?: ({ afterSha?: string | null; beforeSha?: string | null; path: string; restorable?: boolean; size?: number; skipped?: "too_large" | "excluded" | "unreadable" | null; source: "tool" | "shell"; status: "modified" | "created" | "deleted"; })[]; id: string; kind: "turn" | "restore"; prompt?: string; sessionId: string; turnId?: string | null; workdir: string; }yesThe whole checkpoint manifest so far.
kind"checkpoint.updated"no

kind command.progress ​

fieldtyperequireddescription
command"ralph" | "ultrawork"yesCommand reporting.
iterationnumberno0 for the plan, then 1, 2, ….
kind"command.progress"no
outcomestring | nullnoSet on the last event only: ralph 'complete', 'rejected', 'stopped', 'max_iterations' or 'error'; ultrawork 'complete' or 'partial'.
stories({ id: string; note?: string; status: "pass" | "fail" | "pending"; title: string; })[]noEvery story, in plan order.

kind compaction ​

fieldtyperequireddescription
afternumbernoEstimated tokens the history holds now.
autobooleannoTrue when the auto-compaction threshold triggered it.
beforenumbernoEstimated tokens the history held before.
keptnumbernoMessages kept verbatim after the summary.
kind"compaction"no
summaryCharsnumbernoLength of the summary in characters.

kind compaction.started ​

fieldtyperequireddescription
beforenumbernoEstimated tokens the history holds now.
kind"compaction.started"no
reason"manual" | "auto"noauto = the auto-compaction threshold triggered it.

kind context ​

fieldtyperequireddescription
estimatedbooleannoTrue while 'used' is a local estimate; false once the provider reported it.
kind"context"no
modelstring | nullnoModel the window belongs to.
percentnumber | nullnoused/window as a percentage, null when the window is unknown.
providerstring | nullnoVendor serving that model.
usednumbernoTokens the current prompt occupies.
windownumber | nullnoContext window of the model in tokens; null when unknown.

kind diff ​

fieldtyperequireddescription
kind"diff"no
patchstringyesUnified diff of the change.
pathstringyesFile that changed.

kind error ​

fieldtyperequireddescription
codestringyesOne of the protocol error codes.
kind"error"no
messagestringyesHuman-readable detail.

kind hook.continue ​

fieldtyperequireddescription
countnumberyesHow many times Stop hooks continued this turn so far.
kind"hook.continue"no
reasonstringyesThe hook's instruction, handed to the model.

kind job.done ​

fieldtyperequireddescription
jobIdstringyesJob that ran.
kind"job.done"no
sessionIdstring | nullnoSession the run used.
statusstringnoJob status as the scheduler recorded it.
textstringnoWhat the run reported.

kind job.failed ​

fieldtyperequireddescription
jobIdstringyesJob that ran.
kind"job.failed"no
sessionIdstring | nullnoSession the run used.
statusstringnoJob status as the scheduler recorded it.
textstringnoWhat the run reported, or the error.

kind loop.suspected ​

fieldtyperequireddescription
countnumbernoRepeats seen in the last 20 tool calls.
kind"loop.suspected"no
toolstringyesTool whose call repeated.

kind lsp.diagnostics ​

fieldtyperequireddescription
countnumbernoDiagnostics of every severity.
errorsnumbernoHow many of them are errors.
kind"lsp.diagnostics"no
pathstringyesFile the diagnostics are about.
warningsnumbernoHow many of them are warnings.

kind message.delta ​

fieldtyperequireddescription
kind"message.delta"no
textstringyesText fragment to append to the current message.

kind message.done ​

fieldtyperequireddescription
continuationsnumbernoHow many times the turn was resumed after hitting the output limit.
kind"message.done"no
messageKind"" | "interrupted"noOptional message classification inside the message.done payload, for example 'interrupted' for the post-stop system note.
role"assistant" | "user" | "system"noWho produced the message.
textstringyesFull message text.
truncatedbooleannoThe answer still hit the output limit and is incomplete.

kind message.reasoning ​

fieldtyperequireddescription
charsnumbernoCharacters of reasoning so far in this turn.
kind"message.reasoning"no
textstringnoReasoning fragment; not part of the answer.

kind message.user ​

fieldtyperequireddescription
attachments({ kind?: "file" | "image" | "text" | "page"; name?: string; title?: string | null; url?: string | null; })[]noFiles sent along with the prompt.
expansion{ kind?: "skill" | "command"; name: string; text: string; } | nullnoSet when text is a skill command: the skill body the model was given instead. Surfaces show it folded, like a tool call, not inline.
kind"message.user"no
refs(Record<string, unknown>)[]noResolved @ references (path, kind, lines, truncated).
steeredbooleannoTrue when this prompt was queued behind a running turn and then folded into that same turn before its next model call.
textstringyesPrompt text as the user typed it.

kind mode.changed ​

fieldtyperequireddescription
delegationboolean | nullnoWhether delegation mode is now in force, sent when /delegation changes it; absent when only the permission mode moved.
kind"mode.changed"no
mode"plan" | "accept" | "auto"yesMode now in effect.

kind model.changed ​

fieldtyperequireddescription
effort"low" | "medium" | "high" | "max" | nullnoEffective reasoning effort for the session (CORE-effort).
effortSource"session" | "model" | "vendor" | "default" | nullnoRule that decided the effort: 'session', 'model', 'vendor' or 'default'.
efforts("low" | "medium" | "high" | "max")[] | nullnoTiers this model offers, weakest first; [] means it has no effort setting (effort is then null). E.g. Qwen3.8 Flash Next offers low, medium, high.
kind"model.changed"no
modelstring | nullnoModel id now in effect.
providerstring | nullnoVendor now in effect.

kind plan.updated ​

fieldtyperequireddescription
donenumbernoSteps marked done.
kind"plan.updated"no
nextstring | nullnoThe next pending step as 'S3 <title>'; null when none is left.
pathstringyesThe plan file, relative to the workdir.
status"active" | "done" | "archived"yesWhere the plan stands.
titlestringyesThe plan's title.
totalnumbernoSteps in the plan.

kind subagent.done ​

fieldtyperequireddescription
agentIdstringyesSubagent that finished.
budgetnumbernoTool-round budget cap.
deniedCallsnumbernoHow many child tool calls were denied in this run.
deniedToolsstring[]noUnique names of tools whose calls were denied.
kind"subagent.done"no
namestringnoNamed agent that ran, when there was one.
okbooleannoFalse when it failed.
reasonstringnoWhy it ended: complete, budget, timeout, error, interrupted or denied.
resultstringnoFinal report.
roundsnumbernoTool rounds used by the subagent.
sessionIdstring | nullnoThe subagent's own session.
status"queued" | "running" | "done" | "error" | "interrupted"noTerminal state: done, error or interrupted.
summarystringnoThe subagent's final answer.
titlestringnoOne-line label for the delegation, written by the delegating model in the user's language; empty when it wrote none.
usage{ inputTokens?: number; outputTokens?: number; }noTokens the subagent consumed.

kind subagent.spawn ​

fieldtyperequireddescription
agentIdstringyesId correlating this subagent's events.
kind"subagent.spawn"no
namestringnoNamed agent that was spawned.
sessionIdstring | nullnoThe subagent's own session, once it has one.
status"queued" | "running" | "done" | "error" | "interrupted"noState at spawn: queued until a concurrency slot frees up.
taskstringnoTask it was given.
titlestringnoOne-line label for the delegation, written by the delegating model in the user's language; empty when it wrote none.

kind subagent.update ​

fieldtyperequireddescription
agentIdstringyesSubagent reporting progress.
kind"subagent.update"no
lastTextstringnoMost recent text the subagent produced.
namestringnoNamed agent that is running, when there is one.
sessionIdstring | nullnoThe subagent's own session.
status"queued" | "running" | "done" | "error" | "interrupted"noLifecycle state.
textstringnoHuman-readable progress text.
titlestringnoOne-line label for the delegation, written by the delegating model in the user's language; empty when it wrote none.
usage{ inputTokens?: number; outputTokens?: number; } | nullnoTokens the subagent has used so far, cumulative; sent with every update so a surface can show a long delegation is still moving.

kind team.task.update ​

fieldtyperequireddescription
agentNnumber | nullno1-based worker index that owns the task.
assigneestring | nullnoWorker that owns the task.
kind"team.task.update"no
retriesnumbernoHow many times a merge conflict re-queued it.
status"pending" | "queued" | "claimed" | "running" | "done" | "conflict" | "merged" | "failed"noNew state.
taskIdstringyesTask that changed.
teamIdstringyesTeam the task belongs to.

kind todos.updated ​

fieldtyperequireddescription
kind"todos.updated"no
todos({ content: string; id: string; status: "pending" | "in_progress" | "completed"; })[]noThe whole list, in order.

kind tool.call ​

fieldtyperequireddescription
argsRecord<string, unknown>noArguments supplied.
callIdstringyesId pairing this call with its tool.result.
kind"tool.call"no
namestringyesTool being called.

kind tool.progress ​

fieldtyperequireddescription
callIdstringyesId of the tool.call this output belongs to.
chunkstringnoRaw output fragment, in order.
kind"tool.progress"no
namestringyesTool that is running.
seqnumberno0-based index of this progress within the call.
stream"stdout" | "stderr"noWhich stream the chunk came from.
truncatedbooleannoTrue on the final progress when the byte cap stopped the tail.

kind tool.result ​

fieldtyperequireddescription
callIdstringyesId of the matching tool.call.
content({ contentRef?: string | null; data?: string | null; mediaType?: string | null; text?: string | null; type: "text" | "image"; })[] | nullnoA host tool's content blocks: text inline, images as contentRef (session.toolContent). Absent for sensitive results (1.7.0).
errorstring | nullnoFailure detail when ok is false.
kind"tool.result"no
metaRecord<string, unknown> | nullnoHost-tool facts for surfaces (e.g. pages for page preview cards); not shown to the model. Forwarded as the host gave it, also for sensitive results; dropped above 16 KB (addendum 13).
namestringyesTool that ran.
okbooleanyesFalse when the tool failed.
outputstringnoOutput handed back to the model.

kind turn.dequeued ​

fieldtyperequireddescription
kind"turn.dequeued"no
queuednumbernoPrompts still waiting after this one left.
reason"started" | "dropped" | "steered"nostarted = it is now running, dropped = it was discarded, steered = it was merged into the running turn.
turnIdstringyesTurn id that left the queue.

kind turn.done ​

fieldtyperequireddescription
kind"turn.done"no
reason"complete" | "interrupted" | "error" | "denied" | "timeout" | "budget" | "stalled" | "empty_response"noWhy the turn ended. budget = the tool-round budget ran out; the turn reported what it had done before ending. stalled = consecutive rounds made no new tool or file progress. empty_response = the model ended with no text and no tool call, again after one nudge (1.23.0); an error event with code empty_response precedes it.
syntheticbooleannoTrue when the daemon wrote this event itself to close a turn a crash left open, rather than the turn reporting its own end (CORE-dangling-turns). The turn produced no further output after the events already stored.
turnIdstringyesTurn that ended.

kind turn.queued ​

fieldtyperequireddescription
kind"turn.queued"no
positionnumberyes1-based place in the queue behind the running turn.
queuednumberyesPrompts waiting in the queue after this one was added.
turnIdstringyesTurn id assigned to the queued prompt.

kind turn.started ​

fieldtyperequireddescription
initiator"user" | "system"noWho started the turn (1.8.0). 'system' = session.continue: the input is a [system] note, no message.user is emitted, and surfaces show a status line instead of a user bubble.
kind"turn.started"no
promptstring | nullnoThe prompt that opened it; null when there is none.
queuedbooleannoTrue when this turn waited in the prompt queue first.
reasonstring | nullnoWhy a system turn started, e.g. 'handback' (1.8.0).
turnIdstringyesTurn that is now running.

kind usage ​

fieldtyperequireddescription
cachedInputTokensnumber | nullnoOf inputTokens, how many the server answered from its prompt cache, when it reports that (1.20.0).
inputTokensnumbernoPrompt tokens consumed.
kind"usage"no
modelstring | nullnoModel that served the call (1.7.0).
outputTokensnumbernoCompletion tokens produced.
providerstring | nullnoVendor that served the call (1.7.0).
timingsRecord<string, number> | nullnollama.cpp's own timings when the server sends them (1.25.0): prompt_n, prompt_ms, cache_n, predicted_n, predicted_ms. A first token much later than prompt_ms was spent waiting for a slot.

Error codes ​

Returned as the string error.data.code of a JSON-RPC error response.

The numeric error.code: -32601 means only that the method does not exist (method_not_found), so a client can feature-detect an older daemon by it; a missing session, job, memory, content or other entity is -32004 (not_found, mcp_not_found); -32602 invalid params; -32603 internal; -32000 everything else. Before protocol 1.7.0 a missing entity also answered -32601.

codemeaning
approval_deniedThe user denied the approval request.
approval_timeoutNo approval arrived before approvals.timeoutSec elapsed.
auth_expired
empty_response
internalUnexpected server-side failure.
invalid_output
invalid_paramsParams failed schema validation.
login_unsupportedThe vendor does not support the requested login method.
mcp_exists
mcp_invalid
mcp_not_found
mcp_read_only
mcp_start_failed
mcp_unsafe
method_not_foundNo such method (-32601).
mode_deniedThe session mode forbids this tool or action.
not_foundNo such session, request, job, agent or content (-32004).
not_implementedDefined in the schema but not implemented in this milestone.
protocol_incompatibleClient and server protocol majors differ.
session_busy
tool_inactiveThe tool exists but is disabled for this session.
unauthorizedMissing or invalid token, or a call before system.hello.
unavailable

MIT licensed. The manual is generated from the product repositories — see the banner on each page.