Skip to content

feat(agent): add call_agents_parallel tool for concurrent sub-agent fan-out - #47

Merged
duyetbot merged 1 commit into
mainfrom
feat/parallel-subagents
Jul 4, 2026
Merged

feat(agent): add call_agents_parallel tool for concurrent sub-agent fan-out#47
duyetbot merged 1 commit into
mainfrom
feat/parallel-subagents

Conversation

@duyetbot

@duyetbot duyetbot commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a call_agents_parallel derived tool (alongside the existing call_agent_* single-call tools) generated whenever callable_agents has 1+ entries. It accepts { calls: [{ agent_id, message }, ...] } and runs the delegate calls concurrently via a small worker-pool limiter (runWithConcurrencyLimit in apps/agent/src/harness/tools.ts — no new dependency).
  • Each child's result carries its own success/error/response/thread_id — one child failing never fails the whole tool call.
  • New max_parallel_subagents field on AgentConfig (default 5, hard ceiling 10 regardless of config) — plumbed through packages/api-types, packages/agents-store (create/update/detectChanges), and packages/http-routes/src/agents.
  • session-do.ts's runSubAgent gained an optional onThreadStarted callback so the new delegateToAgentDetailed env hook can surface the child's session_thread_id (for Console deep-linking) without changing the existing delegateToAgent return contract used by call_agent_*.
  • call_agents_parallel classified as a builtin tool in default-loop.ts (emits agent.tool_use, not agent.custom_tool_use).
  • Documented in AGENTS.md (Derived Tools table + new "Parallel Delegation" section + max_parallel_subagents config field).

Closes #20

Test plan

  • pnpm typecheck clean
  • New tests in test/unit/harness.test.ts (describe("call_agents_parallel", ...), 8 cases): tool generation gating, concurrent timing (3 children ~1x delay not 3x), partial-failure aggregation, unknown agent_id rejection without aborting the batch, concurrency-cap enforcement (max_parallel_subagents), per-child thread_id surfacing via delegateToAgentDetailed, and the no-delegate fallback
  • pnpm vitest run test/unit/harness.test.ts test/unit/agents-store-service.test.ts — 72 passed
  • pnpm run test:packages (session-runtime, main-node, cap, integrations-adapters-node, sandbox) — all passed
  • Full root pnpm vitest run (all 120 files) is flaky in this sandbox regardless of this change — reran it twice and got two different sets of failing files (20 vs 11), all unrelated timeouts in files this PR doesn't touch (skills.test.ts, stress.test.ts, core.test.ts, implementation.test.ts, unit.test.ts). Verified via git stash that the same resource-contention timeouts reproduce on a clean baseline checkout too, and that all 5 of those files pass cleanly (133/141, 0 failed) when run in a smaller batch instead of the full 120-file suite at once.

Note: per the task, another agent was concurrently working on issue #19 (long-running harness) which also touches apps/agent/src/harness/ — some merge conflicts against that PR are expected.

🤖 Generated with Claude Code

https://claude.ai/code/session_0153JT4zR2YdjkGwMkCaGmF9

…an-out

callable_agents delegation previously only supported one child session at
a time via call_agent_* (blocking until idle). Adds a call_agents_parallel
derived tool that fans out N delegate calls concurrently (worker-pool
limiter, no new dependency), aggregates per-child success/failure + thread
id, and caps concurrency via the new max_parallel_subagents agent config
field (default 5, hard ceiling 10 regardless of config).

Closes #20

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153JT4zR2YdjkGwMkCaGmF9

@sourcery-ai sourcery-ai 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.

Sorry @duyetbot, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@duyetbot, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 29 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8ccf5e5f-8171-42af-be3a-d4e1705bd75d

📥 Commits

Reviewing files that changed from the base of the PR and between a57896c and a5236a1.

📒 Files selected for processing (9)
  • AGENTS.md
  • apps/agent/src/harness/default-loop.ts
  • apps/agent/src/harness/interface.ts
  • apps/agent/src/harness/tools.ts
  • apps/agent/src/runtime/session-do.ts
  • packages/agents-store/src/service.ts
  • packages/api-types/src/types.ts
  • packages/http-routes/src/agents/index.ts
  • test/unit/harness.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/parallel-subagents

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces the call_agents_parallel tool, enabling agents to delegate tasks to multiple sub-agents concurrently and aggregate their results. It adds support for a configurable concurrency cap (max_parallel_subagents) with a default of 5 and a hard ceiling of 10, along with detailed delegation capabilities to surface child thread IDs. Feedback was provided regarding a potential edge case where an invalid or non-finite concurrency configuration could evaluate to NaN and cause silent execution failures, along with a suggested fix to sanitize the input.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +1268 to +1272
const configuredLimit = agentConfig.max_parallel_subagents;
const concurrencyLimit = Math.min(
MAX_PARALLEL_SUBAGENTS_HARD_CAP,
Math.max(1, configuredLimit ?? DEFAULT_MAX_PARALLEL_SUBAGENTS),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

If agentConfig.max_parallel_subagents is configured with an invalid value (such as NaN or a non-finite number), concurrencyLimit can evaluate to NaN. This propagates to runWithConcurrencyLimit and causes workerCount to be NaN, resulting in an empty worker array and a silent failure where no sub-agents are executed. Sanitizing the configured limit to ensure it is a finite integer prevents this.

    const configuredLimit = agentConfig.max_parallel_subagents;
    const concurrencyLimit = Math.min(
      MAX_PARALLEL_SUBAGENTS_HARD_CAP,
      Math.max(
        1,
        typeof configuredLimit === "number" && Number.isFinite(configuredLimit)
          ? Math.floor(configuredLimit)
          : DEFAULT_MAX_PARALLEL_SUBAGENTS
      ),
    );

@duyetbot
duyetbot merged commit 9ab0608 into main Jul 4, 2026
6 checks passed
@duyetbot
duyetbot deleted the feat/parallel-subagents branch July 4, 2026 10:41
duyetbot pushed a commit that referenced this pull request Jul 4, 2026
…licts

max_parallel_subagents (#20/#47) and notify (#23/#46) are independent
additive AgentConfig fields touched by both PRs in the same spots —
kept both.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Child/parallel sub-agent spawning + result aggregation

2 participants