migrating-pi-to-pydantic-ai

Migrate TypeScript Pi coding-agent applications, extensions, or packages to Python with Pydantic AI and Pydantic AI Harness. Use when source code imports `@earendil-works/pi-*`, calls `createAgentSession`, registers Pi extensions, or relies on Pi tools, hooks, skills, sessions, compaction, providers, TUI, RPC, or packages.

Install
npx skills add 'https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim/pydantic_ai/.agents/skills/migrating-pi-to-pydantic-ai'
Download bundle ↓
main · 9e9fdc4Scanned 2026-09-17

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗

references/RESEARCH-AND-MAPPING.md

references/RESEARCH-AND-MAPPING.mdBrowse 4 files
View on GitHub
← Back to SKILL.md

Research and concept mapping

Use this reference conditionally after tracing the source path. It is a decision guide, not a requirement to reproduce the whole Pi host.

Primary documentation

Inspect installed versions before migrating because Pi, Pydantic AI, and Harness continue to evolve.

Pi is TypeScript and Pydantic AI is Python. Capture existing RPC, event, provider, and persisted-record boundaries with language-neutral fixtures and preserve field names with explicit adapters where required.

Extension-to-capability decision table

Pi extension responsibilityTarget owner and likely seamWhat must be proved
registerTool() with instructions and related policyCore: typed function, Tool, toolset, or declarative Capability; Harness: existing focused capability when semantics matchTool name/schema, guidance, validation, progress/result/error shape, cancellation, parallelism, output limits, and effects.
Reusable extension behavior spanning tools, instructions, and hooksCore: custom AbstractCapability, optionally composed from smaller capabilitiesRun binding, hook ordering, emitted typed capability events, state lifetime, errors, and composition with sibling capabilities.
before_agent_start system-prompt injectionCore: static/dynamic instructions or a custom capability hook; Harness: SystemReminders for matching cache-safe reinjectionExact firing frequency, trusted data interpolation, cache impact, and whether injected content persists in history.
context message rewriting or custom compactionCore: ProcessHistory; Core/Harness: a matching compaction strategy; Application: persisted summary/branch policyWhich messages are removed/mutated, summary boundary, retries, token thresholds, restore behavior, and visibility to callers.
tool_call mutation/blockingCore: tool preparation or toolset wrapper for schema/args; Harness: ToolGuardrail; Core: deferred approval for protected effectsPre-validation vs post-validation timing, handler order, mutation revalidation, block reason, termination, authorization, and side effects.
tool_result modificationCore: toolset wrapper or custom capability around the tool lifecycle; Harness: tool guardrail/output-limit capability where matchingResult content/details/error/usage, order, retries, persistence, stream events, and terminal behavior.
Model/message/tool lifecycle listenersCore: Hooks, ProcessEventStream, @on_event, or capability events; Application: observability/event adapterEvent set and order, sync/async timing, listener errors, stream activation, cancellation, and public serialization.
registerCommand, shortcuts, flags, dialogs, widgets, renderers, editor/footer/theme changesApplication/interface host, such as a custom CLI, web UI, ACP host, or retained Pi frontendCommand routing, input/output, keyboard behavior, mode fallbacks, accessibility, cancellation, and terminal snapshots where contractual.
appendEntry, labels, session name, branch/tree navigationApplication: session/log/navigation model; Core: normalized messages only; Harness: StepPersistence only for matching run continuationAppend-only/tree behavior, stable IDs, branches, labels, abandoned history, extension data, restart, and migration of existing JSONL.
sendMessage, sendUserMessage, steering, follow-up queuesCore: explicit run messages, RunContext.enqueue() from in-run tools/capabilities, or AgentRun.enqueue() from external drivers where lifecycle matches; Application: queue/session controlDelivery point, trigger behavior, expansion, concurrent input, retries/compaction interaction, order, and cancellation.
registerProvider, model catalog/auth, payload/header hooks, custom streamingCore/model integration or Application transport, not a generic capability by defaultCredential precedence, refresh, model selection, request/response wire fixtures, usage, errors, abort, tool calls, and streaming.
Resource discovery and reloadApplication: configuration/discovery/reload; Harness: construct selected capability/Skills instances per run/processSearch roots, precedence, trust, snapshots vs hot reload, diagnostics, and behavior for removed/changed resources.
Pi package manifest and pi installDistribution/Application: Python package exposing capabilities plus optional host adaptersInstalled assets, dependency/extras boundary, enable/disable configuration, trust, version pin/update behavior, and wheel contents.
Project trustApplication security policyWhich files/code/settings load before and after trust, persistence of decisions, non-interactive behavior, and confirmation that trust is not a sandbox.
Shared extension event busApplication event bus for host coordination; Core capability events only for typed agent-run coordinationNames, payloads, scope, listener order/errors, restart behavior, and whether events enter model/UI streams.

