Skip to content

feat(orchestrator): collapse per-integration delegation into one tool (#1335)#1488

Open
obchain wants to merge 8 commits into
tinyhumansai:mainfrom
obchain:fix/1335-collapse-delegation-tools
Open

feat(orchestrator): collapse per-integration delegation into one tool (#1335)#1488
obchain wants to merge 8 commits into
tinyhumansai:mainfrom
obchain:fix/1335-collapse-delegation-tools

Conversation

@obchain
Copy link
Copy Markdown
Contributor

@obchain obchain commented May 11, 2026

Summary

  • Collapses the per-integration delegate_<toolkit> fan-out into a single delegate_to_integrations_agent tool that takes the toolkit slug as a required argument, so the orchestrator's function-calling schema cost is now constant in the integration dimension.
  • Connected toolkit slugs are surfaced inline in the tool description and on the toolkit JSON-schema enum so the orchestrator still discovers what's routable without each toolkit being its own schema entry.
  • Updates the orchestrator's prompt.md decision tree and prompt.rs delegation guide to point at the new tool, and trims the duplicated routing recap so the decision tree is the single source of routing rules.

Problem / Context

The orchestrator is the front-line agent, so its tool schema and prompt size directly affect TTFT. Before this PR:

  • src/openhuman/tools/orchestrator_tools.rs::collect_orchestrator_tools expanded SubagentEntry::Skills("*") into one synthesised SkillDelegationTool per connected Composio integration (gmail, github, notion, …). Each carried its own description string and its own JSON-schema entry, even though every one of them dispatched to the same integrations_agent with a different skill_filter.
  • src/openhuman/agent/agents/orchestrator/prompt.md and prompt.rs both referenced the per-toolkit tool names, so the routing guidance drifted as toolkits were added.

The structural problem was the fan-out: visible tool count grew linearly with the number of connected integrations even though the orchestrator only needed the routing handle ("send this to integrations, scoped to toolkit X").

Solution

1. Collapsed delegation toolsrc/openhuman/tools/impl/agent/skill_delegation.rs

SkillDelegationTool::for_connected(Vec<(slug, description)>) returns Some(tool) when at least one toolkit is connected, None otherwise. The tool:

  • Has the canonical name delegate_to_integrations_agent (exposed as INTEGRATIONS_DELEGATE_TOOL_NAME).
  • Exposes a JSON-schema enum on the toolkit parameter listing every connected slug, so model providers that honour enum will reject calls to unconnected toolkits at the schema layer.
  • Re-canonicalises the LLM-provided slug via sanitise_slug before comparing it against the connected set, so quirky names (mixed case, dashes, dots) round-trip predictably.
  • Dispatches via super::dispatch_subagent("integrations_agent", ..., Some(&slug)) — the same path the previous per-toolkit tool used.

2. Constant tool countsrc/openhuman/tools/orchestrator_tools.rs

The SubagentEntry::Skills(*) branch now builds a single (slug, description) vector from the connected integrations and emits at most one collapsed tool. AgentId entries (delegate_researcher, delegate_archivist, etc.) and direct tools in agent.toml are untouched.

3. Prompt updatessrc/openhuman/agent/agents/orchestrator/{prompt.md,prompt.rs}

  • Decision tree references delegate_to_integrations_agent with toolkit set to the relevant slug.
  • The duplicated one-line "when delegating" recap in prompt.md (line 34) was trimmed; the decision tree remains the single source of routing rules.
  • render_delegation_guide emits the compact - **gmail** (\toolkit: "gmail"`): …` format so the prompt reflects how the new tool is actually invoked.

Measurement

Captured via bash scripts/debug-agent-prompts.sh --out <dir> on upstream/main vs this branch, with the test user's currently-signed-in workspace.

Metric Before After Δ
Orchestrator prompt bytes 8144 7960 −184 bytes (prose dedup)
visible_tool_count 61 61 0 (see caveat)

Caveat (called out for transparency): the measurement workspace has zero connected Composio integrations, so the structural fan-out savings don't materialise in this dump. With N>0 connected integrations the win is N - 1 fewer tool-schema entries (each ~300 bytes of description), independent of N. The structural invariant is locked by the new unit test collapsed_delegation_tool_count_is_constant_across_integration_counts, which exercises 1, 3, 7, and 20 integrations and asserts the collapsed tool count stays at 1.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy — 23 unit tests cover: 8 cases for SkillDelegationTool (none-when-empty, canonical name, description enumeration, schema enum, normalisation, missing/unknown toolkit, empty prompt), 8 cases for collect_orchestrator_tools (AgentId + wildcard collapse, constant-count invariant, no-integration path, unknown subagent, empty subagents, sanitised slugs, unconnected omission), 7 prompt rendering cases.
  • Diff coverage ≥ 80% — every new branch is exercised by a dedicated test case; rerun pnpm test:rust to verify.
  • Coverage matrix updated — N/A: structural change to an existing capability surface; no new user-facing feature row.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md) — N/A: orchestrator tool surface, no release-cut behaviour change.
  • Linked issue closed via Closes #NNN in the ## Related section.

Impact

  • Runtime / platform: desktop only, behaviour-preserving change. No new dependencies, no schema migration. Existing JSON-RPC / CLI surfaces unchanged.
  • Performance: orchestrator tool list scales as O(1) in connected integrations instead of O(N). With the issue's example of 22 named direct tools + N integrations + K named archetypes, the visible-tool count now sits at 22 + K + 1 regardless of N.
  • Behaviour: the orchestrator now selects an integration via toolkit: "gmail" rather than calling delegate_gmail. Downstream integrations_agent continues to receive the toolkit via skill_filter, so the integrations agent's view is unchanged.
  • Migration: purely server-side; no persisted state changes.

Related

  • Closes Reduce orchestrator latency by collapsing per-integration delegation tools #1335
  • Capability surfaces: orchestrator delegation routing (src/openhuman/tools/orchestrator_tools.rs, src/openhuman/tools/impl/agent/skill_delegation.rs, src/openhuman/agent/agents/orchestrator/).
  • Follow-up PR(s)/TODOs: an optional dispatch.rs budget cap was explicitly deferred per the issue's "Non-goals" — not introduced preemptively.

AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/1335-collapse-delegation-tools
  • Commit SHAs: 6e53551 (feat), 22dbaab (docs)

Summary by CodeRabbit

  • Refactor

    • Consolidated per-integration delegation into a single unified delegation tool that selects the target integration at call time.
  • Bug Fixes

    • Validate and normalize selected integration identifiers, reject missing/empty inputs, and drop duplicate/sluggified entries to avoid ambiguous routing.
  • User-visible changes

    • Timeline/tool activity titles now reflect the chosen integration or show a generic "connected app" label when unspecified.
  • Tests

    • Expanded coverage for the consolidated flow, validation, collision handling, and edge cases.
  • Documentation

    • Updated prompts and docs to match the consolidated delegation wording.

Review Change Stack

obchain added 2 commits May 11, 2026 15:32
Replaces the N synthesised `delegate_<toolkit>` tools with a single
`delegate_to_integrations_agent` that takes the toolkit slug as a
required argument. The list of connected toolkit slugs is rendered
inline in the tool description and exposed as a JSON schema enum on
the `toolkit` parameter, so the orchestrator's function-calling
schema cost is now constant in the integration dimension while the
orchestrator still discovers which integrations are routable.

`SkillDelegationTool::for_connected` returns `None` when no
integrations are connected so the tool is omitted entirely (the
orchestrator can't usefully route to an empty set), preserving the
existing "no phantom tools" behaviour.

Server-side toolkit validation re-canonicalises the LLM-provided
slug via `sanitise_slug` before comparing it against the connected
set, mirroring how slugs are produced when the description is built
so quirky toolkit names (mixed case, dashes, dots) round-trip
predictably.

Refs tinyhumansai#1335.
Updates the orchestrator's `prompt.md` decision tree and `prompt.rs`
delegation guide so they reference `delegate_to_integrations_agent`
with the `toolkit` argument instead of the obsolete per-toolkit tool
names. Trims the duplicated one-line "when delegating" recap that
restated the decision tree, leaving the decision tree as the single
source of routing rules.

Tests in `prompt.rs` are updated to assert on the new format and
reject the old `delegate_<toolkit>` / `spawn_subagent(...)` strings.

Closes tinyhumansai#1335.
@obchain obchain requested a review from a team May 11, 2026 10:07
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5b33e122-121d-4e09-86d1-c177949598a8

📥 Commits

Reviewing files that changed from the base of the PR and between 0869b87 and 6e70140.

📒 Files selected for processing (2)
  • app/src/utils/__tests__/toolTimelineFormatting.test.ts
  • app/src/utils/toolTimelineFormatting.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/utils/tests/toolTimelineFormatting.test.ts
  • app/src/utils/toolTimelineFormatting.ts

📝 Walkthrough

Walkthrough

Collapse per-integration delegation into a single delegate_to_integrations_agent tool parameterized by toolkit, updating tool schema, execution, orchestrator tool synthesis, prompts, UI timeline formatting, and tests.

Changes

Collapsed Delegation Tool Architecture

Layer / File(s) Summary
Prompt Decision Tree
src/openhuman/agent/agents/orchestrator/prompt.md
Delegation decision tree and routine delegation guidance updated to use delegate_to_integrations_agent with toolkit argument.
Prompt Rendering & Tests
src/openhuman/agent/agents/orchestrator/prompt.rs
render_delegation_guide emits collapsed guidance with toolkit: "<slug>"; tests updated to assert presence/absence of collapsed vs. per-toolkit forms.
Subagent / API Docs
src/openhuman/agent/harness/definition.rs
Docs for SubagentEntry::Skills updated to describe the collapsed delegate_to_integrations_agent tool and pre-populated routing.
Harness / Session / Tool Loop Docs
src/openhuman/agent/harness/session/builder.rs, src/openhuman/agent/harness/tool_loop.rs, src/openhuman/channels/runtime/dispatch.rs, src/openhuman/tools/impl/agent/dispatch.rs
Doc-comments and examples updated to reflect consolidated delegation-tool naming and per-call toolkit scoping.
Data Model & Constant
src/openhuman/tools/impl/agent/skill_delegation.rs
SkillDelegationTool removes skill_id, adds connected_toolkits: Vec<(String,String)>, and defines INTEGRATIONS_DELEGATE_TOOL_NAME. for_connected returns None when empty.
Description Builder
src/openhuman/tools/impl/agent/skill_delegation.rs
Tool description enumerates connected toolkit slugs and one-line descriptions with fallback labels for empty descriptions.
Parameter Schema
src/openhuman/tools/impl/agent/skill_delegation.rs
parameters_schema() requires toolkit and prompt; toolkit constrained by an enum of sanitized slugs.
Execution & Dispatch
src/openhuman/tools/impl/agent/skill_delegation.rs
execute() validates/sanitises toolkit, rejects unknown toolkits with allowed-list error, enforces non-empty prompt, and dispatches to integrations_agent with the validated slug.
Orchestrator Tool Synthesis
src/openhuman/tools/orchestrator_tools.rs
collect_orchestrator_tools builds (slug, description) list from connected integrations, skips unconnected, drops later slug collisions, and emits one collapsed delegation tool via SkillDelegationTool::for_connected (omitted when empty).
Tests & UI
src/openhuman/tools/impl/agent/skill_delegation.rs, src/openhuman/agent/agents/orchestrator/prompt.rs, src/openhuman/tools/orchestrator_tools.rs, app/src/utils/*
Unit tests updated/added for construction, canonical name, schema enum & required fields, execute validation (missing/unknown toolkit, empty prompt, slug normalisation), prompt assertions, orchestrator synthesis behaviors (count, sanitisation, collisions, fallbacks), and timeline formatting for delegate_to_integrations_agent.

Sequence Diagram(s)

sequenceDiagram
  participant Orchestrator as Orchestrator Prompt/Model
  participant DelegateTool as delegate_to_integrations_agent
  participant IntegrationsAgent as integrations_agent
  Orchestrator->>DelegateTool: call(toolkit="gmail", prompt=...)
  DelegateTool->>IntegrationsAgent: dispatch_subagent(integrations_agent, toolkit="gmail", prompt)
  IntegrationsAgent-->>DelegateTool: result
  DelegateTool-->>Orchestrator: result (surface inline)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • senamakel
  • graycyrus

Poem

🐰 From many tools, one tidy way I bring,

A single slug that helps the prompts sing,
delegate_to_integrations_agent takes the call,
Routes to integrations_agent, handling all,
The orchestrator hops lighter in spring.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main change: collapsing per-integration delegation tools into a single tool, which is the primary objective throughout the changeset.
Linked Issues check ✅ Passed The PR successfully addresses all key requirements from issue #1335: collapses per-integration fan-out into a single tool with toolkit parameter, preserves integrations_agent routing, dedupes routing guidance, maintains essential behaviors, includes regression tests, and reports metrics.
Out of Scope Changes check ✅ Passed All changes are in scope: core infrastructure updates (orchestrator_tools.rs, skill_delegation.rs), prompt refinements, documentation updates, and frontend test additions directly support the #1335 objectives of collapsing delegation tools and deduping prompts.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/openhuman/tools/impl/agent/skill_delegation.rs (1)

125-170: ⚡ Quick win

Add routing breadcrumbs on validation failures and dispatch.

This new delegation entrypoint has several hard-to-infer branches (missing toolkit, unknown toolkit, empty prompt, dispatch to integrations_agent) but currently emits no logs, which will make routing regressions much harder to diagnose from production traces. A few [integrations_delegate] debug/trace lines on entry, rejection, and successful dispatch would make this path much easier to support. As per coding guidelines "Add copious debug/trace logs while implementing features (not as an afterthought); use log/tracing crates at debug/trace level on RPC entry/exit, error paths, state transitions, and hard-to-infer branches".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/tools/impl/agent/skill_delegation.rs` around lines 125 - 170,
In the execute method of skill_delegation.rs add trace/debug logs tagged like
"[integrations_delegate]" at entry (log tool_name and raw_toolkit/raw prompt
values), on each validation rejection (missing toolkit, unknown toolkit —
include raw_toolkit, allowed list, and sanitised slug — and empty prompt), and
around the dispatch_subagent call (log before dispatch with target
"integrations_agent", tool_name, prompt and slug, and log the result or error
after awaiting super::dispatch_subagent); use the project's tracing/log crate at
trace or debug level and include the actual error/result details in the log
messages to aid routing diagnostics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/tools/impl/agent/skill_delegation.rs`:
- Around line 268-289: Update the test
execute_normalises_toolkit_input_before_matching to actually call tool.execute
with toolkit "Google-Calendar" (via the existing tool.execute(json!({"toolkit":
"Google-Calendar", "prompt": "x"})).await.unwrap()) instead of only asserting
sanitise_slug("Google-Calendar"); assert that the execution reaches past the
unknown-toolkit validation by checking the returned error is not the
unknown-toolkit case (e.g., ensure the error result does not include the
"unknown-toolkit" indicator or message) and keep the existing setup using
SkillDelegationTool::for_connected so the toolkit gate should pass; remove or
replace the direct sanitise_slug assertion since the test must exercise the
execute() path that uses sanitise_slug internally.

In `@src/openhuman/tools/orchestrator_tools.rs`:
- Around line 136-156: The current mapping over connected_integrations uses
sanitise_slug(&integration.toolkit) and drops the original toolkit identifier,
which can collapse distinct integrations (e.g., Slack.Bot vs Slack-Bot) into the
same slug; update the transformation in the block building connected:
Vec<(String, String)> to detect slug collisions (by building a temporary map or
set keyed by slug) and fail closed (return an Err or log+panic) when a duplicate
slug is produced, or instead preserve a stable upstream id alongside the slug
(e.g., produce Vec<(String /*slug*/, String /*description*/, String
/*raw_toolkit_id*/)> or pair slug with integration.toolkit) so downstream uses
(skill_filter) can disambiguate; locate the transform around
connected_integrations, sanitise_slug, and where connected is consumed
(skill_filter) to apply the change.

---

Nitpick comments:
In `@src/openhuman/tools/impl/agent/skill_delegation.rs`:
- Around line 125-170: In the execute method of skill_delegation.rs add
trace/debug logs tagged like "[integrations_delegate]" at entry (log tool_name
and raw_toolkit/raw prompt values), on each validation rejection (missing
toolkit, unknown toolkit — include raw_toolkit, allowed list, and sanitised slug
— and empty prompt), and around the dispatch_subagent call (log before dispatch
with target "integrations_agent", tool_name, prompt and slug, and log the result
or error after awaiting super::dispatch_subagent); use the project's tracing/log
crate at trace or debug level and include the actual error/result details in the
log messages to aid routing diagnostics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78f4f128-387b-4b40-ad2b-36b61657b063

📥 Commits

Reviewing files that changed from the base of the PR and between 09c5560 and 22dbaab.

📒 Files selected for processing (4)
  • src/openhuman/agent/agents/orchestrator/prompt.md
  • src/openhuman/agent/agents/orchestrator/prompt.rs
  • src/openhuman/tools/impl/agent/skill_delegation.rs
  • src/openhuman/tools/orchestrator_tools.rs

Comment thread src/openhuman/tools/impl/agent/skill_delegation.rs
Comment thread src/openhuman/tools/orchestrator_tools.rs Outdated
…rmaliser

Addresses CodeRabbit review on tinyhumansai#1488.

`sanitise_slug` is lossy — `Slack.Bot` and `Slack-Bot` both collapse
to `slack_bot`, so the previous mapping silently shadowed one
integration when discarding the raw id. `collect_orchestrator_tools`
now walks the connected list with a slug-collision set, drops every
duplicate after the first, and warns via `log::warn` so operators
can spot the shadowed toolkit. A new
`duplicate_sanitised_slug_drops_later_collisions` test locks the
behaviour.

`execute_normalises_toolkit_input_before_matching` previously only
asserted on `sanitise_slug` directly, so a regression to raw `==`
inside `execute` would have stayed green. The test now drives
`execute("GMail", ...)` to confirm the unknown-toolkit branch fires
and `execute("Google-Calendar", ...)` to confirm the toolkit gate is
bypassed when the normalised slug matches a connected entry.
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 11, 2026
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

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

Review — collapse per-integration delegation into one tool

Overall this is a clean, well-tested structural improvement. The O(1) invariant is the right fix, slug collision handling is solid, and the test suite is comprehensive. A few things to tighten up:

3 findings (1 major, 1 major, 1 minor) — details in inline comments below.

Verified / looks good

  • for_connected returns None on empty input ✓
  • Slug collision detection with HashSet — first arrival wins ✓
  • sanitise_slug shared between tool-building and prompt rendering — cannot drift ✓
  • Error messages include raw LLM input for debuggability ✓
  • O(1) invariant test across 1/3/7/20 integrations ✓
  • No bare .unwrap() in production code ✓
  • No PII/secrets in logs ✓
  • No new standalone files at src/openhuman/ root ✓

Comment thread src/openhuman/tools/orchestrator_tools.rs Outdated
Comment thread src/openhuman/tools/orchestrator_tools.rs
Comment thread src/openhuman/tools/impl/agent/skill_delegation.rs
obchain added 3 commits May 11, 2026 19:01
Six doc sites still described the pre-tinyhumansai#1335 world where the orchestrator
synthesised one `delegate_{toolkit}` tool per connected Composio
integration. Update each to describe the collapsed
`delegate_to_integrations_agent` tool whose `toolkit` argument selects
the route, so future readers grepping for delegation surface land on
the current behaviour.
…tions

`build_description` in `SkillDelegationTool` renders ` - <slug>` lines
with no label when the upstream `ConnectedIntegration::description` is
blank, leaving the orchestrator LLM with no signal about what the
toolkit can do for newly-onboarded or under-populated integrations.

Match the phrasing the old per-toolkit fan-out used in that case
("External integration via <raw toolkit name>…") before pushing the
slug into the collapsed tool's enum, and lock the behaviour with
`empty_integration_description_falls_back_to_generic_label`.
`SkillDelegationTool::execute` had three rejection branches and a
dispatch call with no `log::debug!` lines, so the only way to diagnose
a routing failure was to add prints. Per the project's verbose-
diagnostics rule for new/changed flows, emit one entry log with the
raw toolkit and prompt size, one log per rejection branch (missing
toolkit, unknown toolkit, empty prompt), and one before the
`integrations_agent` dispatch — all prefixed `[skill-delegation]` so a
single grep traces the path.
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 11, 2026
@obchain obchain requested a review from graycyrus May 12, 2026 05:41

/// Canonical tool name surfaced to the orchestrator LLM.
pub const INTEGRATIONS_DELEGATE_TOOL_NAME: &str = "delegate_to_integrations_agent";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[major] Frontend timeline formatting degrades with the collapsed tool name.

app/src/utils/toolTimelineFormatting.ts:86 extracts the toolkit name from the tool name via entry.name.match(/^delegate_(.+)$/). With the old delegate_gmail, this correctly extracted gmail. With the new delegate_to_integrations_agent, it extracts to_integrations_agent — which does not match KNOWN_TOOLKIT_RE (L80-81), so the UI falls back to humanizeIdentifier("delegate_to_integrations_agent") = "To Integrations Agent" instead of showing the actual toolkit name like "Gmail".

The code at L55 already reads parsedArgs?.toolkit as a fallback path, but the regex match at L86 takes priority. The fix is to check parsedArgs?.toolkit before falling back to regex extraction from the tool name.

Similarly, app/src/utils/__tests__/toolTimelineFormatting.test.ts has test stubs using delegate_notion — these should add a case for the collapsed tool with a toolkit arg.

app/src/providers/ChatRuntimeProvider.tsx:302 uses startsWith('delegate_') which still matches, so that's fine.

This is not a runtime crash but a visible UX regression — users would see "To Integrations Agent" instead of the toolkit name in the tool timeline.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 0869b87. Toolkit arg path stays primary; unknown slugs (e.g. slack_bot) humanise to Slack Bot; missing toolkit falls back to Checking your connected app to match the spawn_subagent integrations_agent copy. New Vitest cases cover all three branches.

The collapsed delegation tool no longer carries the toolkit in its
name, so `humanizeIdentifier('delegate_to_integrations_agent')`
surfaced "To Integrations Agent" in the chat timeline whenever the
toolkit arg was missing or outside KNOWN_TOOLKIT_RE.

Use the existing toolkit arg first, fall back to a humanised toolkit
slug for unknown integrations (e.g. `slack_bot` → "Slack Bot"), and
finally render "Checking your connected app" — matching the
spawn_subagent → integrations_agent generic copy — instead of
humanising the tool name.

Covers three new Vitest cases (known toolkit, unknown toolkit, no
toolkit) and leaves the existing delegate_<toolkit> behaviour intact.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/utils/__tests__/toolTimelineFormatting.test.ts`:
- Line 91: Prettier formatting is failing in
app/src/utils/__tests__/toolTimelineFormatting.test.ts for the test case
it('formats delegate_to_integrations_agent without a toolkit arg as a generic
connected-app label', ...); fix by running Prettier --write on that file (or
your repo's formatter) to apply the project's formatting rules and re-run tests;
ensure the test block (the it(...) declaration and surrounding file) is
reformatted to match the project's Prettier config so CI passes.

In `@app/src/utils/toolTimelineFormatting.ts`:
- Around line 59-79: Prettier formatting is failing for the block that sets
title (references: provider, entry.name === 'delegate_to_integrations_agent',
parsedArgs?.toolkit, integrationActivityTitle, humanizeIdentifier); run Prettier
on this file and reformat the function/block containing that title assignment so
it matches project style rules (fix spacing/line breaks, trailing commas, and
indentation) and then commit the formatted file so CI Prettier check passes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec2544b9-7e1d-4c46-b7b1-950eb72e01ca

📥 Commits

Reviewing files that changed from the base of the PR and between 71f38f8 and 0869b87.

📒 Files selected for processing (2)
  • app/src/utils/__tests__/toolTimelineFormatting.test.ts
  • app/src/utils/toolTimelineFormatting.ts

Comment thread app/src/utils/__tests__/toolTimelineFormatting.test.ts
Comment thread app/src/utils/toolTimelineFormatting.ts
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.

Reduce orchestrator latency by collapsing per-integration delegation tools

2 participants