Skip to content

fix(subagents): route spawn_agent through its streaming override#1080

Merged
Aaronontheweb merged 2 commits into
netclaw-dev:devfrom
Aaronontheweb:fix/spawn-agent-streaming-dispatch
May 19, 2026
Merged

fix(subagents): route spawn_agent through its streaming override#1080
Aaronontheweb merged 2 commits into
netclaw-dev:devfrom
Aaronontheweb:fix/spawn-agent-streaming-dispatch

Conversation

@Aaronontheweb
Copy link
Copy Markdown
Collaborator

Summary

A sub-agent spawned via spawn_agent was killed at exactly the 90s tool-execution timeout despite actively streaming — the streaming-tool-call work (#1045) meant to prevent mid-run sub-agent timeouts never actually ran for spawn_agent.

SpawnAgentTool.ExecuteStreamAsync was an orphan method. INetclawTool.ExecuteStreamAsync is a C# default interface method, bound to the DIM default at the NetclawTool<T> base class — a derived tool adding a matching public method does not re-implement it, so the override was unreachable through INetclawTool-typed dispatch. DispatchingToolExecutor always hit the DIM default, collapsing spawn_agent to the non-streaming path with no activity sink. Zero ToolActivityUpdate items reached the parent's per-call StreamingToolWatchdog, which then fired at its flat budget and cancelled a healthy, progressing sub-agent.

  • Add a virtual ExecuteStreamAsync hook on NetclawTool<T> so the override is the interface implementation for the whole tool hierarchy.
  • Mark SpawnAgentTool.ExecuteStreamAsync as override — the wiring is now compiler-enforced, so this class of bug can't recur silently.
  • Add a full-chain integration test crossing DispatchingToolExecutorINetclawTool dispatch → SpawnAgentToolSubAgentActorStreamingToolWatchdog.

Test plan

  • New SpawnAgentStreamingTests fails without the fix (verified by reverting the two source changes), passes with it
  • StreamingToolCallTests, SubAgentSpawnIntegrationTests, SubAgentActorTests, SpawnAgentToolTests still pass (77 tests green)
  • Full solution builds with 0 warnings / 0 errors; slopwatch reports 0 issues; copyright headers verified

…ool dispatch

spawn_agent's ExecuteStreamAsync was an orphan public method. INetclawTool.ExecuteStreamAsync
is a default interface method, bound to the DIM default at the NetclawTool<T> base class — a
derived tool adding a matching public method does not re-implement it, so the override was
unreachable through INetclawTool-typed dispatch. spawn_agent fell through to the non-streaming
path, emitted zero activity items, and the parent's per-call StreamingToolWatchdog killed
healthy sub-agents at the flat tool-execution timeout.

Add a virtual ExecuteStreamAsync hook on NetclawTool<T> so the override is the interface
implementation for the whole tool hierarchy, and mark SpawnAgentTool's override as `override`
so the wiring is compiler-enforced. Add a full-chain integration test that crosses the
executor -> INetclawTool dispatch -> SpawnAgentTool -> SubAgentActor -> watchdog seam.
Reuse the production SingleClientProvider instead of a private duplicate,
decouple the integration test's result assertion from FakeChatClient's exact
output text, and condense the doc comments on the streaming test and the
NetclawTool<T>.ExecuteStreamAsync hook. No behavior change.
@Aaronontheweb Aaronontheweb merged commit 817f677 into netclaw-dev:dev May 19, 2026
14 checks passed
@Aaronontheweb Aaronontheweb added the subagents spawn_agent, SubAgentActor, definition loader, discovery context layer, and related features label May 19, 2026
@Aaronontheweb Aaronontheweb deleted the fix/spawn-agent-streaming-dispatch branch May 19, 2026 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

subagents spawn_agent, SubAgentActor, definition loader, discovery context layer, and related features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant