9.2 KiB
title, task, lineage_type, upstream_source, upstream_sha, imported_at, prompt_class, upstream_changes, author, validated
| title | task | lineage_type | upstream_source | upstream_sha | imported_at | prompt_class | upstream_changes | author | validated |
|---|---|---|---|---|---|---|---|---|---|
| RPC Mode | import | https://github.com/K-Dense-AI/scientific-agent-skills/blob/b2a92ba0/skills/pi-agent/references/rpc.md | b2a92ba0 | 2026-08-14 | prompt | accepted | upstream | false |
RPC Mode
Source: https://pi.dev/docs/latest/rpc
RPC mode runs Pi headlessly over stdin/stdout JSONL. Use it for language-agnostic clients, IDE integrations, custom UIs, or subprocess isolation. For Node/TypeScript in-process apps prefer the SDK unless you want subprocess isolation.
pi --mode rpc [options]
Common options: --provider, --model (supports provider/id and :<thinking>), --name/-n, --no-session, --session-dir.
Framing
Commands are JSON objects on stdin, one per line; responses (type: "response") and events stream to stdout as JSON lines. Use LF (\n) as the only record delimiter, strip an optional trailing \r, and never use readers that split on Unicode separators — Node readline is not protocol-compliant because it also splits on U+2028/U+2029, which are valid inside JSON strings.
Commands accept an optional id; the response echoes it. Events generally omit id; bash_execution_update carries the id of its originating bash command.
Responses have the shape {"type":"response","command":"...","success":true|false,"data":{...},"error":"..."}. Parse failures return command: "parse".
Prompting Commands
prompt — {"id":"req-1","type":"prompt","message":"Hello"}. Optional images: [{"type":"image","data":"base64...","mimeType":"image/png"}]. While streaming, streamingBehavior is required ("steer" or "followUp") or the command errors. Extension commands execute immediately even during streaming; skill commands and prompt templates expand before sending or queueing. success: true means accepted, queued, or handled — later failures arrive as events, not a second response.
steer — queue a steering message delivered after the current assistant turn's tool calls. follow_up — queue a message delivered when the agent is fully done. Both accept images and expand skills/templates but reject extension commands.
abort — abort the current agent operation.
new_session — optional parentSession; response data: { cancelled } (an extension may cancel via session_before_switch).
State, Model, Thinking
get_state→model(full Model object ornull),thinkingLevel,isStreaming,isCompacting,steeringMode,followUpMode,sessionFile,sessionId,sessionName,autoCompactionEnabled,messageCount,pendingMessageCount.get_messages→ allAgentMessageobjects.set_model(provider,modelId) → full Model object.cycle_model→{ model, thinkingLevel, isScoped }, ornulldata with one model.get_available_models→ array of Model objects.set_thinking_level(off,minimal,low,medium,high,xhigh,max;xhigh/maxonly when the model supports them).cycle_thinking_level→{ level },nullif the model has no thinking.get_available_thinking_levels→{ levels };["off"]for non-reasoning models.
Queue, Compaction, Retry
set_steering_mode/set_follow_up_mode:"all"or"one-at-a-time"(default).compactwith optionalcustomInstructions→{ summary, firstKeptEntryId, tokensBefore, estimatedTokensAfter, usage, details }.estimatedTokensAfteris a heuristic over the rebuilt context, not a provider-exact count;usagemay be omitted by custom compaction handlers.set_auto_compaction(enabled),set_auto_retry(enabled),abort_retry.
Bash
bash (command, optional id) executes immediately, streams bash_execution_update events, and returns { output, exitCode, cancelled, truncated } plus fullOutputPath when truncated. Internally a BashExecutionMessage is stored in agent state; it reaches the LLM on the next prompt, rendered as ``Ran cmd``` plus a fenced output block. Multiple bash commands before a prompt are all included. abort_bash` aborts a running command.
Session Commands
get_session_stats→ session file/id, message counts,tokens(input,output,cacheRead,cacheWrite,total),cost, andcontextUsage(tokens,contextWindow,percent). Totals include tool-reported usage and summary generation.contextUsageis omitted without a model/context window;tokens/percentarenullright after compaction until a fresh assistant response provides usage.export_htmlwith optionaloutputPath→{ path }.switch_session(sessionPath) →{ cancelled }.fork(entryId) →{ text, cancelled };clone→{ cancelled }. Both can be cancelled bysession_before_fork.get_fork_messages→[{ entryId, text }].get_entrieswith optionalsincecursor →{ entries, leafId }. Includes pre-compaction history and abandoned branches, unlikeget_messages. Entry ids are durable cursors across client restarts; an unknownsincereturnssuccess: false.leafIdisnullfor an empty session.get_tree→{ tree, leafId }where each node is{ entry, children, label?, labelTimestamp? }. Orphaned entries appear as extra roots.get_last_assistant_text→{ text }or{ text: null }.set_session_name(name); read it back fromget_state.sessionName. Set the initial name with--name.
Commands Discovery
get_commands returns extension commands, prompt templates, and skills (skill: prefixed) with name, description, source (extension | prompt | skill), optional location (user | project | path), and path. Built-in TUI commands such as /settings are interactive-only and excluded.
Events
agent_start; agent_end (messages, willRetry); agent_settled (nothing will continue automatically — no retry, compaction retry, or queued continuation); turn_start / turn_end; message_start / message_update / message_end; bash_execution_update; tool_execution_start / _update / _end; queue_update; compaction_start / compaction_end; auto_retry_start / auto_retry_end; summarization_retry_scheduled / summarization_retry_attempt_start / summarization_retry_finished; extension_error.
message_update.assistantMessageEvent types: text_start, text_delta, text_end, thinking_start, thinking_delta, thinking_end, toolcall_start, toolcall_delta, toolcall_end.
message_update is delta-only — it carries a top-level usage object plus the delta event, and omits both the former cumulative message field and assistantMessageEvent.partial:
{"type":"message_update","usage":{"input":100,"output":1,"cacheRead":0,"cacheWrite":0,"totalTokens":101,"cost":{}},
"assistantMessageEvent":{"type":"text_delta","contentIndex":0,"delta":"Hello "}}
usage is the latest cumulative provider-reported usage and may stay zero until completion. Clients needing a live partial message must assemble it from message_start and subsequent events using contentIndex; treat message_end.message as authoritative. For tool calls, buffer toolcall_delta.delta — toolcall_end.toolCall holds the completed call.
compaction_start/compaction_end carry reason ("manual", "threshold", "overflow"). On overflow success, willRetry is true and the prompt is retried. Aborted compaction returns result: null, aborted: true; failed compaction returns result: null, aborted: false plus errorMessage. tool_execution_update.partialResult is cumulative, so clients can replace their display each update.
Extension UI Protocol
Extension dialogs (select, confirm, input, editor) emit extension_ui_request on stdout and block until the client sends extension_ui_response on stdin with the matching id. Fire-and-forget methods (notify, setStatus, setWidget, setTitle, set_editor_text) emit a request with no response expected. A timeout field means the agent auto-resolves when it expires, so clients need not track timeouts.
Responses: {"type":"extension_ui_response","id":"...","value":"..."} for select/input/editor, {"confirmed":true|false} for confirm, {"cancelled":true} to dismiss any dialog.
Degraded in RPC mode: custom() returns undefined; setWorkingMessage, setWorkingIndicator, setFooter, setHeader, setEditorComponent, setToolsExpanded are no-ops; getEditorText() returns ""; getToolsExpanded() returns false; pasteToEditor() delegates to setEditorText(); getAllThemes() returns []; getTheme() returns undefined; setTheme() returns { success: false, error }. ctx.mode is "rpc" and ctx.hasUI is true — use ctx.mode === "tui" to guard real-terminal features.
Message Types
UserMessage (role, content string or blocks, timestamp, attachments), AssistantMessage (content with text/thinking/toolCall blocks, api, provider, model, usage, stopReason ∈ stop/length/toolUse/error/aborted, timestamp), ToolResultMessage (toolCallId, toolName, content, optional usage for nested LLM work, isError), BashExecutionMessage (from the bash command, not LLM tool calls), and Attachment. Full definitions in references/session-format.md.