Caricamento in corso...
Caricamento in corso...
Last synced: Today, 22:00
Technical reference for the OpenClaw framework. Real-time synchronization with the official documentation engine.
Use this file to discover all available pages before exploring further.
OpenClaw integrates with pi-coding-agent and its sibling packages (
pi-aipi-agent-corepi-tuiOpenClaw uses the pi SDK to embed an AI coding agent into its messaging gateway architecture. Instead of spawning pi as a subprocess or using RPC mode, OpenClaw directly imports and instantiates pi's
AgentSessioncreateAgentSession()json{ "@mariozechner/pi-agent-core": "0.70.2", "@mariozechner/pi-ai": "0.70.2", "@mariozechner/pi-coding-agent": "0.70.2", "@mariozechner/pi-tui": "0.70.2" }
| Package | Purpose |
|---|---|
text pi-ai | Core LLM abstractions: text Modeltext streamSimple |
text pi-agent-core | Agent loop, tool execution, text AgentMessage |
text pi-coding-agent | High-level SDK: text createAgentSessiontext SessionManagertext AuthStoragetext ModelRegistry |
text pi-tui | Terminal UI components (used in OpenClaw's local TUI mode) |
textsrc/agents/ ├── pi-embedded-runner.ts # Re-exports from pi-embedded-runner/ ├── pi-embedded-runner/ │ ├── run.ts # Main entry: runEmbeddedPiAgent() │ ├── run/ │ │ ├── attempt.ts # Single attempt logic with session setup │ │ ├── params.ts # RunEmbeddedPiAgentParams type │ │ ├── payloads.ts # Build response payloads from run results │ │ ├── images.ts # Vision model image injection │ │ └── types.ts # EmbeddedRunAttemptResult │ ├── abort.ts # Abort error detection │ ├── cache-ttl.ts # Cache TTL tracking for context pruning │ ├── compact.ts # Manual/auto compaction logic │ ├── extensions.ts # Load pi extensions for embedded runs │ ├── extra-params.ts # Provider-specific stream params │ ├── google.ts # Google/Gemini turn ordering fixes │ ├── history.ts # History limiting (DM vs group) │ ├── lanes.ts # Session/global command lanes │ ├── logger.ts # Subsystem logger │ ├── model.ts # Model resolution via ModelRegistry │ ├── runs.ts # Active run tracking, abort, queue │ ├── sandbox-info.ts # Sandbox info for system prompt │ ├── session-manager-cache.ts # SessionManager instance caching │ ├── session-manager-init.ts # Session file initialization │ ├── system-prompt.ts # System prompt builder │ ├── tool-split.ts # Split tools into builtIn vs custom │ ├── types.ts # EmbeddedPiAgentMeta, EmbeddedPiRunResult │ └── utils.ts # ThinkLevel mapping, error description ├── pi-embedded-subscribe.ts # Session event subscription/dispatch ├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams ├── pi-embedded-subscribe.handlers.ts # Event handler factory ├── pi-embedded-subscribe.handlers.lifecycle.ts ├── pi-embedded-subscribe.handlers.types.ts ├── pi-embedded-block-chunker.ts # Streaming block reply chunking ├── pi-embedded-messaging.ts # Messaging tool sent tracking ├── pi-embedded-helpers.ts # Error classification, turn validation ├── pi-embedded-helpers/ # Helper modules ├── pi-embedded-utils.ts # Formatting utilities ├── pi-tools.ts # createOpenClawCodingTools() ├── pi-tools.abort.ts # AbortSignal wrapping for tools ├── pi-tools.policy.ts # Tool allowlist/denylist policy ├── pi-tools.read.ts # Read tool customizations ├── pi-tools.schema.ts # Tool schema normalization ├── pi-tools.types.ts # AnyAgentTool type alias ├── pi-tool-definition-adapter.ts # AgentTool -> ToolDefinition adapter ├── pi-settings.ts # Settings overrides ├── pi-hooks/ # Custom pi hooks │ ├── compaction-safeguard.ts # Safeguard extension │ ├── compaction-safeguard-runtime.ts │ ├── context-pruning.ts # Cache-TTL context pruning extension │ └── context-pruning/ ├── model-auth.ts # Auth profile resolution ├── auth-profiles.ts # Profile store, cooldown, failover ├── model-selection.ts # Default model resolution ├── models-config.ts # models.json generation ├── model-catalog.ts # Model catalog cache ├── context-window-guard.ts # Context window validation ├── failover-error.ts # FailoverError class ├── defaults.ts # DEFAULT_PROVIDER, DEFAULT_MODEL ├── system-prompt.ts # buildAgentSystemPrompt() ├── system-prompt-params.ts # System prompt parameter resolution ├── system-prompt-report.ts # Debug report generation ├── tool-summaries.ts # Tool description summaries ├── tool-policy.ts # Tool policy resolution ├── transcript-policy.ts # Transcript validation policy ├── skills.ts # Skill snapshot/prompt building ├── skills/ # Skill subsystem ├── sandbox.ts # Sandbox context resolution ├── sandbox/ # Sandbox subsystem ├── channel-tools.ts # Channel-specific tool injection ├── openclaw-tools.ts # OpenClaw-specific tools ├── bash-tools.ts # exec/process tools ├── apply-patch.ts # apply_patch tool (OpenAI) ├── tools/ # Individual tool implementations │ ├── browser-tool.ts │ ├── canvas-tool.ts │ ├── cron-tool.ts │ ├── gateway-tool.ts │ ├── image-tool.ts │ ├── message-tool.ts │ ├── nodes-tool.ts │ ├── session*.ts │ ├── web-*.ts │ └── ... └── ...
Channel-specific message action runtimes now live in the plugin-owned extension directories instead of under
src/agents/toolsThe main entry point is
runEmbeddedPiAgent()pi-embedded-runner/run.tstypescriptimport { runEmbeddedPiAgent } from "./agents/pi-embedded-runner.js"; const result = await runEmbeddedPiAgent({ sessionId: "user-123", sessionKey: "main:whatsapp:+1234567890", sessionFile: "/path/to/session.jsonl", workspaceDir: "/path/to/workspace", config: openclawConfig, prompt: "Hello, how are you?", provider: "anthropic", model: "claude-sonnet-4-6", timeoutMs: 120_000, runId: "run-abc", onBlockReply: async (payload) => { await sendToChannel(payload.text, payload.mediaUrls); }, });
Inside
runEmbeddedAttempt()runEmbeddedPiAgent()typescriptimport { createAgentSession, DefaultResourceLoader, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent"; const resourceLoader = new DefaultResourceLoader({ cwd: resolvedWorkspace, agentDir, settingsManager, additionalExtensionPaths, }); await resourceLoader.reload(); const { session } = await createAgentSession({ cwd: resolvedWorkspace, agentDir, authStorage: params.authStorage, modelRegistry: params.modelRegistry, model: params.model, thinkingLevel: mapThinkingLevel(params.thinkLevel), tools: builtInTools, customTools: allCustomTools, sessionManager, settingsManager, resourceLoader, }); applySystemPromptOverrideToSession(session, systemPromptOverride);
subscribeEmbeddedPiSession()AgentSessiontypescriptconst subscription = subscribeEmbeddedPiSession({ session: activeSession, runId: params.runId, verboseLevel: params.verboseLevel, reasoningMode: params.reasoningLevel, toolResultFormat: params.toolResultFormat, onToolResult: params.onToolResult, onReasoningStream: params.onReasoningStream, onBlockReply: params.onBlockReply, onPartialReply: params.onPartialReply, onAgentEvent: params.onAgentEvent, });
Events handled include:
message_startmessage_endmessage_updatetool_execution_starttool_execution_updatetool_execution_endturn_startturn_endagent_startagent_endcompaction_startcompaction_endAfter setup, the session is prompted:
typescriptawait session.prompt(effectivePrompt, { images: imageResult.images });
The SDK handles the full agent loop: sending to LLM, executing tool calls, streaming responses.
Image injection is prompt-local: OpenClaw loads image refs from the current prompt and passes them via
imagescodingToolsexecprocesspi-agent-core's
AgentToolexecuteToolDefinitionpi-tool-definition-adapter.tstypescriptexport function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] { return tools.map((tool) => ({ name: tool.name, label: tool.label ?? name, description: tool.description ?? "", parameters: tool.parameters, execute: async (toolCallId, params, onUpdate, _ctx, signal) => { // pi-coding-agent signature differs from pi-agent-core return await tool.execute(toolCallId, params, signal, onUpdate); }, })); }
splitSdkTools()customToolstypescriptexport function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) { return { builtInTools: [], // Empty. We override everything customTools: toToolDefinitions(options.tools), }; }
This ensures OpenClaw's policy filtering, sandbox integration, and extended toolset remain consistent across providers.
The system prompt is built in
buildAgentSystemPrompt()system-prompt.tsThe prompt is applied after session creation via
applySystemPromptOverrideToSession()typescriptconst systemPromptOverride = createSystemPromptOverride(appendPrompt); applySystemPromptOverrideToSession(session, systemPromptOverride);
Sessions are JSONL files with tree structure (id/parentId linking). Pi's
SessionManagertypescriptconst sessionManager = SessionManager.open(params.sessionFile);
OpenClaw wraps this with
guardSessionManager()session-manager-cache.tstypescriptawait prewarmSessionFile(params.sessionFile); sessionManager = SessionManager.open(params.sessionFile); trackSessionManagerAccess(params.sessionFile);
limitHistoryTurns()Auto-compaction triggers on context overflow. Common overflow signatures include
request_too_largecontext length exceededinput exceeds the maximum number of tokensinput token count exceeds the maximum number of input tokensinput is too long for the modelollama error: context length exceededcompactEmbeddedPiSessionDirect()typescriptconst compactResult = await compactEmbeddedPiSessionDirect({ sessionId, sessionFile, provider, model, ... });
OpenClaw maintains an auth profile store with multiple API keys per provider:
typescriptconst authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
Profiles rotate on failures with cooldown tracking:
typescriptawait markAuthProfileFailure({ store, profileId, reason, cfg, agentDir }); const rotated = await advanceAuthProfile();
typescriptimport { resolveModel } from "./pi-embedded-runner/model.js"; const { model, error, authStorage, modelRegistry } = resolveModel( provider, modelId, agentDir, config, ); // Uses pi's ModelRegistry and AuthStorage authStorage.setRuntimeApiKey(model.provider, apiKeyInfo.apiKey);
FailoverErrortypescriptif (fallbackConfigured && isFailoverErrorMessage(errorText)) { throw new FailoverError(errorText, { reason: promptFailoverReason ?? "unknown", provider, model: modelId, profileId, status: resolveFailoverStatus(promptFailoverReason), }); }
OpenClaw loads custom pi extensions for specialized behavior:
src/agents/pi-hooks/compaction-safeguard.tstypescriptif (resolveCompactionMode(params.cfg) === "safeguard") { setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare }); paths.push(resolvePiExtensionPath("compaction-safeguard")); }
src/agents/pi-hooks/context-pruning.tstypescriptif (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") { setContextPruningRuntime(params.sessionManager, { settings, contextWindowTokens, isToolPrunable, lastCacheTouchAt, }); paths.push(resolvePiExtensionPath("context-pruning")); }
EmbeddedBlockChunkertypescriptconst blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;
Streaming output is processed to strip
<think><thinking><final>typescriptconst stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => { // Strip <think>...</think> content // If enforceFinalTag, only return <final>...</final> content };
Reply directives like
[[media:url]][[voice]][[reply:id]]typescriptconst { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
pi-embedded-helpers.tstypescriptisContextOverflowError(errorText) // Context too large isCompactionFailureError(errorText) // Compaction failed isAuthAssistantError(lastAssistant) // Auth failure isRateLimitAssistantError(...) // Rate limited isFailoverAssistantError(...) // Should failover classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "timeout" | ...
If a thinking level is unsupported, it falls back:
typescriptconst fallbackThinking = pickFallbackThinkingLevel({ message: errorText, attempted: attemptedThinking, }); if (fallbackThinking) { thinkLevel = fallbackThinking; continue; }
When sandbox mode is enabled, tools and paths are constrained:
typescriptconst sandbox = await resolveSandboxContext({ config: params.config, sessionKey: sandboxSessionKey, workspaceDir: resolvedWorkspace, }); if (sandboxRoot) { // Use sandboxed read/edit/write tools // Exec runs in container // Browser uses bridge URL }
apply_patchOpenClaw also has a local TUI mode that uses pi-tui components directly:
typescript// src/tui/tui.ts import { ... } from "@mariozechner/pi-tui";
This provides the interactive terminal experience similar to pi's native mode.
| Aspect | Pi CLI | OpenClaw Embedded |
|---|---|---|
| Invocation | text pi | SDK via text createAgentSession() |
| Tools | Default coding tools | Custom OpenClaw tool suite |
| System prompt | AGENTS.md + prompts | Dynamic per-channel/context |
| Session storage | text ~/.pi/agent/sessions/ | text ~/.openclaw/agents/<agentId>/sessions/text $OPENCLAW_STATE_DIR/agents/<agentId>/sessions/ |
| Auth | Single credential | Multi-profile with rotation |
| Extensions | Loaded from disk | Programmatic + disk paths |
| Event handling | TUI rendering | Callback-based (onBlockReply, etc.) |
Areas for potential rework:
guardSessionManagerResourceLoadersubscribeEmbeddedPiSessionPi integration coverage spans these suites:
src/agents/pi-*.test.tssrc/agents/pi-auth-json.test.tssrc/agents/pi-embedded-*.test.tssrc/agents/pi-embedded-helpers*.test.tssrc/agents/pi-embedded-runner*.test.tssrc/agents/pi-embedded-runner/**/*.test.tssrc/agents/pi-embedded-subscribe*.test.tssrc/agents/pi-tools*.test.tssrc/agents/pi-tool-definition-adapter*.test.tssrc/agents/pi-settings.test.tssrc/agents/pi-hooks/**/*.test.tsLive/opt-in:
src/agents/pi-embedded-runner-extraparams.live.test.tsOPENCLAW_LIVE_TEST=1For current run commands, see Pi Development Workflow.
© 2024 TaskFlow Mirror
Powered by TaskFlow Sync Engine