docs/docs/id/pi.md
2026-04-22 04:29:01 +00:00

22 KiB

read_when summary title x-i18n
Memahami desain integrasi SDK Pi di OpenClaw
Memodifikasi siklus hidup sesi agen, tooling, atau pengkabelan provider untuk Pi
Arsitektur integrasi agen Pi tertanam OpenClaw dan siklus hidup sesi Arsitektur Integrasi Pi
generated_at model provider source_hash source_path workflow
2026-04-22T04:23:19Z gpt-5.4 openai 0ab2934958cd699b585ce57da5ac3077754d46725e74a8e604afc14d2b4ca022 pi.md 15

Arsitektur Integrasi Pi

Dokumen ini menjelaskan bagaimana OpenClaw terintegrasi dengan pi-coding-agent dan paket saudaranya (pi-ai, pi-agent-core, pi-tui) untuk mendukung kemampuan agen AI-nya.

Ikhtisar

OpenClaw menggunakan SDK pi untuk menanamkan agen coding AI ke dalam arsitektur gateway pesan. Alih-alih menjalankan pi sebagai subprocess atau menggunakan mode RPC, OpenClaw secara langsung mengimpor dan membuat instance AgentSession pi melalui createAgentSession(). Pendekatan tertanam ini memberikan:

  • Kontrol penuh atas siklus hidup sesi dan penanganan event
  • Injeksi tool kustom (messaging, sandbox, aksi khusus channel)
  • Kustomisasi system prompt per channel/konteks
  • Persistensi sesi dengan dukungan branching/Compaction
  • Rotasi profil auth multi-akun dengan failover
  • Peralihan model yang agnostik provider

Dependensi Paket

{
  "@mariozechner/pi-agent-core": "0.68.1",
  "@mariozechner/pi-ai": "0.68.1",
  "@mariozechner/pi-coding-agent": "0.68.1",
  "@mariozechner/pi-tui": "0.68.1"
}
Package Purpose
pi-ai Abstraksi LLM inti: Model, streamSimple, tipe pesan, API provider
pi-agent-core Loop agen, eksekusi tool, tipe AgentMessage
pi-coding-agent SDK tingkat tinggi: createAgentSession, SessionManager, AuthStorage, ModelRegistry, tool bawaan
pi-tui Komponen UI terminal (digunakan dalam mode TUI lokal OpenClaw)

Struktur File

