Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server. The Pi provider adapter (packages/provider-pi/src/server/adapter.ts), observed in the desktop app.
Steps to reproduce
- Install the pi-subagents extension for Pi and start a Pi thread in T3 Code.
- Ask the agent to call the
subagenttool for one agent withasync: true, for example{ "agent": "reviewer", "task": "Review the diff", "async": true }. - Watch the Agents panel and the thread timeline while the child runs and after it finishes.
Expected behavior
The async child shows as a running subagent of the run that launched it, the way Claude background agents do and the way pi-subagents' synchronous mode already does. It settles as completed or failed when pi-subagents reports that the child finished.
Actual behavior
Nothing appears in the subagent UI. The subagent tool row turns completed as soon as the launch returns, while the child keeps running. In the thread where I hit this, a review child ran for about four minutes with no sign in T3 Code that anything was running or that it finished.
The adapter's subagent support (emitSubagentTasks in adapter.ts) reads only result.details.results[], the shape of Pi's synchronous example extension. pi-subagents' async mode reports differently:
- At launch, the
subagenttool returnsdetails = { mode: "single", asyncId, asyncDir, results: [] }, so the adapter emits no subagent. - When the child finishes, pi-subagents sends a custom message with
customType: "subagent-notify". Itsdetails.runslists each run's agent and status, and its text names each run's directory. The message arrives between turns, before the wake turn starts, andhandleSessionEventignores non-assistantmessage_endevents.
Impact
Minor bug or occasional failure
Version or commit
Observed on desktop 0.0.46-nightly.20261008.2833. The same code is on main at d81afa0a6.
Environment
macOS 27.0, Pi 1.1.0 (@earendil-works/pi-coding-agent), pi-subagents 0.76.1, Pi provider with openai-codex/gpt-6.1-sol as the parent model.
Logs or stack traces
# Inbound `pi --mode rpc` frames, in order, from a live run with only pi-subagents loaded.
# T3 Code's Pi replay recorder normalized ids and paths. "..." marks trimmed fields.
{"type":"tool_execution_end","toolName":"subagent","isError":false,"result":{"content":[{"type":"text","text":"Run fan-out: 1/64 used, 63 remaining\nAsync: echo [00000000-0000-4000-8000-000000000005]\n\nThe async run is deta ..."}],"details":{"mode":"single","runId":"00000000-0000-4000-8000-000000000005","results":[],"asyncId":"00000000-0000-4000-8000-000000000005","asyncDir":"/tmp/pi-rec-tmp/pi-subagents-uid-501/async-subagent-runs/00000000-0000-4000-8000-000000000005","...":"..."}}}
{"type":"agent_settled","aborted":false}
{"type":"message_end","message":{"role":"custom","customType":"subagent-notify","content":"Background task completed: **echo**\n\necho:\nECHO_DONE\n\nRetention-managed async directory: /tmp/pi-rec-tmp/pi-subagents-uid-501/async-subagent-runs/00000000-0000-4000-8000-000000000005\n\n...","display":false,"details":{"runs":[{"agent":"echo","status":"completed"}]}}}
{"type":"agent_start"}Workaround
Ask the agent for subagent({ action: "status" }), or read the run's result from pi-subagents' async directory. Once the wake turn runs (#15589, fixed by #17214), the parent model also sees the result, but T3 Code's subagent UI still shows nothing.
I have a fix with a recorded replay fixture and will link the PR here.
Activity
kushaldotdev commentedon Oct 9, 2026
Additional confirmation, and one scope note.
With #17214 merged (the first nightly after the merge is
0.0.46-nightly.20261008.2849), the wake no longer kills the Pi session, but the runs are still invisible: the adapter continues to require the synchronous shape (toolName === "subagent"plusdetails.results[]withagentandtask), while an async launch returnsso
emitSubagentTasksreturns without emitting anything (pi-subagents 0.76.1,src/runs/foreground/subagent-executor.js).Also worth tracking separately: workflow, chain and parallel launches are outside #17393's scope, so they will still show nothing after it lands. Filed as a follow-up with the widget-snapshot data source that already carries that tree: #17564
freezscholte commentedon Oct 26, 2026
Still reproducible on pi-subagents 0.83.0 (released 2026-10-26).
Repro on a Pi thread in T3 Code:
async: truethat counts 1→200, one bash call per number.steeraction, and the child stopped at 10 and answered as instructed. The child's session file under~/.pi/agent/sessions/confirms it.For comparison, the same test with a foreground child: the steer stays queued behind the blocked parent turn and never reaches the child, which counts to 200. That's expected, but it means background is the only steerable mode, and it's also the one T3 doesn't show.
giovanecesar commentedon Oct 30, 2026
Still reproducible on T3 Code 0.1.5 (desktop app, local server) with pi-subagents 0.84.0 and Pi 1.4.0 on macOS arm64.
With
asyncByDefault: truein the pi-subagents config, asubagentlaunch that omitsasyncruns in the background. The tool returnsDetachedright away. The children ran for several minutes and completed. None of them appeared in the Agents panel. The thread'sorchestration_v2_projection_subagentstable has 0 rows.emitSubagentTasksinpackages/provider-pi/src/server/adapter.tsstill reads onlydetails.results[], andmainhas not changed this since 0.1.5.Workaround: set
asyncByDefault: falseso launches run in the foreground and render. The parent then waits for each child.Produced by Claude Code (Opus 5.5) via
t3 triage.StiensWout commentedon Nov 9, 2026
Note
🤖 GPT 6.1 Sol responding on behalf of StiensWout
The maintainer closed our independent #33590 and is retaining our earlier #23786, which covers single, workflow, chain and parallel native Pi subagent lifecycles with regression and runtime evidence. Our new PR preserves additional original-turn, pause/terminal, late-member and bounded-retention cases plus running/incremental/completed client captures. Once a build contains the retained fix, could you retry the reported async launches and close the corresponding issue if rows appear and settle correctly after that fix lands? General extension background-job lifetime from #24187 remains separate.
thanhpp commentedon Nov 13, 2026
Additional runtime confirmation on T3 Code 0.1.8, Pi 1.5.2, and pi-subagents 0.88.1:
Two real native async subagent discovery runs were correlated to their T3 parent through provider thread mapping. Both children exited 0. T3 persisted both launches as completed
dynamic_toolcalls, but the parent had zeroorchestration_v2_projection_subagentsrows and zero subagent-named events; the run IDs were absent from those child projections/events. The UI was not inspected. Expected: track each native async child through its terminal state; actual: no child projection.The installed 0.1.8 executable and checkout
bf469bb19669671d0df2efda74ed73867a7137c0show the same likely seam: async launch returnsdetails.results: []plusrunId/asyncId, butemitSubagentTasksreads onlydetails.results(packages/provider-pi/src/server/adapter.ts:1258-1277,1305-1328). Foreground native results already have projection; the synthetic adapter test covers foreground-shaped results only. Native Pi children are distinct from T3delegate_task, which uses an app-owned thread path.Proposed minimal reproduction (not the exact discovery-run prompts used above): in a T3 Pi session, call
subagent({agent: "scout", task: "Return OK.", async: true}), wait for native completion, and compare the child projection with the completed tool call.Note
🤖 AI assistant responding on behalf of thanhpp