Agent and runtime ownership map

Observed Pi behaviorTarget owner and likely seamFocused proof
createAgentSession().prompt() and final assistant messageCore: reusable Agent.run(); Application: result adapterAssert public input/output/error, messages, usage/cost, tool effects, and model selection.
Pi's default read/write/edit/bash coding loopHarness: Coder only when Coder's exact six-tool composition and unrestricted host shell match the required behavior; otherwise compose FileSystem, Shell, RepoContext, context controls, and custom toolsCompare exact tool schemas, edit semantics, cwd, ignores/protected paths, command allowlisting or rejection, truncation, process lifetime, environment, and cancellation.
Pi AgentSession event subscriptionCore: run_stream_events(), iter(), agent/capability/custom events; Application: event adapterGolden-test only consumed event types/fields, order, reconstruction, usage, terminal detection, errors, and cancellation.
Pi session messagesCore: serialized ModelMessage history; Application: session ownership/storeContinue from real persisted records in a fresh process and test incomplete tool calls and cross-session isolation.
JSONL session tree, fork/clone/switch, compaction/branch entries, model/thinking changesApplication: explicit session format and navigation; Harness StepPersistence: only when agent run resume/fork semantics fitTest every consumed record type, branch restoration, compaction context, stable cursors, crash recovery, and old-record migration.
Automatic retry and overflow compactionCore/provider retry settings plus Core/Harness compaction and application loop policyAssert triggering error classes, delay/limits, cancellation, failed-message handling, retry count, and context after compaction.
Skills and /skill:nameHarness: Skills for configured SKILL.md instructions; Application: command/discovery layer and resources/scriptsAssert explicit library roots, selected catalog, instruction loading, missing resources, reload behavior, trust, and behavioral frontmatter differences.
Dynamic tool loading via setActiveTools()Core: ToolSearch, deferred Capability, or per-step tool preparationAssert initial catalog, selection, next-request availability, removals, provider-native/fallback protocol, and prompt-cache effects.
Plan-mode extensionHarness: Planning when the model-owned plan lifecycle fits; Application: command/widget; otherwise custom capability/stateAssert plan ownership, updates, reminders, persistence, user edits, UI, and behavior across compaction/restart.
Subagent extension or spawned Pi processHarness: SubAgents for model-directed isolated delegation; Application: subprocess orchestration when process/session semantics matterAssert task input, tools/capabilities, history isolation, model choice, result/events, budgets, cancellation, errors, and recursion.
Permission/protected-path extensionHarness: guardrail and/or Core: approval; Application: trusted policy and approver UIExercise allow/block/approve/deny, symlink/path cases, identity, audit, and exactly-once protected effect.
Sandbox or SSH extensionHarness: FileSystem, Shell, or ModalSandbox; Application: selected remote/sandbox backendExercise filesystem/shell operations, cwd, network, credentials, timeouts, cleanup, and real containment against escapes.
Pi RPC or JSON modeApplication: preserve protocol with a Python adapter or intentionally adopt a Pydantic AI UI protocolRun the same language-neutral request/event fixtures, including errors, mid-run input, abort, command listing, and session operations.
Pi TUIApplication/interface: retain Pi temporarily, build a host, use clai, ACP, web chat, or another adapter according to observed needsTest only user-facing behavior in scope; capability parity does not prove terminal UI parity.
Pi skills/prompts/extensions/packages as one installable packagePython distribution: capabilities, skill assets, and host integration can ship together but remain separate runtime ownersInspect wheel, import selected capabilities, discover skill assets explicitly, and test host startup without dev dependencies.
Telemetry and extension loggingCore: instrumentation/OpenTelemetry; optional Logfire; Application: existing backend and logsAssert correlation, content/privacy, required spans/events, nested usage, retention, dashboards, and alerts before switching.

Common plugin ports

  • Custom tool extension: start with a typed tool. Use a declarative Capability only when the tool and its instructions should travel together; subclass only if hooks or events are also required.
  • Permission gate: separate policy evaluation, approval pause, and approver UI. Usually this is a guardrail or tool wrapper plus core deferred approval plus an application interface—not one monolithic capability.
  • Plan mode: use Harness Planning for model-owned plans, while slash commands and widgets remain interface code.
  • Subagent package: use Harness SubAgents only when Pi's subprocess/session behavior is not itself contractual.
  • Coding/sandbox package: compare Coder first, then compose smaller filesystem/shell/repo-context capabilities. Add a real sandbox independently when untrusted execution is in scope.
  • Provider package: implement the model/provider transport and keep login/catalog UI in the host; do not route provider payload rewriting through an agent capability unless it is genuinely per-run policy.
Referenced from SKILL.md