@sage-protocol/pi-adapter
Sage Protocol MCP integration for pi coding agent
Package details
Install @sage-protocol/pi-adapter from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@sage-protocol/pi-adapter- Package
@sage-protocol/pi-adapter- Version
0.5.1- Published
- Sep 12, 2026
- Downloads
- 727/mo · 218/wk
- Author
- hack4kites
- License
- MIT
- Types
- extension
- Size
- 381.4 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./extensions/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@sage-protocol/pi-adapter
Sage integration for the Pi coding agent runtime.
- Pi agent: earendil-works/pi — extensible terminal coding harness
- Compatibility: tested with Pi
0.84.1; package peer range>=0.64.0 <0.85.0 - Sage Protocol: sage-protocol/sage — decentralized capability/library layer for AI agents
What It Does
- Exposes Sage MCP tools (
hub_list_servers,hub_status,hub_session_list,hub_start_server,hub_stop_server,sage_search,sage_execute,sage_status, andsage_behavior) - Lets Pi own skill discovery and loading through native
<available_skills>,/skill:<name>, and fullSKILL.mdreads - Injects SessionStart Sage context and shows the loaded library/skill inventory
- Captures prompts and responses for RLM feedback
- Observes truthful full native skill loads and writes source- and session-qualified load receipts
- Exposes
sage_mark_guided_usein the packaged Pi extension so an agent can bind actually loaded, actually applied skills to the exact prompt capture through Sage's native-use daemon path - Optionally exposes one status-only
sage_wallet_statustool when Glove supplies either a strict inherited connected descriptor declaration or the complete legacy endpoint/root/owner tuple - Preserves optional security hooks and explicit subagent skill resolution
- Keeps Sage-owned skills under
packages/sage/skills/and the curated Pi export surface rather than bundling copies in this adapter
The adapter does not call sage suggest hook skill for each prompt, inject
sage-suggested-skills, or render a suggestion-quality widget. It has no
suggestion auto-skip or auto-reject lifecycle. Manual sage suggest skill "<task>" remains available when a person or agent explicitly wants CLI
ranking, but it is not automatic Pi injection.
Install
# Pi CLI extension (no source changes)
pi install npm:@sage-protocol/pi-adapter
# SDK embedding
npm install @sage-protocol/pi-adapter
Quick Start
import {
createAgentSession,
createCodingTools,
type ToolDefinition as PiToolDefinition,
} from '@earendil-works/pi-coding-agent';
import {
createSageSessionConfig,
type ToolDefinition as SageToolDefinition,
} from '@sage-protocol/pi-adapter';
function asPiCustomTools(tools: SageToolDefinition[]): PiToolDefinition[] {
// Type-shape compatibility across supported Pi minors; no runtime conversion.
return tools as unknown as PiToolDefinition[];
}
const sage = await createSageSessionConfig({ source: 'pi-agent-core' });
const cwd = process.cwd();
const securedTools = sage.wrapToolsWithSecurity(createCodingTools(cwd));
const { session } = await createAgentSession({
cwd,
noTools: 'builtin',
customTools: asPiCustomTools([...securedTools, ...sage.customTools]),
});
const disposeSageHooks = sage.setupHooks(session);
In current Pi, tools is a string allowlist. Tool definitions belong in
customTools; noTools: 'builtin' prevents duplicate unwrapped built-ins. The
single helper cast is only the TypeScript peer-version boundary between the
adapter's cross-minor tool shape and Pi's generic ToolDefinition—it does not
convert anything at runtime.
Pi presents its native skill catalog separately. When a skill applies, load it
with /skill:<name> or read its complete SKILL.md, follow the procedure, then
call sage_mark_guided_use only if the loaded procedure actually guided the
current turn. Loading alone is not use.
API
createSageSessionConfig(config) returns:
{
customTools: ToolDefinition[]; // Sage hub and code-mode bridge tools
mcpBridge: SageMcpBridge; // MCP process lifecycle
setupHooks: (session: AgentSession) => () => void; // SessionStart + capture hooks
wrapToolsWithSecurity: (tools: ToolDefinition[]) => ToolDefinition[];
}
Recommended configuration:
interface SageP2Config {
sageBin?: string; // default: "sage"
sageProfile?: string; // Sage config profile
timeoutMs?: number; // default: 20_000
enableRlmFeedback?: boolean;
enableSecurityHooks?: boolean;
source?: string; // default: "pi"
// Inherited mode: both exact Glove values are required, with no legacy fields.
gloveLocalServiceFdsV1?: string; // exact JSON alias-to-FD map
gloveGuestChannelServiceAlias?: string; // exact wallet service alias
// Legacy mode: all three are required, with no inherited fields.
gloveGuestChannelEndpoint?: string; // canonical absolute Unix socket path
gloveGuestChannelRoot?: string; // canonical absolute trusted root
gloveGuestChannelOwnerUid?: number; // isolated socket-owner UID (not Pi's UID)
env?: Record<string, string>;
/** @deprecated Low-level legacy suggestion compatibility; ignored by the default Pi path. */
suggestLimit?: number;
/** @deprecated Low-level legacy suggestion compatibility; ignored by the default Pi path. */
suggestDebounceMs?: number;
/** @deprecated Low-level legacy suggestion compatibility; ignored by the default Pi path. */
enableProvision?: boolean;
}
Migrating to 0.4
Version 0.4 moves Pi skill discovery and loading to Pi's native skill surface.
The legacy sageInjectSuggestion(...) method is retained as a no-op for
compatibility, and default setup no longer performs automatic suggestions. Do
not call sageInjectSuggestion; use Pi's native skill load flow and call
sage_mark_guided_use after an actually loaded skill guides the current prompt.
The guided-use write requires both the Sage CLI command
sage suggest feedback native-use and daemon capability native_skill_use_v1.
Version 0.4.2 reports which runtime half is stale instead of collapsing either
case into a generic write failure. It never falls back to weaker suggestion
feedback. Update the CLI when it lacks the command; update and restart saged
when the daemon lacks the capability. Then retry the same declaration.
Docs
- Usage Guide — native skill flow, integration modes, env vars
- Setup — install and verify
- Developer Guide — build, test, CI contract
- SKILL.md — agent-driven integration skill
Validate
npm test
npm run typecheck
npm run build
git diff --check
License
MIT
Session inbox liveness (shared with hook-driven harnesses)
The adapter currently renews the daemon lease from its own 2 s poll in
src/intercom.ts. The Sage CLI now ships a harness-agnostic keepalive,
sage inbox keepalive --auth-file <capability> --watch-pid <pid>, which is what
hook-driven harnesses (Claude Code, Codex) use. A follow-up can have the adapter
spawn it detached after saveAuth with process.pid as the watched host, send
heartbeat only on idle/busy transitions, and replace the receive poll with
sage inbox receive --auth-file <capability> --wait <secs>, so both harness
families share one liveness mechanism. Fencing (session_inbox_fenced) stops
both the adapter timer and the keepalive.