pi-delegation-policy

A Pi extension for configurable delegation intensity and exact subagent role model references.

Packages

Package details

extension

Install pi-delegation-policy from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-delegation-policy
Package
pi-delegation-policy
Version
0.12.0
Published
Sep 20, 2026
Downloads
2,636/mo · 399/wk
Author
yivas
License
MIT
Types
extension
Size
281.8 KB
Dependencies
0 dependencies · 3 peers
Pi manifest JSON
{
  "subagents": {
    "agents": [
      "./agents"
    ]
  },
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-delegation-policy

A local Pi extension that helps the main agent decide when delegation is worth it and which exact models to use for Small, Medium, Large, and optional Visual Design. It provides guidance; it is not a subagent runner.

Status: Version 0.12.0 is the latest published package and supports off, normal, aggressive, and orchestrator. The package peer range is Pi >=0.84.3; Pi 0.84.3 is the minimum supported version and Pi 0.85.1 is the explicitly checked baseline.

Docs: Read the documentation site.

Value and boundary

  • Choose off, normal, aggressive, or orchestrator globally or for the current session branch.
  • Configure an exact provider/model reference or explicitly disable each ordinary role.
  • Optionally bind a thinking level, or an inclusive level range, per role; leave a role unset and the main agent chooses its level per launch.
  • Optionally add an Advisor model and consult it on demand with the explicit advisor_ask tool; it advises and executes no work.
  • Keep global defaults and session-branch overrides across reload, resume, and tree navigation.
  • Validate active configurations before injecting one policy block through Pi's public before_agent_start event.
  • Optionally use ContextShunt to observe or enforce bounded handling of recognized oversized text results without launching a worker, and to ask the context_shunt_delegate reader one question about a preserved result.

The extension guides the main agent. It never routes or supervises subagents, never changes Pi's main model or thinking, never stores credentials, and makes no network request of its own. Two explicit tools ask the host-authorized external executor for one bounded answer: context_shunt_delegate for one question about an already-preserved text artifact, and advisor_ask for one piece of advice. Neither is ever invoked from a hook, and neither replaces delegation, the launcher, tool permissions, or a remote backend. ContextShunt is opt-in: off performs no classification, metrics, archival, or interception; observe records only what enforcement would block; and enforce blocks only recognized declared excess and replaces only successfully preserved, known textual results. It never bypasses the tool permission/backend, runs a command again, or launches a worker from a hook. Enforcement checks Pi's public tool provenance and leaves same-named extension or SDK tools unchanged; observe may report those names only as non-binding heuristics. In 0.9.0 orchestrator, an enabled capable role and authorized launcher require delegation of all transferable execution before it begins, regardless of size: small lookups, code reading, detailed planning, edits, tests, writing, detailed review, and integration mechanics. Bootstrap is limited to mandatory instructions, tool discovery, and a narrow assignment scope; after assigning, the main agent coordinates only disjoint work, waits through the host, and consumes results before dependencies or finalizing. It retains strategy, critical user decisions, coordination, safety, evidence evaluation, final acceptance, and concise synthesis, not permission to perform transferable review or integration. Direct work requires a briefly stated concrete exception: genuinely non-transferable work, no enabled capable role, a confirmed unavailable authorized launcher, or an explicit user or higher-priority requirement. It reinspects only a concrete gap, risk, or contradiction and delegates transferable fixes or rechecks. A final-review or integration label, size, triviality, convenience, economics, transfer cost, or familiarity never justifies doing the whole task personally. Published 0.7.0 retains its original policy; 0.9.0 contains this stricter guidance. It has no model fallback, telemetry, project configuration, presets, or external skill loading.

A valid active policy requires an explicit decision for Small, Medium, and Large: an exact model reference or disabled. At least one ordinary role must remain enabled. A disabled role is not validated. An absent role, an invalid enabled reference, or no enabled ordinary role produces D:ERR and injects no policy. A configured thinking policy whose level the role's model does not support is another D:ERR cause and names the role, level, and model. off always produces D:OFF without injection.

Inspiration and attribution

ContextShunt is inspired by the large-read routing pattern described in Spotify Engineering's article on Portal and shunt and its shunt plugin. It is an independent adaptation for Pi: it does not integrate Portal or AiKA, launch a worker automatically, or claim affiliation or endorsement.

The policy considers only enabled ordinary roles, chooses the least costly role that can satisfy the task's acceptance criteria and evidence, and keeps work with the main agent when none can. It never invents a model or role. efficient and intensive are tie-breaks only when both Small and Medium are enabled; otherwise their bias is inactive.

Visual Design is an independent optional specialist for direction, assets, bounded presentation-layer implementation, and visual review. Use it only when behavior and data contracts are already defined and unchanged, the affected surface is bounded, and visual quality or user experience is the primary acceptance criterion. It does not count as an ordinary role or replace one. When configured, evaluate those four conditions before ordinary-role selection for every task or phase. If they hold and the main agent chooses to delegate that visual portion, or the active intensity requires delegation, it must select Visual Design instead of Small, Medium, or Large, using Visual Design's exact configured provider/model and that role's thinking policy. Reevaluate when the task or phase changes. This priority does not make normal or aggressive delegate more work. In published 0.7.0 and normal or aggressive, route business logic, data, APIs, routes, application architecture, tooling, interaction behavior, and cross-system integration to an enabled ordinary role by task fit; the main agent retains final integration and acceptance. In 0.9.0 orchestrator, the main agent instead retains integration responsibility, coordination, and final acceptance while a capable ordinary role performs transferable integration mechanics and detailed review unless a named direct-work exception applies.

Advisor is an optional second consultation model, off by default and not part of the ordinary-role minimum. Configure it as an exact reference in global defaults, or null in a session to turn it off, with its own optional thinking policy. When it is configured and valid, the main agent may call the explicit advisor_ask tool with a question, optional extra context, and the thinking level for that call. The advisor answers in bounded plain text — at most 8 KiB, returned with the model and level that produced it — and executes no work of its own. Configuring nothing changes nothing: advisor_ask then answers advisor-unavailable and the agent continues. A configured advisor whose model is missing, out of scope, or unauthenticated produces D:ERR and injects no policy; because that check is shared, it also leaves the ContextShunt reader unauthorized. Using the tool sends the advisor's model a bounded window of the current conversation; the limits and privacy reference states exactly what that window includes, what it excludes, the size cap, and what the executor and its provider may retain.

ContextShunt reader is an optional capability of the same opt-in layer, off by default. ContextShunt registers two normal tools: context_shunt_delegate, which answers one question from an already-preserved text artifact, and context_shunt_recover, which returns one bounded line or byte range from a preserved artifact. Three ContextShunt keys control the reader: readerEnabled (built-in false), readerRole (an existing ordinary role, small by default, no separate reader model), and answerMaxBytes (8192 by default, 1024 to 16384). It also requires an effective mode of enforce, an active delegation intensity, and a valid configuration; in any other state a call produces a bounded error and no answer.

The reader's task contains only the preserved snapshot, its opaque source ID, its line count, and a question of at most 2048 UTF-8 bytes: no conversation, no other artifact, and no other tool call. An answer, its citations, and its envelope stay within answerMaxBytes; a validated answer over that cap is preserved and returned as a receipt for context_shunt_recover instead of being truncated. Citations name exact line ranges of that snapshot, at most 16 of them, and a result with no established answer reports insufficient-evidence instead. The reader needs a compatible external executor: protocol version 0.69.0 is the verified one, and another build fails closed with reader-unavailable, with no answer and no fallback. The limits and privacy reference states what one request sends and what the executor and its provider may retain.

Install and start

pi install npm:pi-delegation-policy
# restart Pi, or run /reload
  1. Open /delegate (or press Alt+G in Pi's TUI).
  2. For Small, Medium, and Large, select an exact authenticated provider/model or Disable for this session. Keep at least one enabled. The thinking rows are optional: leave one unset to choose a level per launch, or fix one level or an inclusive range. Visual Design and Advisor are optional model rows and do not count toward that minimum.
  3. Select normal, aggressive, or orchestrator, then choose Apply changes.
  4. Run /delegate status. disabled, not configured, and exact references remain distinct, and each role reports its thinking policy and source. D:ERR means no policy is injected.
  5. The applied state affects the next agent run.

Global defaults are stored at ~/.pi/agent/delegation-policy.json and new values use schema version 7. A thinking object holds at most one policy per role; omitting it keeps the per-launch thinking choice. The legacy positive contextShunt.limits.readerOutputBytes field remains accepted when reading schema 4, but is ignored and omitted from new saves. Schemas 2 through 6 defaults and session entries are read and normalized in memory without rewriting them; they carry no advisor key, and only schemas 6 and later carry a thinking policy. Schema 3 stores null for an explicitly disabled ordinary role. Session changes write a schema 2 off guard before the schema 7 state; saving defaults changes only the global file.

The extension stores delegation policy only: intensity, preference, model references, the optional ContextShunt configuration, and the thinking policy you configure. It never stores the thinking level chosen for an individual run.

A package that cannot read schema 7 treats the document as invalid: global defaults fall back to empty defaults with off and no injection, and a branch falls back to off with a sanitized notice. Before downgrading to a package that does not read schema 4, set global and branch ContextShunt to off; the guarded branch write already presents schema 2 off to older versions. Before downgrading to 0.6.0, also change the global intensity to off, normal, or aggressive and run /delegate off in every active branch. For <=0.5.0, convert global defaults to schema 2 and replace ordinary null values with exact model references. Schema 2 never accepts orchestrator. See the configuration reference for details.

See the getting-started guide and configuration reference.

Essential commands

/delegate                         Open the editor
/delegate off                     Disable policy for this session branch
/delegate normal                  Enable balanced delegation guidance
/delegate aggressive              Enable delegation-first guidance
/delegate orchestrator             Minimize main-agent execution and narration
/delegate status                  Show effective session state
/delegate reset                   Reset this branch to off and other fields to global defaults
/delegate context off             Stop ContextShunt work for this branch
/delegate context observe         Record would-block decisions without changing calls or results
/delegate context enforce         Enforce recognized budgets and bounded recovery
/delegate context status          Show effective ContextShunt state

The editor is a bounded, keyboard-first panel. Every model selector pins Use global default and Disable for this session before searchable models. It shows model ID first and [provider] last, fuzzy-searches provider, model ID, and display name, and shows at most 10 model rows. Four thinking rows offer global inheritance, no policy for the session, a fixed level, or an inclusive range, and list only the levels the role's model supports. It also shows a compact effective-policy preview, one row per setting with a hint block for the focused row's explanation and sources, and public model metadata when Pi supplies it. Changes are drafts until Apply changes; saving effective configuration as defaults updates only the global file without applying the draft, and closing a modified draft requires explicit discard.

Context advanced in /delegate edits reader enablement, the requested reader role, its answer byte cap, limits, and comma-separated patterns, with per-field global inheritance and a ContextShunt draft reset. In enforce, an oversized recognized read receives a bounded-read or user-confirmed one-time exception path. Preguards use declared lines, while postguards use real UTF-8 bytes and returned line counts; rejected reads do not consume the shared declared-request window. Large known text results are compacted only after their original is stored in a private, session-only artifact with a quota and an absolute 30-minute TTL from creation; scheduled cleanup runs while the process is active, recovery does not renew it, and shutdown removes the temporary directory. Crashes or OS suspension can delay deletion. context_shunt_recover accepts either a bounded line range or byte range. Errors, valid JSON of every root type, images, mixed content, and unknown tool contracts remain unchanged. The package declares agents/pi-delegation-policy.bulk-reader.md for discovery by a compatible executor. It allows only read, grep, find, and ls; it remains a guided profile, not an automatic bridge or a claim of executor isolation. It is not copied into user agent directories or launched automatically. If an executor cannot discover a path-based profile, use the guided redirection only.

Development

npm ci
npm run format:check
npm run lint
npm run typecheck
npm test
npm run build
npm run pack:check

Tests use local mocks and do not make paid model calls or network requests. See CONTRIBUTING.md.

License

MIT. See LICENSE.