pi-faithless-subagents
PI-native constrained subagent orchestration library
Package details
Install pi-faithless-subagents from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-faithless-subagents- Package
pi-faithless-subagents- Version
0.1.9- Published
- Apr 16, 2026
- Downloads
- 1,175/mo · 25/wk
- Author
- faithless
- License
- MIT
- Types
- extension, skill
- Size
- 122 KB
- Dependencies
- 5 dependencies · 0 peers
Pi manifest JSON
{
"extensions": [
"./pi-extension.ts"
],
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-faithless-subagents
Constrained 4-role subagent workflows for PI:
explorerplannerworkerreviewer
The package does not invent workflows. You provide an explicit workflow spec, and the orchestrator validates and runs it.
What changed
The extension now runs subagent steps through PI's own session runtime by default:
- it reuses the active PI model
- it maps role reasoning policy to PI thinking level
- it runs each step in an isolated in-memory PI session
- it exposes only the declared host tools for that step
A legacy OpenAI-backed runner still exists as an explicit fallback for non-PI usage.
Install
npm install pi-faithless-subagents
PI extension tools
This package registers exactly two PI tools:
pi_subagents_run_workflowpi_subagents_run_step
The package manifest is exposed from pi-extension.ts via the normal PI extension mechanism.
Workflow shape
interface WorkflowSpec {
id: string;
steps: StepSpec[];
}
interface StepSpec {
id: string;
role: "explorer" | "planner" | "worker" | "reviewer";
objective: string;
dependsOn?: string[];
inputArtifacts?: string[];
allowedReadPaths?: string[];
allowedWritePaths?: string[];
timeoutMs?: number;
maxTurns?: number;
retryLimit?: number;
optionalDependencies?: string[];
}
Role contracts
Explorer
Purpose:
- inspect the codebase
- identify relevant files
- record facts and open questions
Artifact:
report.md- kind:
report
Required sections:
## Goal## Relevant Files## Findings## Open Questions## Recommended Next Step
Planner
Purpose:
- turn exploration output into an implementation plan
Artifact:
plan.md- kind:
plan
Required sections:
## Goal## Constraints## Implementation Plan## Acceptance Criteria## Risks
Worker
Purpose:
- implement within the declared write scope
Artifact:
implementation-report.md- kind:
implementation-report
Required sections:
## Plan Followed## Files Changed## Tests Run## Known Gaps
Reviewer
Purpose:
- review worker output and produce a verdict
Artifact:
verdict.md- kind:
verdict
Required sections:
## Verdict## Findings## Blocking Issues## Non-Blocking Issues## Recommended Disposition
PI-native execution model
By default, createPiExtension() uses the PI-native runner.
For each step it:
- creates a fresh in-memory PI session
- reuses the active PI model from the calling PI session
- maps role reasoning policy to PI thinking level
- disables extension/skill/prompt/theme discovery for the child session
- exposes only the filtered host tools allowed for that role
- injects upstream artifacts into the step prompt
- validates the returned artifact before marking the step complete
maxTurns is enforced as a PI tool-call cap for the step.
The runtime also applies bounded-memory safeguards by default:
- upstream artifacts injected into prompts are capped and truncated with explicit markers
- serialized tool outputs sent back to models are capped and truncated
- returned artifacts are size-checked before being accepted
- timed out steps abort their child execution via
AbortSignal
Default host tools
When defaultTools is enabled, the package wires in these host tools:
list_filesread_filesearch_textwrite_file(worker only)run_command(worker/reviewer only, allowlisted)
You can also provide your own host tools through piTools.
Default host tools are bounded as well:
read_filereturns at most a capped prefix with truncation metadatalist_filescaps the number of returned entriessearch_textcaps match count and bytes scanned per filerun_commandcaps returnedstdoutandstderr
You can tune these defaults with defaultTools.maxReadFileBytes, defaultTools.maxListEntries, defaultTools.maxSearchMatches, defaultTools.maxSearchFileBytes, defaultTools.maxSearchLineBytes, and defaultTools.maxCommandOutputBytes.
Policy constraints
The orchestrator enforces:
- only
workersteps may declare writable repository paths - every
workerstep must declare at least one writable path - writable paths must remain under
repoRoot - overlapping worker write scopes are rejected
inputArtifactsmay only reference declared dependencies
Path-based host tools are checked against allowedReadPaths and allowedWritePaths at execution time.
PI usage
Example workflow tool payload:
{
"workflow": {
"id": "demo-run",
"steps": [
{
"id": "explore",
"role": "explorer",
"objective": "Inspect src and identify the relevant files",
"allowedReadPaths": ["src"]
},
{
"id": "plan",
"role": "planner",
"objective": "Write an implementation plan from the explorer report",
"dependsOn": ["explore"],
"allowedReadPaths": ["src"]
},
{
"id": "work",
"role": "worker",
"objective": "Implement the approved change",
"dependsOn": ["plan"],
"allowedReadPaths": ["src"],
"allowedWritePaths": ["src"]
},
{
"id": "review",
"role": "reviewer",
"objective": "Review the worker output",
"dependsOn": ["work"],
"allowedReadPaths": ["src"]
}
]
},
"hostContext": {
"repoRoot": "/absolute/path/to/repo",
"runRoot": "/absolute/path/to/run-root"
}
}
Programmatic usage
Full extension
import { createPiExtension } from "pi-faithless-subagents";
const extension = createPiExtension({
defaultTools: { commandAllowlist: ["npm", "node"] }
});
const result = await extension.toolAdapter.callTool({
name: "pi_subagents_run_step",
arguments: {
runId: "review-pass",
step: {
id: "review",
role: "reviewer",
objective: "Review the existing implementation",
allowedReadPaths: ["src", "test"]
},
hostContext: {
repoRoot: "/absolute/path/to/repo",
runRoot: "/absolute/path/to/run-root"
}
}
});
Orchestrator only
import { createPiSubagents, createPiNativeRunner, createDefaultPiHostTools } from "pi-faithless-subagents";
const orchestrator = createPiSubagents({
runner: createPiNativeRunner({
piTools: createDefaultPiHostTools({ commandAllowlist: ["npm"] })
})
});
Legacy OpenAI fallback
import { createPiSubagents, createPiToolBackedOpenAIRunner, createDefaultPiHostTools } from "pi-faithless-subagents";
const orchestrator = createPiSubagents({
runner: createPiToolBackedOpenAIRunner({
apiKey: process.env.OPENAI_API_KEY,
piTools: createDefaultPiHostTools({ commandAllowlist: ["npm"] })
})
});
Run artifacts
A run with id my-run writes to:
<runRoot>/my-run/
Important files:
events.logsteps/<stepId>/attempt-1/metadata.jsonsteps/<stepId>/attempt-1/output/<artifact-file>
Typical output files:
- explorer:
report.md - planner:
plan.md - worker:
implementation-report.md - reviewer:
verdict.md
Main exports
createPiSubagentscreatePiExtensioncreatePiNativeRunnercreateOpenAIRunnercreatePiToolBackedOpenAIRunnercreateDefaultPiHostToolsPI_TOOL_DEFINITIONSROLE_POLICIESSYSTEM_PROMPTS
Commands
npm run build
npm test
npm run check
npm run smoke
npm run smoke:pi
npm run smoke:workflow
Important source files
src/extension.ts— extension assembly and default runner selectionsrc/pi-runner.ts— PI-native step execution backendsrc/openai.ts— legacy OpenAI runnersrc/orchestrator.ts— workflow executionsrc/pi-tools.ts— host tool adaptation and path enforcementsrc/tools.ts— PI tool schemas and adaptersrc/roles.ts— role reasoning and artifact policysrc/artifacts.ts— artifact templates and validationsrc/policy.ts— workflow safety checks