src/agents/
├── pi-embedded-runner.ts          # Ekspor ulang dari pi-embedded-runner/
├── pi-embedded-runner/
│   ├── run.ts                     # Entri utama: runEmbeddedPiAgent()
│   ├── run/
│   │   ├── attempt.ts             # Logika satu percobaan dengan penyiapan sesi
│   │   ├── params.ts              # Tipe RunEmbeddedPiAgentParams
│   │   ├── payloads.ts            # Membangun payload respons dari hasil run
│   │   ├── images.ts              # Injeksi gambar model vision
│   │   └── types.ts               # EmbeddedRunAttemptResult
│   ├── abort.ts                   # Deteksi error abort
│   ├── cache-ttl.ts               # Pelacakan TTL cache untuk pruning konteks
│   ├── compact.ts                 # Logika Compaction manual/otomatis
│   ├── extensions.ts              # Memuat ekstensi pi untuk run tertanam
│   ├── extra-params.ts            # Parameter stream khusus provider
│   ├── google.ts                  # Perbaikan urutan giliran Google/Gemini
│   ├── history.ts                 # Pembatasan riwayat (DM vs grup)
│   ├── lanes.ts                   # Lajur perintah sesi/global
│   ├── logger.ts                  # Logger subsistem
│   ├── model.ts                   # Resolusi model melalui ModelRegistry
│   ├── runs.ts                    # Pelacakan run aktif, abort, antrean
│   ├── sandbox-info.ts            # Info sandbox untuk system prompt
│   ├── session-manager-cache.ts   # Caching instance SessionManager
│   ├── session-manager-init.ts    # Inisialisasi file sesi
│   ├── system-prompt.ts           # Builder system prompt
│   ├── tool-split.ts              # Memisahkan tool menjadi builtIn vs custom
│   ├── types.ts                   # EmbeddedPiAgentMeta, EmbeddedPiRunResult
│   └── utils.ts                   # Pemetaan ThinkLevel, deskripsi error
├── pi-embedded-subscribe.ts       # Langganan/pengiriman event sesi
├── pi-embedded-subscribe.types.ts # SubscribeEmbeddedPiSessionParams
├── pi-embedded-subscribe.handlers.ts # Factory handler event
├── pi-embedded-subscribe.handlers.lifecycle.ts
├── pi-embedded-subscribe.handlers.types.ts
├── pi-embedded-block-chunker.ts   # Chunking balasan blok untuk streaming
├── pi-embedded-messaging.ts       # Pelacakan pengiriman tool messaging
├── pi-embedded-helpers.ts         # Klasifikasi error, validasi giliran
├── pi-embedded-helpers/           # Modul helper
├── pi-embedded-utils.ts           # Utilitas pemformatan
├── pi-tools.ts                    # createOpenClawCodingTools()
├── pi-tools.abort.ts              # Pembungkusan AbortSignal untuk tool
├── pi-tools.policy.ts             # Kebijakan allowlist/denylist tool
├── pi-tools.read.ts               # Kustomisasi tool baca
├── pi-tools.schema.ts             # Normalisasi skema tool
├── pi-tools.types.ts              # Alias tipe AnyAgentTool
├── pi-tool-definition-adapter.ts  # Adapter AgentTool -> ToolDefinition
├── pi-settings.ts                 # Override pengaturan
├── pi-hooks/                      # Hook pi kustom
│   ├── compaction-safeguard.ts    # Ekstensi safeguard
│   ├── compaction-safeguard-runtime.ts
│   ├── context-pruning.ts         # Ekstensi pruning konteks cache-TTL
│   └── context-pruning/
├── model-auth.ts                  # Resolusi profil auth
├── auth-profiles.ts               # Penyimpanan profil, cooldown, failover
├── model-selection.ts             # Resolusi model default
├── models-config.ts               # Generasi models.json
├── model-catalog.ts               # Cache katalog model
├── context-window-guard.ts        # Validasi jendela konteks
├── failover-error.ts              # Kelas FailoverError
├── defaults.ts                    # DEFAULT_PROVIDER, DEFAULT_MODEL
├── system-prompt.ts               # buildAgentSystemPrompt()
├── system-prompt-params.ts        # Resolusi parameter system prompt
├── system-prompt-report.ts        # Generasi laporan debug
├── tool-summaries.ts              # Ringkasan deskripsi tool
├── tool-policy.ts                 # Resolusi kebijakan tool
├── transcript-policy.ts           # Kebijakan validasi transkrip
├── skills.ts                      # Pembangunan snapshot/prompt Skills
├── skills/                        # Subsistem skill
├── sandbox.ts                     # Resolusi konteks sandbox
├── sandbox/                       # Subsistem sandbox
├── channel-tools.ts               # Injeksi tool khusus channel
├── openclaw-tools.ts              # Tool khusus OpenClaw
├── bash-tools.ts                  # Tool exec/process
├── apply-patch.ts                 # Tool apply_patch (OpenAI)
├── tools/                         # Implementasi tool individual
│   ├── 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
│   └── ...
└── ...

Runtime aksi pesan khusus channel sekarang berada di direktori ekstensi milik Plugin alih-alih di bawah src/agents/tools, misalnya:

  • file runtime aksi Plugin Discord
  • file runtime aksi Plugin Slack
  • file runtime aksi Plugin Telegram
  • file runtime aksi Plugin WhatsApp

Alur Integrasi Inti

1. Menjalankan Agen Tertanam

Titik masuk utama adalah runEmbeddedPiAgent() di pi-embedded-runner/run.ts:

import { 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);
  },
});

2. Pembuatan Sesi

Di dalam runEmbeddedAttempt() (dipanggil oleh runEmbeddedPiAgent()), SDK pi digunakan:

import {
  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);

3. Langganan Event

subscribeEmbeddedPiSession() berlangganan event AgentSession pi:

const 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,
});

Event yang ditangani mencakup:

  • message_start / message_end / message_update (streaming teks/thinking)
  • tool_execution_start / tool_execution_update / tool_execution_end
  • turn_start / turn_end
  • agent_start / agent_end
  • compaction_start / compaction_end

4. Prompting

Setelah penyiapan, sesi diberi prompt:

await session.prompt(effectivePrompt, { images: imageResult.images });

SDK menangani loop agen penuh: mengirim ke LLM, menjalankan pemanggilan tool, dan melakukan streaming respons.

Injeksi gambar bersifat lokal terhadap prompt: OpenClaw memuat ref gambar dari prompt saat ini dan meneruskannya melalui images hanya untuk giliran tersebut. OpenClaw tidak memindai ulang giliran riwayat lama untuk menginjeksi ulang payload gambar.

Arsitektur Tool

Pipeline Tool

  1. Tool Dasar: codingTools milik pi (read, bash, edit, write)
  2. Pengganti Kustom: OpenClaw mengganti bash dengan exec/process, menyesuaikan read/edit/write untuk sandbox
  3. Tool OpenClaw: messaging, browser, canvas, sessions, Cron, gateway, dll.
  4. Tool Channel: tool aksi khusus Discord/Telegram/Slack/WhatsApp
  5. Pemfilteran Kebijakan: tool difilter berdasarkan profil, provider, agen, grup, dan kebijakan sandbox
  6. Normalisasi Skema: skema dibersihkan untuk quirk Gemini/OpenAI
  7. Pembungkusan AbortSignal: tool dibungkus agar mematuhi abort signal

Adapter Definisi Tool

AgentTool milik pi-agent-core memiliki signature execute yang berbeda dibanding ToolDefinition milik pi-coding-agent. Adapter di pi-tool-definition-adapter.ts menjembatani ini:

export 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) => {
      // signature pi-coding-agent berbeda dari pi-agent-core
      return await tool.execute(toolCallId, params, signal, onUpdate);
    },
  }));
}

Strategi Pemisahan Tool

splitSdkTools() meneruskan semua tool melalui customTools:

export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) {
  return {
    builtInTools: [], // Kosong. Kami menimpa semuanya
    customTools: toToolDefinitions(options.tools),
  };
}

Ini memastikan pemfilteran kebijakan, integrasi sandbox, dan kumpulan tool yang diperluas milik OpenClaw tetap konsisten di seluruh provider.

Konstruksi System Prompt

System prompt dibangun di buildAgentSystemPrompt() (system-prompt.ts). Fungsi ini merakit prompt penuh dengan bagian-bagian termasuk Tooling, Gaya Pemanggilan Tool, guardrail keamanan, referensi CLI OpenClaw, Skills, Docs, Workspace, Sandbox, Messaging, Tag Balasan, Voice, Balasan Senyap, Heartbeat, metadata runtime, serta Memory dan Reactions saat diaktifkan, dan file konteks opsional serta konten system prompt tambahan. Bagian-bagian dipangkas untuk mode prompt minimal yang digunakan oleh subagen.

Prompt diterapkan setelah pembuatan sesi melalui applySystemPromptOverrideToSession():

const systemPromptOverride = createSystemPromptOverride(appendPrompt);
applySystemPromptOverrideToSession(session, systemPromptOverride);

Manajemen Sesi

File Sesi

Sesi adalah file JSONL dengan struktur pohon (tautan id/parentId). SessionManager milik Pi menangani persistensi:

const sessionManager = SessionManager.open(params.sessionFile);

OpenClaw membungkus ini dengan guardSessionManager() untuk keamanan hasil tool.

Caching Sesi

session-manager-cache.ts meng-cache instance SessionManager untuk menghindari parsing file berulang:

await prewarmSessionFile(params.sessionFile);
sessionManager = SessionManager.open(params.sessionFile);
trackSessionManagerAccess(params.sessionFile);

Pembatasan Riwayat

limitHistoryTurns() memangkas riwayat percakapan berdasarkan jenis channel (DM vs grup).

Compaction

Compaction otomatis dipicu saat konteks meluap. Tanda overflow yang umum mencakup request_too_large, context length exceeded, input exceeds the maximum number of tokens, input token count exceeds the maximum number of input tokens, input is too long for the model, dan ollama error: context length exceeded. compactEmbeddedPiSessionDirect() menangani Compaction manual:

const compactResult = await compactEmbeddedPiSessionDirect({
  sessionId, sessionFile, provider, model, ...
});

Autentikasi & Resolusi Model

Profil Auth

OpenClaw mempertahankan penyimpanan profil auth dengan beberapa API key per provider:

const authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });

Profil dirotasi saat terjadi kegagalan dengan pelacakan cooldown:

await markAuthProfileFailure({ store, profileId, reason, cfg, agentDir });
const rotated = await advanceAuthProfile();

Resolusi Model

import { resolveModel } from "./pi-embedded-runner/model.js";

const { model, error, authStorage, modelRegistry } = resolveModel(
  provider,
  modelId,
  agentDir,
  config,
);

// Menggunakan ModelRegistry dan AuthStorage milik Pi
authStorage.setRuntimeApiKey(model.provider, apiKeyInfo.apiKey);

Failover

FailoverError memicu fallback model saat dikonfigurasi:

if (fallbackConfigured && isFailoverErrorMessage(errorText)) {
  throw new FailoverError(errorText, {
    reason: promptFailoverReason ?? "unknown",
    provider,
    model: modelId,
    profileId,
    status: resolveFailoverStatus(promptFailoverReason),
  });
}

Ekstensi Pi

OpenClaw memuat ekstensi Pi kustom untuk perilaku khusus:

Safeguard Compaction

src/agents/pi-hooks/compaction-safeguard.ts menambahkan guardrail ke Compaction, termasuk penganggaran token adaptif serta ringkasan kegagalan tool dan operasi file:

if (resolveCompactionMode(params.cfg) === "safeguard") {
  setCompactionSafeguardRuntime(params.sessionManager, { maxHistoryShare });
  paths.push(resolvePiExtensionPath("compaction-safeguard"));
}

Pruning Konteks

src/agents/pi-hooks/context-pruning.ts mengimplementasikan pruning konteks berbasis cache-TTL:

if (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") {
  setContextPruningRuntime(params.sessionManager, {
    settings,
    contextWindowTokens,
    isToolPrunable,
    lastCacheTouchAt,
  });
  paths.push(resolvePiExtensionPath("context-pruning"));
}

Streaming & Balasan Blok

Chunking Blok

EmbeddedBlockChunker mengelola streaming teks menjadi blok balasan diskret:

const blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;

Penghapusan Tag Thinking/Final

Output streaming diproses untuk menghapus blok <think>/<thinking> dan mengekstrak konten <final>:

const stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => {
  // Hapus konten <think>...</think>
  // Jika enforceFinalTag, hanya kembalikan konten <final>...</final>
};

Directive Balasan

Directive balasan seperti [[media:url]], [[voice]], [[reply:id]] di-parse dan diekstrak:

const { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);

Penanganan Error

Klasifikasi Error

pi-embedded-helpers.ts mengklasifikasikan error untuk penanganan yang sesuai:

isContextOverflowError(errorText)     // Konteks terlalu besar
isCompactionFailureError(errorText)   // Compaction gagal
isAuthAssistantError(lastAssistant)   // Kegagalan auth
isRateLimitAssistantError(...)        // Terkena rate limit
isFailoverAssistantError(...)         // Harus failover
classifyFailoverReason(errorText)     // "auth" | "rate_limit" | "quota" | "timeout" | ...

Fallback Tingkat Thinking

Jika tingkat thinking tidak didukung, sistem menggunakan fallback:

const fallbackThinking = pickFallbackThinkingLevel({
  message: errorText,
  attempted: attemptedThinking,
});
if (fallbackThinking) {
  thinkLevel = fallbackThinking;
  continue;
}

Integrasi Sandbox

Saat mode sandbox diaktifkan, tool dan path dibatasi:

const sandbox = await resolveSandboxContext({
  config: params.config,
  sessionKey: sandboxSessionKey,
  workspaceDir: resolvedWorkspace,
});

if (sandboxRoot) {
  // Gunakan tool read/edit/write yang di-sandbox
  // Exec berjalan di container
  // Browser menggunakan URL bridge
}

Penanganan Khusus Provider

Anthropic

  • Scrubbing magic string penolakan
  • Validasi giliran untuk peran berurutan
  • Validasi parameter tool Pi upstream yang ketat

Google/Gemini

  • Sanitasi skema tool milik Plugin

OpenAI

  • Tool apply_patch untuk model Codex
  • Penanganan penurunan tingkat thinking

Integrasi TUI

OpenClaw juga memiliki mode TUI lokal yang menggunakan komponen pi-tui secara langsung:

// src/tui/tui.ts
import { ... } from "@mariozechner/pi-tui";

Ini menyediakan pengalaman terminal interaktif yang mirip dengan mode native Pi.

Perbedaan Utama dari Pi CLI

Aspect Pi CLI OpenClaw Embedded
Invocation perintah pi / RPC SDK melalui createAgentSession()
Tools Tool coding default Kumpulan tool OpenClaw kustom
System prompt AGENTS.md + prompt Dinamis per channel/konteks
Session storage ~/.pi/agent/sessions/ ~/.openclaw/agents/<agentId>/sessions/ (atau $OPENCLAW_STATE_DIR/agents/<agentId>/sessions/)
Auth Kredensial tunggal Multi-profil dengan rotasi
Extensions Dimuat dari disk Path terprogram + disk
Event handling Rendering TUI Berbasis callback (onBlockReply, dll.)

Pertimbangan Mendatang

Area yang berpotensi dikerjakan ulang:

  1. Penyelarasan signature tool: Saat ini mengadaptasi antara signature pi-agent-core dan pi-coding-agent
  2. Pembungkusan session manager: guardSessionManager menambah keamanan tetapi meningkatkan kompleksitas
  3. Pemuatan ekstensi: Bisa menggunakan ResourceLoader milik Pi secara lebih langsung
  4. Kompleksitas handler streaming: subscribeEmbeddedPiSession telah berkembang besar
  5. Keunikan provider: Banyak codepath khusus provider yang berpotensi dapat ditangani oleh Pi

Pengujian

Cakupan integrasi Pi mencakup suite berikut:

  • src/agents/pi-*.test.ts
  • src/agents/pi-auth-json.test.ts
  • src/agents/pi-embedded-*.test.ts
  • src/agents/pi-embedded-helpers*.test.ts
  • src/agents/pi-embedded-runner*.test.ts
  • src/agents/pi-embedded-runner/**/*.test.ts
  • src/agents/pi-embedded-subscribe*.test.ts
  • src/agents/pi-tools*.test.ts
  • src/agents/pi-tool-definition-adapter*.test.ts
  • src/agents/pi-settings.test.ts
  • src/agents/pi-hooks/**/*.test.ts

Live/opsional:

  • src/agents/pi-embedded-runner-extraparams.live.test.ts (aktifkan OPENCLAW_LIVE_TEST=1)

Untuk perintah run saat ini, lihat Pi Development Workflow.