Skip to content

feat(pi): Agent tool for sub-agents on the pi runtime - #6756

Open
waynesun09 wants to merge 7 commits into
pi-extensions-keyfrom
pi-agent-tool
Open

feat(pi): Agent tool for sub-agents on the pi runtime#6756
waynesun09 wants to merge 7 commits into
pi-extensions-keyfrom
pi-agent-tool

Conversation

@waynesun09

@waynesun09 waynesun09 commented Aug 29, 2026

Copy link
Copy Markdown
Member

Summary

Stacked on #6754 (base branch pi-extensions-key) → #6752. Retarget as the stack merges.

Gives the pi runtime Claude Code's Agent tool (alias Task) so review and retro run their real sub-agent rosters on pi instead of the single-context fallback. The contract is Claude Code's, so skills/pr-review and skills/retro-analysis dispatch unchanged: prompt, description, model (Claude alias/id or provider/id, translated through the manifest alias table; an unknown or Claude-shaped id is rejected with a clear tool error rather than passed through), subagent_type (Exploreread,grep,find,ls; otherwise the parent's built-in set minus Agent/Task); run_in_background accepted and ignored — pi runs sibling tool calls concurrently, which is the parallel dispatch the skills ask for.

Design was verified empirically first (2026-08-29, with a community stand-in): the full pr-review roster ran as parallel children carrying the hook adapter and both provider extensions, mixed providers per child (Grok 4.6 / Sonnet 5 / Haiku), and a Grok orchestrator finished a review in ~16 min. This PR replaces the stand-in with a fullsend-owned extension and closes the gaps that run exposed (model spec bound by the runtime, per-child thinking default medium, child transcripts and cost accounted).

Mechanics.

  • internal/runtime/pi_extension/fullsend-agent.js (ESM, go:embed, SHA-256-checked in the run command like the hook adapter — shared exit 97): registers Agent/Task; children spawn as pi --print --mode json --no-approve --no-extensions --no-prompt-templates --no-themes --session-dir <sessions>/agent-<seq> -e <every provider extension present in the image> -e fullsend-hooks.js --tools <set> --model <spec> --thinking <level> --append-system-prompt <child note> with the prompt delivered over stdin (pi's option parser treats a positional starting with -/-- as a flag and @… as a file even after --, and argv caps at 128 KiB — reproduced with pi 0.84.4) and FULLSEND_SUBAGENT_DEPTH=1; the extension refuses to register when that variable is already set and children never receive -e fullsend-agent.js (no recursion by construction); concurrency semaphore (4) with shutdown-drained waiters, per-child timeout/abort/session_shutdownSIGTERM (pi reaps its detached bash grandchildren) then SIGKILL after 3 s; per-child provider env hygiene (the same ANTHROPIC_*/XAI_* scrubs and project pins buildPiRunCommand applies, chosen by the child's resolved provider); children get a child-only --append-system-prompt instead of the orchestrator's APPEND_SYSTEM.md; result = the child's final text (64 KB cap), isError on stopReason error/aborted, non-zero exit, timeout or missing agent_end; one usage line per child appended to /sandbox/pi-config/subagents/usage.jsonl; stderr [fullsend-agent] #<seq> <model> start/done lines.
  • Bootstrap writes the manifest agent block (enabled when the agent lists Agent/Task or has no tools:; provider extensions probed with test -d; alias table via translatePiModel incl. claude-sonnet-4-6@default-style ids; thinking = FULLSEND_PI_SUBAGENT_THINKING or medium) and swaps the "no sub-agent tool" runtime note for an "Agent is available; parallel dispatch = several Agent calls in one message" note.
  • Run: -e fullsend-agent.js after the hook adapter (PreToolUse hooks see Agent calls, as on Claude Code); Agent,Task added to --tools when the agent declares them.
  • Transcripts/metrics: child session files are extracted as <agent>-sub<seq>-<basename>.jsonl plus <agent>-subagents-usage.jsonl; child tokens/cost are folded into RunMetrics totals and a new per_model_usage breakdown (parent iteration included, so the map sums to the totals); ClearIterationArtifacts removes child sessions and the usage file so retries don't double-count.
  • Docs: docs/runtimes/pi.md "Sub-agents" (replaces "not supported"), docs/runtimes.md matrix row, docs/contributing/runtime-implementation.md "Agent tool contract" + manifest fields.

Closes the "pi Agent tool (Track E)" item of #6527; refs #6464.

Review round 1 → fixes (head 67e8ed5c)

Claude + Grok found one HIGH (prompt as positional argv) and the MEDIUMs now fixed: stdin prompt delivery (verified against real pi 0.84.4: - a leading dash exits 1 as argv, arrives as the user message over stdin); detached dropped and SIGTERMSIGKILL sequence (test reaps a detached grandchild); abort signal wired, shuttingDown re-checked after the semaphore, waiters drained on shutdown; empty child tool list → --no-builtin-tools; per-provider child env; :thinking suffix stripped from model specs; the parent's live provider allowed for inherited specs; the manifest agent block is now SHA-256-verified in the run command (pre-.env and post-.env, exit 95) so the extension no longer trusts an agent-writable file; fullsend-agent reserved as an extension name; child-only system prompt (--append-system-prompt replaces APPEND_SYSTEM.md discovery); 1 MiB stdout-line cap, head -c 1MiB usage read, 512-byte description cap (record stays under PIPE_BUF); per_model_usage folds the parent entry on every iteration and the usage file is renamed after reading (idempotent across retries; malformed lines counted and warned); Explore tools intersected with the parent's set; docs reconciled (choosing-a-runtime.md, runtimes/claude.md, runtime-implementation.md flowchart + guards, docs/cli/run.md per_model_usage, "what a child does not inherit").

Review round 2 → fixes (head a007629b, rebased onto #6754's current head)

Claude + Grok round 2: the semaphore over-admitted one child when a queued dispatch was aborted while other waiters remained (a queued ticket claimed a slot in unqueue; its release() then handed that slot on without decrementing) — tickets now grant()/evict() explicitly and only an acquired ticket releases, with a maxConcurrent=2 regression test that failed on the old code; the manifest's integrity is now enforced for the whole iteration, not just at launch: the run command exports FULLSEND_PI_MANIFEST_SHA256 after .env, fullsend-hooks.js refuses to load a manifest that does not match it (so a child whose adapter starts later dies and the tool reports isError), and the Agent extension re-hashes the manifest immediately before each dispatch; resolveModel accepts only a closed set (manifest alias values, the parent's own spec, and a Bootstrap-written providerModels list taken verbatim from pi 0.84.4's google-vertex catalog — 13 ids; gemini-3.7-pro does not exist there); the usage-file download goes through the same OpenRoot containment as transcripts (a ../ agent label escaped outputDir before); usage figures are clamped at zero and half-records (missing seq or usage) are counted as skipped; the Agent-extension guard has its own exit code 94 (97 = hook adapter, 95 = manifest, 96 = declared extensions, 98 = provider config); comments/docs corrected (pi does honour --, but @ positionals stay file arguments and argv is capped — stdin stays; description capped in the log line; per_model_usage field list; parent entry on every Agent-enabled iteration; dash note on unset -f test [ …; all roles supported on pi; -e fullsend-agent.js in the command template; providerModels manifest row).

Review round 3 (verification) → fixes (head 7331170c)

Both reviewers confirmed every round-2 fix. Two residuals closed: the per-dispatch drift check now also re-hashes the hook adapter file children load (agent.extensionDigests, written by Bootstrap as sha256(fullsend-hooks.js) — the same digest the launch guard checks — so a parent that rewrites the adapter mid-iteration gets hook adapter changed since load; refusing to dispatch); and the xai/xai-vertex branch of resolveModel only normalises the spelling now and then goes through the same closed set as every other provider (providerModels["xai-vertex"] = ["xai/grok-4.6"], the single id pi-xai-vertex v0.2.0 registers). Also: +Inf cost clamped, the -- sentence in runtime-implementation.md corrected, -e fullsend-agent.js in the literal command template, the new model lists added to the PI_VERSION-bump re-check table, and a note that Bootstrap and Run must share a process for the manifest digest guard. Node: 58/58 with a real pi 0.84.4 (57 + 1 skipped without).

Test plan

  • go build ./...; go test ./... — all packages pass except the known environmental failures (TestDummyRuntime_* with a local gateway, TestResolveAgentSource_OverrideOnlyEntryUsesAgentsRepoFallback and TestListTriggeredHarnesses_BaseComposition on macOS /var symlinks); new: piToolsFor mapping, piAgentManifestFor (enabled/disabled, aliases, extensions present/absent), buildPiRunCommand goldens (-e order, --tools, guard adjacency), ExtractTranscripts child sessions, foldPiSubagentUsage/parsePiSubagentUsage, metrics aggregation across iterations
  • node --test on both extension test files — 55 (54 pass, 1 skipped without FULLSEND_TEST_PI_BIN; 55/55 with it pointing at a pi 0.84.4 install, incl. the 200 KiB stdin prompt and the positional negative control) (fake pi stub: success text, error stopReason → isError, timeout → group kill, concurrency cap, Explore tool set, model translation/rejection, depth refusal, missing manifest → registers nothing)
  • pre-commit run --from-ref pi-extensions-key --to-ref HEAD — all hooks pass
  • Local fullsend run review --runtime pi on the stacked branch against a real PR (Grok 4.6 orchestrator via xai-vertex, pr-review skill roster): 7 Agent dispatches (3 Opus, 4 Sonnet; up to 4 concurrent), every child stop, agent exit 0 in one iteration; transcripts/review-sub1..7-*.jsonl + review-subagents-usage.jsonl extracted; metrics.json per_model_usage = xai-vertex/xai/grok-4.6 $2.34 / anthropic-vertex/claude-opus-4-6 $0.95 (3 req) / anthropic-vertex/claude-sonnet-4-6 $0.85 (4 req), summing to total_cost_usd $4.15

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

feat(pi): add Agent/Task sub-agent support

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds Claude-compatible Agent/Task tooling to pi for parallel sub-agent rosters.
• Preserves hooks, provider selection, tool restrictions, timeouts, and recursion safeguards.
• Accounts child usage and exports per-child transcripts, metrics, tests, and documentation.
Diagram

sequenceDiagram
    participant Runner as Runtime Runner
    participant Manifest as Agent Manifest
    participant Parent as Parent pi
    participant AgentExt as Agent Extension
    participant Child as Child pi
    participant Providers as Provider Extensions
    participant Hooks as Hook Adapter
    participant Artifacts as Run Artifacts
    Runner->>Manifest: Write agent config
    Runner->>Parent: Load guarded extension
    Parent->>AgentExt: Agent or Task call
    AgentExt->>Manifest: Resolve model and tools
    AgentExt->>Child: Spawn bounded process
    Child->>Providers: Invoke selected model
    Child->>Hooks: Run tool hooks
    Child-->>AgentExt: Final text and usage
    Child->>Artifacts: Write child session
    AgentExt->>Artifacts: Append usage record
    AgentExt-->>Parent: Return tool result
    Runner->>Artifacts: Fold metrics and extract
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use pi SDK child sessions
  • ➕ Avoids spawning a separate CLI process per sub-agent
  • ➕ Could share more runtime state in-process
  • ➖ Parent extensions do not automatically apply to SDK-created children
  • ➖ Requires recreating hook, provider, tool, session, and lifecycle behavior manually
  • ➖ Increases coupling to pi SDK internals
2. Adopt pi bundled subagent extension
  • ➕ Uses an existing upstream example
  • ➕ Reduces runner-owned JavaScript
  • ➖ Does not preserve the required hook adapter and provider extension set
  • ➖ Lacks the same approval, session-directory, accounting, and integrity posture
  • ➖ Does not satisfy the Claude-compatible fleet contract without substantial changes

Recommendation: Keep the runner-owned child-process extension. It preserves the parent runtime posture through explicit flags and extensions, isolates sessions, prevents recursive dispatch by construction, and provides the accounting and shutdown guarantees required by existing review and retro skills. The SDK and bundled-extension alternatives reduce custom process code but do not provide equivalent hooks, providers, artifacts, or security behavior.

Files changed (18) +1874 / -34

Enhancement (8) +969 / -14
run.goAggregate per-model usage across iterations +15/-0

Aggregate per-model usage across iterations

• Extends aggregate metrics with an optional model-level usage breakdown and accumulates those entries across retry iterations.

internal/cli/run.go

pi_agent.goMap Agent and Task into pi tool allowlists +35/-0

Map Agent and Task into pi tool allowlists

• Defines Agent/Task names, the read-only Explore tool set, and enablement rules. Treats either Claude tool name as activating both registered pi aliases.

internal/runtime/pi_agent.go

pi_bootstrap.goBootstrap the embedded Agent extension +210/-8

Bootstrap the embedded Agent extension

• Embeds and uploads the extension, writes its manifest block, probes available providers, resolves model aliases, configures child limits and thinking, and selects the appropriate runtime note.

internal/runtime/pi_bootstrap.go

fullsend-agent.jsImplement the pi Agent and Task extension +455/-0

Implement the pi Agent and Task extension

• Registers Claude-compatible Agent/Task tools and launches isolated child pi processes with validated models, bounded concurrency, tool restrictions, hooks, timeouts, process-group cleanup, output caps, and usage recording.

internal/runtime/pi_extension/fullsend-agent.js

pi_run.goLoad, guard, and account for Agent execution +49/-4

Load, guard, and account for Agent execution

• Adds SHA-256 guarding and ordered loading for the Agent extension. Reads child usage after each run, folds it into metrics, and clears usage between retry iterations.

internal/runtime/pi_run.go

pi_subagents.goFold child usage into run metrics +132/-0

Fold child usage into run metrics

• Parses the extension's usage JSONL, tolerates malformed records, adds child tokens and cost to totals, and builds a reconciling per-model breakdown including the parent.

internal/runtime/pi_subagents.go

pi_transcript.goExtract child sessions and usage artifacts +45/-2

Extract child sessions and usage artifacts

• Recognizes child session directories, generates collision-resistant transcript names with Agent sequence numbers, and downloads the usage JSONL alongside transcripts.

internal/runtime/pi_transcript.go

runtime.goAdd reusable per-model usage metrics +28/-0

Add reusable per-model usage metrics

• Introduces ModelUsage and an additive helper, then exposes an optional per-model breakdown on runtime metrics.

internal/runtime/runtime.go

Tests (7) +797 / -5
telemetry_run_test.goTest per-model aggregate metric accumulation +17/-0

Test per-model aggregate metric accumulation

• Verifies model usage sums across iterations and remains omitted when no runtime supplies a sub-agent breakdown.

internal/cli/telemetry_run_test.go

pi_agent_test.goTest Agent tool mapping and enablement +27/-2

Test Agent tool mapping and enablement

• Covers alias deduplication, frontmatter enablement rules, and the safety of the Explore tool subset.

internal/runtime/pi_agent_test.go

pi_bootstrap_test.goTest Agent bootstrap, metrics, and artifacts +254/-2

Test Agent bootstrap, metrics, and artifacts

• Adds integration-style coverage for manifest generation, provider probing, thinking overrides, usage folding, child transcript extraction, and iteration cleanup.

internal/runtime/pi_bootstrap_test.go

fullsend-agent.test.mjsTest sub-agent extension behavior +382/-0

Test sub-agent extension behavior

• Covers the tool schema, model resolution, child arguments, concurrency, successful and failed streams, timeouts, shutdown, result truncation, usage records, and recursion prevention.

internal/runtime/pi_extension/fullsend-agent.test.mjs

pi_extensions_test.goDisambiguate top-level extension manifest assertion +3/-1

Disambiguate top-level extension manifest assertion

• Parses the manifest before asserting the harness extension key is omitted, avoiding confusion with the Agent block's child extension list.

internal/runtime/pi_extensions_test.go

pi_run_test.goTest Agent run-command wiring and integrity +55/-0

Test Agent run-command wiring and integrity

• Verifies guard ordering before the writable environment, extension load order, Agent/Task allowlists, enabled and disabled behavior, and embedded hash pinning.

internal/runtime/pi_run_test.go

pi_subagents_test.goTest sub-agent usage parsing and folding +59/-0

Test sub-agent usage parsing and folding

• Covers successful, failed, malformed, missing-model, and no-child records while asserting totals and model breakdowns remain consistent.

internal/runtime/pi_subagents_test.go

Documentation (3) +108 / -15
runtime-implementation.mdDocument the pi Agent extension contract +36/-2

Document the pi Agent extension contract

• Adds the Agent extension, child session, and usage artifacts to the sandbox layout. Documents manifest fields, enablement, integrity checks, hook behavior, recursion prevention, and process-group shutdown semantics.

docs/contributing/runtime-implementation.md

runtimes.mdMark pi sub-agents and all roles supported +4/-4

Mark pi sub-agents and all roles supported

• Updates the runtime comparison to show Agent/Task support on pi and removes the recommendation to use Claude solely for sub-agents. Clarifies that review and retro now execute their real rosters.

docs/runtimes.md

pi.mdAdd pi sub-agent usage and operations guide +68/-9

Add pi sub-agent usage and operations guide

• Documents the Agent tool contract, parallel dispatch, child inheritance, thinking-level override, artifacts, metrics, enablement, and remaining fleet validation caveat.

docs/runtimes/pi.md

@fullsend-ai-review

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Ended 6:09 PM UTC

Commit: 81e5855 · View workflow run →

@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown

Site preview

Preview: https://1aeb9eb3-site.fullsend-ai.workers.dev

Commit: ca12f63c0674c9448ca305fbe2924cb5c3feca1b

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:11 PM UTC · Completed 6:29 PM UTC

Commit: 4e91c29 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $12.82

@qodo-code-review

qodo-code-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Queued agents outlive shutdown ✓ Resolved 🐞 Bug ☼ Reliability
Description
A call waiting on the concurrency semaphore checks shuttingDown only before await acquire(),
then spawns unconditionally once a running child releases the slot. During session_shutdown, such
queued calls can therefore launch after the one-time kill pass and continue running outside the
parent session.
Code

internal/runtime/pi_extension/fullsend-agent.js[356]

+    await acquire();
Relevance

●●● Strong

Recent accepted cancellation precedents favor preventing work from continuing after shutdown; this
is a deterministic reliability fix.

PR-#1982
PR-#2182

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Queued calls are stored by acquire, and release resolves the next waiter. The run path checks
shutdown before waiting but proceeds directly to runChild after acquisition, while shutdown only
iterates the current running set; therefore a queued call awakened after a killed child closes is
not covered by the shutdown kill pass.

internal/runtime/pi_extension/fullsend-agent.js[267-280]
internal/runtime/pi_extension/fullsend-agent.js[352-360]
internal/runtime/pi_extension/fullsend-agent.js[403-406]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Agent calls queued behind the concurrency semaphore can resume and spawn after `session_shutdown`, because shutdown kills only currently running children and queued calls do not re-check the shutdown state after acquisition.

## Issue Context
The semaphore wakes a waiter when an active child releases its slot. Shutdown must prevent every queued waiter from spawning and ensure those calls resolve as aborted without leaking semaphore capacity.

## Fix Focus Areas
- internal/runtime/pi_extension/fullsend-agent.js[267-281]
- internal/runtime/pi_extension/fullsend-agent.js[352-363]
- internal/runtime/pi_extension/fullsend-agent.js[403-406]
- internal/runtime/pi_extension/fullsend-agent.test.mjs[295-307]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 62 rules
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/runtime/pi_extension/fullsend-agent.js Outdated
@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Aug 29, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

Risk Assessment: moderate (2/5)

Details

Moderate risk. The PR is large (3876 lines, 24 files) giving a high change-size score, but strong mitigating factors keep overall risk moderate: no protected paths, no security-sensitive files, no CI or dependency changes, solid test ratio (0.38), and the author is experienced. Most additions are new files rather than modifications to shared hot paths. Elevated Tier 2 churn and coupling scores are driven by hub files (run.go, runtime.go) where this PR's changes are minor. Clear issue lineage (#6527, #6464) confirms well-scoped planned feature work. Re-review anchoring: Tier 1 signals unchanged from prior assessment; score of 2 confirmed.

Previous run

Risk Assessment: moderate (2/5)

Details

Moderate risk. The PR is large (3873 lines, 24 files) giving a high change-size score, but strong mitigating factors keep overall risk moderate: no protected paths, no security-sensitive files, no CI or dependency changes, solid test ratio (0.38), and the author is highly familiar with the internal/runtime/pi subsystem. Most additions are new files rather than modifications to shared hot paths, reducing merge conflict and regression risk. Clear issue lineage (#6527, #6464) confirms well-scoped planned feature work. Re-review anchoring: signals consistent with prior score of 2.

Previous run (2)

Risk Assessment: moderate (2/5)

Details

Moderate risk. While the PR is large (1908 lines, 18 files), the high change-size score is offset by strong mitigating factors: no protected paths, no security-sensitive files, no CI/dependency changes, decent test ratio (0.39), known non-bot non-first-time author, and well-scoped feature work with clear issue lineage (#6527, #6464). The high-churn files (run.go, runtimes.md) are touched only lightly. Six files are entirely new.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

Review

Findings

Low

  • [error-handling-gap] internal/runtime/pi_run.go:742 — When the sub-agent usage file read fails (uerr != nil), foldPiSubagentUsage is never called because it sits inside the else branch. The parent's own entry is not recorded in PerModelUsage. In a retry run where one iteration dispatched children and another's read fails, per_model_usage stops summing to the totals — breaking the documented invariant. Practical impact is low because piSubagentUsageReadCommand ends with 2>/dev/null || true, so uerr would only be non-nil from a transport-level sandbox.Exec failure.
    Remediation: Move the foldPiSubagentUsage call (with empty data) outside the else branch so the parent entry is always added when the Agent tool is enabled.

  • [fail-open] internal/runtime/pi_bootstrap.go:337 — When Bootstrap and Run execute in separate processes, piManifestHash returns an empty string, causing Run to silently omit both the manifest integrity shell guard and the FULLSEND_PI_MANIFEST_SHA256 export. Nothing logs or warns when the guard is not emitted, making this silent fail-open invisible to operators.
    Remediation: Add a log line in Run when piManifestHash returns empty and the agent tool is enabled, so operators who inadvertently separate Bootstrap and Run get a warning that the manifest integrity chain is not active.

  • [naming-consistency] internal/runtime/pi_bootstrap.go:26piAgentUsageFile is named with a File suffix but its value is a relative path with a directory component (subagents/usage.jsonl). The codebase convention uses File for bare filenames (piHooksExtensionFile, piManifestFile, piAgentExtensionFile) and Path for values with directory segments. The existing method piAgentUsagePath() creates a File-constant / Path-method pair that inverts the usual naming.
    Remediation: Rename piAgentUsageFile to piAgentUsageRelPath and rename the method piAgentUsagePath() to piAgentUsageAbsPath(), or accept the minor inconsistency.

  • [stale-reference] docs/architecture.md:842 — The pi runtime mermaid diagram is now incomplete after this PR: the pi-config directory listing is missing fullsend-agent.js and subagents/; the shell guard node is missing the Agent extension SHA-256 check and the manifest SHA-256 check; the command line node is missing [-e fullsend-agent.js]; and the failure node lists only exit 97 but the PR adds exit 94 and 95. The detailed diagram in docs/contributing/runtime-implementation.md IS updated.
    Remediation: Update the mermaid diagram in docs/architecture.md to include fullsend-agent.js, subagents/, exit 94/95, the Agent extension guard checks, and the [-e fullsend-agent.js] flag.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run

Review

Findings

Low

  • [error-handling-gap] internal/runtime/pi_run.go:742 — When the sub-agent usage file read fails (uerr != nil), foldPiSubagentUsage is never called because it sits inside the else branch. The parent's own entry is not recorded in PerModelUsage. In a retry run where one iteration dispatched children and another's read fails, per_model_usage stops summing to the totals — breaking the documented invariant.
    Remediation: Move the foldPiSubagentUsage call (with empty data) outside the else branch so the parent entry is always added when the Agent tool is enabled.

  • [stale-reference] docs/contributing/runtime-implementation.md:106 — The security feature matrix row for pi's "Sandbox tool hooks wiring" mentions only exit 97 and exit -1. The PR adds exit 94 (Agent extension) and exit 95 (manifest), but this summary table was not updated.
    Remediation: Extend the pi column to mention exit 94 and exit 95.

  • [stale-reference] docs/contributing/runtime-implementation.md:429 — States "Bootstrap and Run are separate calls with no shared process state." The PR introduces piManifestHashes (a package-level sync.Map) to carry the manifest SHA-256 digest from Bootstrap to Run in-process, and adds an Agent tool contract section that explicitly says "Bootstrap and Run must run in one process." The two statements contradict each other.
    Remediation: Update line 429 to reflect that Bootstrap and Run now share process state via piManifestHashes.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (2)

Review

Findings

Low

  • [error-handling-gap] internal/runtime/pi_run.go:742 — When the sub-agent usage file read fails (uerr != nil), foldPiSubagentUsage is never called because it sits inside the else branch. The parent's own entry is not recorded in PerModelUsage. In a retry run where one iteration dispatched children and another's read fails, per_model_usage stops summing to the totals — breaking the documented invariant.
    Remediation: Call foldPiSubagentUsage with empty data outside the else branch, so the parent entry is always added when the Agent tool is enabled.

  • [credential-exposure] internal/runtime/pi_extension/fullsend-agent.jschildEnv applies per-provider credential scrubbing for anthropic-vertex and xai-vertex but has no case for the openai provider. The code comment (lines 294–309) explains this is deliberate: the parent's shell already unsets OPENAI_BASE_URL/AZURE_OPENAI_API_KEY/OPENAI_API_KEY, and pi resolves its key from auth.json. As defense-in-depth, adding an openai case would mirror the parent's post-.env unsets in buildPiRunCommand, closing a narrow re-export path.
    Remediation: Add an openai case to childEnv that deletes OPENAI_BASE_URL, AZURE_OPENAI_API_KEY, and OPENAI_API_KEY.

  • [stale-reference] docs/architecture.md:842 — The pi runtime architecture diagram does not mention fullsend-agent.js, subagents/usage.jsonl, sessions/agent-<seq>/ directories, or exit codes 94/95. The detailed flowchart in docs/contributing/runtime-implementation.md IS updated by this PR, but this higher-level diagram is not.
    Remediation: Add fullsend-agent.js to the config-dir listing, [-e fullsend-agent.js] to the command-line node, and exit 94/95 alongside exit 97.

  • [stale-reference] docs/contributing/runtime-implementation.md:106 — The security feature matrix row for pi's "Sandbox tool hooks wiring" mentions only exit 97 and exit -1. The PR adds exit 94 (Agent extension) and exit 95 (manifest), but this summary table was not updated.
    Remediation: Extend the pi column to mention exit 94 and exit 95.

  • [stale-reference] docs/contributing/runtime-implementation.md — States "Bootstrap and Run are separate calls with no shared process state." The PR introduces piManifestHashes (a sync.Map) to share the manifest SHA-256 digest from Bootstrap to Run in-process.
    Remediation: Amend the sentence to note the manifest digest is now shared in-process via piManifestHashes.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (3)

Review

Findings

Medium

  • [credential-exposure] internal/runtime/pi_extension/fullsend-agent.jschildEnv applies per-provider credential scrubbing for anthropic-vertex and xai-vertex but has no case for the openai provider. The documentation states "The child's environment is rebuilt per resolved provider with the same rules buildPiRunCommand applies to the parent," but this contract is not fulfilled for openai. A non-openai parent dispatching an openai child would not scrub OPENAI_BASE_URL, AZURE_OPENAI_API_KEY, OPENAI_API_KEY, NODE_OPTIONS, or NODE_PATH.
    Remediation: Add an openai case to childEnv that deletes these variables, mirroring the parent's post-.env unsets in buildPiRunCommand.

Low

  • [error-handling-gap] internal/runtime/pi_run.go:662 — When the sub-agent usage file read fails (uerr != nil), the foldPiSubagentUsage call is inside the else branch. On a read failure, the parent's own entry is never recorded in PerModelUsage, so metrics.json may have an incomplete or absent per_model_usage that does not sum to the totals. While this is an exceptional condition (sandbox communication failure), the parent entry should be recorded unconditionally.
    Remediation: Call foldPiSubagentUsage with empty data outside the else branch, so the parent entry is always added when the Agent tool is enabled.

Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (4)

Review

Findings

High

  • [stale capability claim] docs/guides/getting-started/choosing-a-runtime.md:7 — The introductory callout says pi "has no sub-agent tool yet (review/retro run in a single context)". This PR adds the Agent tool to the pi runtime, so review/retro now run their real sub-agent roster. The same stale claim appears on line 18 in the Available runtimes table. This is a user-facing getting-started page that will actively mislead new users after this PR merges.
    Remediation: Update the callout on line 7 and the pi table row on line 18 to reflect that pi now supports sub-agents via the Agent tool. Point to the new Sub-agents section in docs/runtimes/pi.md.

  • [stale capability claim] docs/runtimes/claude.md:44 — Lines 44–45 say "Native sub-agents via the Agent tool, which is why review and retro are Claude-only today." This is no longer true — the PR adds the Agent tool to the pi runtime. Line 31 also says "All, including review and retro — they need sub-agents" in a way that implies only Claude Code has sub-agent support.
    Remediation: Remove the "Claude-only today" claim and update line 31 to remove the implication that sub-agents are unique to Claude Code.

Medium

  • [race condition] internal/runtime/pi_extension/fullsend-agent.js:349 — The shuttingDown check runs BEFORE await acquire(). If shutdown() is called while a call is queued in waiters, the queued call's waiter is resolved by a release() from an already-finishing child. The call bypasses the shuttingDown guard, acquires a slot, and spawns a new child AFTER shutdown() has already killed all in-flight children. Because children are spawned with detached: true (own process group), the newly spawned child is not in the parent's process group and persists until its timeout (default 15 minutes) or natural completion.
    Remediation: Move the shuttingDown check to after await acquire(), releasing the slot immediately if shutdown has been requested.

  • [stale diagram] docs/architecture.md:842 — The Mermaid sandbox diagram for the pi runtime does not include fullsend-agent.js in the config files node, does not mention the Agent extension's SHA-256 check in the guard node, and does not show the optional -e fullsend-agent.js in the command-line node.
    Remediation: Add fullsend-agent.js to the P1 config-files node, mention the Agent extension SHA-256 check in the P0 guard node, and add -e fullsend-agent.js (conditional) to the P2 command-line node.

Low

  • [cross-boundary wire format documentation] internal/runtime/pi_subagents.go:28 — The piSubagentUsageRecord.Usage struct uses camelCase JSON tags (cacheRead, cacheWrite) to decode the format written by fullsend-agent.js, while all Go-facing types in this package use snake_case tags. The existing type-level comment does not note this cross-boundary convention, which could lead a maintainer adding a field to default to snake_case and break deserialization.
    Remediation: Add a brief comment noting the camelCase tags match the fullsend-agent.js wire format.

  • [missing field documentation] docs/cli/run.md:73 — The metrics.json fields table does not document the new per_model_usage field added by this PR. The field is omitempty and only appears when sub-agents ran, but operators inspecting metrics.json after a pi review/retro run will encounter it without documentation.
    Remediation: Add a row for per_model_usage to the metrics.json fields table.

  • [incomplete cost contract] docs/guides/infrastructure/distributed-tracing.md:204 — The pi row in the Runtime cost extraction table describes only stream-based cost extraction; it does not mention the sub-agent usage file folding step added by this PR.
    Remediation: Append a note that sub-agent costs from the Agent extension's usage file are folded into the total after the stream is parsed.

  • [edge case] internal/runtime/pi_extension/fullsend-agent.js:237 — The capText function's trailing U+FFFD stripping regex could strip legitimate U+FFFD replacement characters from the original text, not just those introduced by mid-codepoint truncation. Very low practical impact.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:03 PM UTC · Completed 7:21 PM UTC

Commit: 67e8ed5 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $8.84

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Ended 8:03 PM UTC

Commit: 7fa2def · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:17 PM UTC · Completed 8:36 PM UTC

Commit: a007629 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $11.56

fullsend-ai-review[bot]

This comment was marked as outdated.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:53 PM UTC · Completed 9:14 PM UTC

Commit: 7331170 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $8.71

An agent definition that lists Agent or Task under tools: now activates
both pi tool names (the extension registers Agent with Task as its
legacy alias) instead of reporting them as unsupported. Adds the
enablement predicate (no tools: entry, or Agent/Task listed) and the
read-only Explore tool set shared with the extension via the manifest.

Refs: #6527, #6464

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
A pi extension that registers Claude Code's Agent tool (and its legacy
alias Task) with the same contract — prompt, description, model,
subagent_type, run_in_background accepted and ignored — so the fleet's
pr-review and retro-analysis skills dispatch unchanged on the pi runtime.

Each call runs one child pi --print --mode json to completion with the
parent's flag set (trust off, --no-extensions plus the manifest's
provider extensions and the hook adapter, strict --tools, its own
session dir) and FULLSEND_SUBAGENT_DEPTH=1; the extension refuses to
register when that variable is already set, so recursion is impossible.
Models are translated through the manifest alias table (opus|sonnet|
haiku, Claude ids with an @suffix, anthropic/ and xai/ direct-API forms)
and anything the run cannot serve — an invented Claude id, a provider
without credentials — is rejected with the accepted forms rather than
passed through. Explore gives the read-only tool set; a concurrency cap,
a timeout that kills the child's process group, and a usage.jsonl line
per child (for metrics.json) complete it. Failed children surface as
isError with the child's message.

Refs: #6527, #6464

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
Bootstrap now enables the Agent tool when the agent definition has no
tools: frontmatter or lists Agent/Task: it uploads fullsend-agent.js,
probes the sandbox for the pi binary and the vendored provider extension
directories that exist, and writes the `agent` manifest block the
extension reads — child extensions (providers present, then the hook
adapter when security is on), the model alias table (default = the
agent's model translated as for the parent; opus|sonnet|haiku on the
Anthropic Vertex provider), thinking (FULLSEND_PI_SUBAGENT_THINKING
when it names a pi level, else medium), the child and Explore tool
sets, the concurrency cap, timeout and usage file. The hook adapter's
tool-name table gains Agent/Task so the scripts see Claude vocabulary,
and APPEND_SYSTEM.md gets a note describing the tool and that parallel
dispatch is several Agent calls in one message; an agent whose tools:
leaves Agent out keeps the single-context note.

Refs: #6527, #6464

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
Partial: the run-command guard and -e wiring; transcripts, metrics
folding and docs follow in the next commits.

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
A child dispatched through the Agent tool is a separate pi process, so
none of its tokens reach the parent's --mode json stream and its session
file lands in its own `sessions/agent-<seq>/` directory. Without this the
run's artifacts and metrics.json show the orchestrator's cost only, and a
review whose spend is dominated by its roster looks nearly free.

ExtractTranscripts now names child sessions `<agent>-sub<seq>-<basename>`
(the sequence number keeps children with equal session basenames apart)
and downloads the extension's usage file beside them. Run reads that file
after the iteration and folds it into RunMetrics: the totals grow by what
the children spent, and per_model_usage attributes them, with the
parent's own iteration as one entry so the breakdown sums to the totals.
Runs that dispatch nothing keep metrics.json byte-identical.
ClearIterationArtifacts removes the usage file, which sits outside the
sessions dir the glob already clears, so a retry does not re-count the
previous iteration's children.

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
…acts

The pi runtime pages still said sub-agents were not wired and that
review/retro must stay on Claude Code, which is no longer true and would
send readers to the single-context workaround.

pi.md gains a Sub-agents section: the tool contract, what a child inherits
(hooks, providers, trust off, tool allowlist), the model alias table and
why an unservable model is rejected rather than passed through, the
medium thinking default with its env override and the review-budget
reason for it, and where child transcripts, the usage file and
per_model_usage land. runtimes.md's matrix row and the "stay on claude
for sub-agents" advice follow. runtime-implementation.md gets an Agent
tool contract section with the manifest fields, the depth guard, the
shared exit-97 integrity check and the process-group kill, plus the two
new paths in the sandbox layout tree.

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Aug 29, 2026
fullsend-ai-review[bot]

This comment was marked as outdated.

fullsend-ai-review[bot]

This comment was marked as outdated.

… contributing

Same split as the extensions section: the `Sub-agents` section on the pi
runtime page was written as security design notes — "Prompt delivery",
"Stopping a child", "`.env` is the same trust class here as everywhere
else", the manifest/adapter digest re-hash sequencing — so an agent author
who just wants to use `Agent` could not read it straight through.

- `docs/runtimes/pi.md` § Sub-agents is now a walkthrough: a parameter
  table, choosing a model (four accepted forms and the one rule that
  rejects the rest), running children in parallel, what a child does and
  does not inherit, thinking level, where the output lands, turning it off,
  and a symptom/cause/fix table. 118 lines down to 102.
- `docs/contributing/runtime-implementation.md` § Agent tool contract is
  renamed "Pi sub-agents: the Agent tool contract" so it sits beside the
  Pi extensions subsection, and gains the two facts the user page no longer
  carries: the usage file is consumed as it is read (`<usageFile>.read`,
  capped at 1 MiB) so a retry cannot double-count children, and the `.env`
  trust discussion around `FULLSEND_SUBAGENT_DEPTH`. Everything else the
  user page dropped — stdin prompt delivery and the argv hazards, the
  SIGTERM-then-SIGKILL stop sequence and process groups, the per-dispatch
  digest re-checks — was already documented there and is now linked rather
  than restated.

`docs/cli/run.md` § Per-model usage already read cleanly and is unchanged.

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:19 PM UTC · Completed 10:00 PM UTC

Commit: ca12f63 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $13.22

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

// reached the stream just parsed; the extension's usage file is the
// only record of what they spent. A read failure is not fatal —
// losing the breakdown must not fail an iteration that succeeded.
if usage, _, _, uerr := sandbox.Exec(params.SandboxName, piSubagentUsageReadCommand(m.Agent.UsageFile), 10*time.Second); uerr != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] error-handling-gap

When the sub-agent usage file read fails (uerr != nil), foldPiSubagentUsage is never called because it sits inside the else branch. The parent's own entry is not recorded in PerModelUsage. In a retry run where one iteration dispatched children and another's read fails, per_model_usage stops summing to the totals — breaking the documented invariant. Practical impact is low because piSubagentUsageReadCommand ends with 2>/dev/null || true, so uerr would only be non-nil from a transport-level sandbox.Exec failure.

Suggested fix: Move the foldPiSubagentUsage call (with empty data) outside the else branch so the parent entry is always added when the Agent tool is enabled.


// piManifestHash returns the digest recorded for a sandbox, or "" when
// Bootstrap did not run in this process.
func piManifestHash(sandboxName string) string {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] fail-open

When Bootstrap and Run execute in separate processes, piManifestHash returns an empty string, causing Run to silently omit both the manifest integrity shell guard and the FULLSEND_PI_MANIFEST_SHA256 export. Nothing logs or warns when the guard is not emitted, making this silent fail-open invisible to operators.

Suggested fix: Add a log line in Run when piManifestHash returns empty and the agent tool is enabled, so operators who inadvertently separate Bootstrap and Run get a warning that the manifest integrity chain is not active.

@@ -23,6 +26,14 @@ const (
// sandbox hook scripts; loaded explicitly with -e, never auto-discovered

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] naming-consistency

piAgentUsageFile is named with a File suffix but its value is a relative path with a directory component (subagents/usage.jsonl). The codebase convention uses File for bare filenames (piHooksExtensionFile, piManifestFile, piAgentExtensionFile) and Path for values with directory segments. The existing method piAgentUsagePath() creates a File-constant / Path-method pair that inverts the usual naming.

Suggested fix: Rename piAgentUsageFile to piAgentUsageRelPath and rename the method piAgentUsagePath() to piAgentUsageAbsPath(), or accept the minor inconsistency.

# Choose an agent runtime

> **Claude Code is the stable default.** The fleet agents have run on Claude Code in production for a long time; it is what a new installation gets unless you ask for something else. **pi is in its enablement (experimental) phase** — it works end to end for `triage`, `prioritize`, `code` and `fix`, has no sub-agent tool yet (`review`/`retro` run in a single context), and its fleet pilot is still in progress. Unless you are taking part in that pilot, keep the default.
> **Claude Code is the stable default.** The fleet agents have run on Claude Code in production for a long time; it is what a new installation gets unless you ask for something else. **pi is in its enablement (experimental) phase** — it works end to end for `triage`, `prioritize`, `code` and `fix`, and `review`/`retro` now dispatch their real sub-agent roster through a fullsend-supplied `Agent`/`Task` tool, but its fleet pilot is still in progress. Unless you are taking part in that pilot, keep the default.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the specific phrase:

Suggested change
> **Claude Code is the stable default.** The fleet agents have run on Claude Code in production for a long time; it is what a new installation gets unless you ask for something else. **pi is in its enablement (experimental) phase** — it works end to end for `triage`, `prioritize`, `code` and `fix`, and `review`/`retro` now dispatch their real sub-agent roster through a fullsend-supplied `Agent`/`Task` tool, but its fleet pilot is still in progress. Unless you are taking part in that pilot, keep the default.
> **Claude Code is the stable default.** The fleet agents have run on Claude Code in production for a long time; it is what a new installation gets unless you ask for something else. **pi is in its enablement (experimental) phase** — it works end to end for `triage`, `prioritize`, `code` and `fix`, and `review`/`retro`. Unless you are taking part in the `pi` pilot, keep the default.

|---------|--------|-------------|-------------|
| `claude` | **Stable (default)** | Claude Code on Vertex AI | Every production deployment — mature, full sub-agent support for `review`/`retro` |
| `pi` | Experimental (enablement phase) | [Pi](https://github.com/earendil-works/pi) — Claude on Vertex by default; any provider pi supports by model name (e.g. Gemini on Vertex with the same credentials) | Opt-in pilots only; no sub-agent tool yet, so `review`/`retro` run single-context; see [Runtimes](../../runtimes.md) for known constraints |
| `pi` | Experimental (enablement phase) | [Pi](https://github.com/earendil-works/pi) — Claude on Vertex by default; any provider pi supports by model name (e.g. Gemini on Vertex with the same credentials) | Opt-in pilots only; `Agent`/`Task` sub-agents come from a fullsend extension (children are `pi` processes) rather than from pi itself; see [Runtimes](../../runtimes.md) for known constraints |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too much detail somewhere it does not belong, probably you are already documenting this somewhere else. Remove this detail.

Comment thread docs/runtimes/claude.md
| | |
|---|---|
| Roles | All, including `review` and `retro` — they need sub-agents |
| Roles | All, including `review` and `retro` — they need sub-agents (pi covers these too, through a fullsend extension: [pi § Sub-agents](pi.md#sub-agents)) |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, too much detail where it does not belong.

Comment thread docs/runtimes/claude.md
Claude Code's exact framing can read differently there.
- **Native sub-agents** via the `Agent` tool, which is why `review` and `retro` are Claude-only
today.
- **Native sub-agents** via the `Agent` tool. This is no longer Claude-only: pi serves the same `Agent`/`Task` contract from a runner-owned extension that runs each child as its own `pi` process ([pi § Sub-agents](pi.md#sub-agents)). What stays Claude-specific is that the sub-agents are *native* — no child process, no separate session dir, no per-child provider hygiene.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, comenting pi details on the claude page.

Suggested change
- **Native sub-agents** via the `Agent` tool. This is no longer Claude-only: pi serves the same `Agent`/`Task` contract from a runner-owned extension that runs each child as its own `pi` process ([pi § Sub-agents](pi.md#sub-agents)). What stays Claude-specific is that the sub-agents are *native* — no child process, no separate session dir, no per-child provider hygiene.
- **Native sub-agents** via the `Agent` tool.

Comment thread docs/runtimes.md
|---|---|---|
| Models | Anthropic on Vertex | Claude, **Grok** and **Gemini** on Vertex; **GPT** via OpenAI WIF (opt-in, [not yet exercised live](runtimes/pi.md#models-and-providers)) |
| Sub-agents | Native (`Agent` tool) | Not wired — agents execute sub-agent definitions inline ([#6527](https://github.com/fullsend-ai/fullsend/issues/6527)) |
| Sub-agents | Native (`Agent` tool) | `Agent`/`Task` via a fullsend extension — children are `pi` processes with the same hooks, providers and tool allowlist ([pi runtime § Sub-agents](runtimes/pi.md#sub-agents)) |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Details where they are not needed.

Suggested change
| Sub-agents | Native (`Agent` tool) | `Agent`/`Task` via a fullsend extension — children are `pi` processes with the same hooks, providers and tool allowlist ([pi runtime § Sub-agents](runtimes/pi.md#sub-agents)) |
| Sub-agents | Native (`Agent` tool) | `Agent`/`Task` via a fullsend extension |

Comment thread docs/runtimes.md
| Sub-agents | Native (`Agent` tool) | `Agent`/`Task` via a fullsend extension — children are `pi` processes with the same hooks, providers and tool allowlist ([pi runtime § Sub-agents](runtimes/pi.md#sub-agents)) |
| Fallback model chain | `FULLSEND_FALLBACK_MODELS`, tried in order | Ignored with a warning |
| Roles | All | `review`/`retro` stay on Claude Code — they rely on sub-agent rosters |
| Roles | All | All; `review`/`retro` run their real sub-agent roster, at `--thinking medium` by default |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| Roles | All | All; `review`/`retro` run their real sub-agent roster, at `--thinking medium` by default |
| Roles | All | All; `review`/`retro` at `--thinking medium` by default |

@rh-hemartin rh-hemartin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the extension may live elsewhere and then install them on the image, but for now that looks good to me. Probably a followup to move the extensions would be good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk/moderate PR risk: moderate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants