Skip to content

fix: increase tool call limit to 50 and show clear pause message#2828

Merged
wwwillchen merged 2 commits intodyad-sh:mainfrom
wwwillchen-bot:agent-2754-1772236131
Mar 2, 2026
Merged

fix: increase tool call limit to 50 and show clear pause message#2828
wwwillchen merged 2 commits intodyad-sh:mainfrom
wwwillchen-bot:agent-2754-1772236131

Conversation

@wwwillchen-bot
Copy link
Copy Markdown
Collaborator

@wwwillchen-bot wwwillchen-bot commented Feb 27, 2026

Summary

  • Increase MAX_TOOL_CALL_STEPS from 25 to 50 to allow longer multi-step tasks
  • Add step limit detection to track total steps across all passes
  • Show a clear <dyad-step-limit> message when the limit is reached, instructing users to send "continue" to resume
  • Create DyadStepLimit component for displaying the pause notification

Fixes #2754

Test plan

  • Run the local agent and perform a task that requires many tool calls
  • Verify the agent pauses at 50 tool calls instead of 25
  • Verify a clear message is shown explaining why it paused and how to continue
  • Type "continue" to verify the agent resumes working

πŸ€– Generated with Claude Code


Open with Devin

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the agent's capability to handle more extensive multi-step operations by raising the tool call limit. It also refines the user experience by providing transparent communication when the agent pauses due to reaching this limit, offering explicit instructions for how to proceed. This change aims to balance the prevention of runaway processes with the need to support more intricate automated workflows.

Highlights

  • Increased Tool Call Limit: The maximum number of tool call steps has been increased from 25 to 50, allowing the agent to perform longer and more complex multi-step tasks without premature interruption.
  • Cumulative Step Tracking: A new mechanism has been introduced to track the total number of tool call steps executed across all passes, ensuring accurate detection of the overall step limit.
  • Clear Pause Notification: When the tool call limit is reached, a clear and informative <dyad-step-limit> message is now displayed, instructing users to send 'continue' to resume the agent's operation.
  • New UI Component: A dedicated DyadStepLimit React component has been created to consistently render the pause notification within the chat interface.
Changelog
  • src/components/chat/DyadMarkdownParser.tsx
    • Imported the newly created DyadStepLimit component.
    • Added dyad-step-limit to the list of recognized custom tags for markdown parsing.
    • Implemented a new rendering case within the renderCustomTag function to display the DyadStepLimit component.
  • src/components/chat/DyadStepLimit.tsx
    • Added a new React component DyadStepLimit responsible for rendering the pause notification when the agent reaches its tool call limit.
    • The component displays the number of steps executed and provides instructions for the user to 'continue'.
  • src/pro/main/ipc/handlers/local_agent/local_agent_handler.ts
    • Updated the MAX_TOOL_CALL_STEPS constant from 25 to 50.
    • Introduced a totalStepsExecuted variable to track the cumulative number of tool calls across all processing passes.
    • Modified the stepCountIs condition to utilize the new MAX_TOOL_CALL_STEPS value.
    • Added logic to increment totalStepsExecuted after each stream response is processed.
    • Implemented a conditional check to append a dyad-step-limit message to the response if the totalStepsExecuted meets or exceeds the defined limit, pausing the agent.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with πŸ‘ and πŸ‘Ž on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

gemini-code-assist[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

This PR increases the local agent's tool call step limit from 25 to 50, adds cross-pass step tracking, and introduces a <dyad-step-limit> UI card that pauses the agent and prompts the user to type "Continue" (or click the Continue button) to resume.

Key changes:

  • MAX_TOOL_CALL_STEPS raised to 50 in local_agent_handler.ts; a totalStepsExecuted counter accumulates steps across all passes and triggers the notice once >= 50
  • New DyadStepLimit React component renders an amber pause card with a functional Continue button that submits a "Continue" prompt on behalf of the user
  • DyadMarkdownParser registers dyad-step-limit as a custom tag and routes it to the new component
  • New E2E test and fixture exercise the full pause-and-resume flow

Issues found:

  • steps.length counts AI SDK agentic steps (one step per model call iteration, which may include multiple parallel tool calls), not individual tool calls. The user-facing message "Paused after N tool calls" can therefore under-count actual tool calls when the model issues parallel calls in a single step.
  • Every historical <dyad-step-limit> card in a conversation will show an active Continue button, since state is derived from the message-level streaming flag. If the agent has paused multiple times, multiple functional Continue buttons will be visible simultaneously, which could confuse users into re-sending "Continue" for an already-resumed session.

Confidence Score: 4/5

  • Safe to merge with minor UX and terminology improvements worth tracking as follow-ups.
  • The core logic is correct: the step counter accumulates properly, the limit check fires after the loop, and the UI component is wired up consistently with the existing custom-tag pattern. The two flagged issues are a terminology inaccuracy in user-facing copy (steps vs. tool calls) and a UX concern around stale Continue buttons in conversation history β€” neither is a runtime bug or data correctness issue.
  • src/components/chat/DyadStepLimit.tsx β€” the Continue button visibility logic should be revisited to prevent stale buttons on historical pause cards.

Important Files Changed

Filename Overview
src/pro/main/ipc/handlers/local_agent/local_agent_handler.ts Increases MAX_TOOL_CALL_STEPS from 25 to 50, adds totalStepsExecuted counter across passes, and appends a notice to fullResponse when the limit is reached. The terminology "tool calls" in the notice is slightly inaccurate since steps.length counts agentic iterations (which may each contain multiple parallel tool calls).
src/components/chat/DyadStepLimit.tsx New component rendering the pause notification card with a Continue button. The _limit prop is parsed but never rendered. All historical instances of this card (from prior turns) will show an active Continue button since state derives from the message-level streaming flag.
src/components/chat/DyadMarkdownParser.tsx Registers dyad-step-limit as a custom tag and routes it to DyadStepLimit, forwarding steps/limit attributes and the shared state. Consistent with the existing tag-dispatch pattern.
e2e-tests/local_agent_step_limit.spec.ts New E2E test that verifies the step-limit pause card appears, shows a Continue button, and correctly resumes when clicked. Snapshot-verified and follows existing test patterns.
e2e-tests/fixtures/engine/local-agent/step-limit.ts Fixture generating exactly 50 single-tool-call turns to reliably trigger the step limit. Comment correctly notes the final text turn is unreachable.

Sequence Diagram

sequenceDiagram
    participant User
    participant Frontend as DyadStepLimit (UI)
    participant Handler as local_agent_handler
    participant AISDK as AI SDK (streamText)

    User->>Handler: Send prompt
    Handler->>AISDK: streamText(stopWhen: [stepCountIs(50), ...])
    loop Up to 50 agentic steps
        AISDK-->>Handler: step (model call + tool execution)
        Handler-->>Frontend: sendResponseChunk (incremental text)
    end
    AISDK-->>Handler: stream ends (step limit reached)
    Handler->>Handler: totalStepsExecuted += steps.length
    alt totalStepsExecuted >= MAX_TOOL_CALL_STEPS (50)
        Handler->>Handler: append <dyad-step-limit> to fullResponse
        Handler->>Frontend: sendResponseChunk (final, includes dyad-step-limit tag)
        Frontend-->>User: Render DyadStepLimit card (amber, "Paused after N tool calls")
        User->>Frontend: Click "Continue" button
        Frontend->>Handler: streamMessage(prompt="Continue")
        Handler->>AISDK: New streamText pass (fresh 50-step budget)
    else totalStepsExecuted < MAX_TOOL_CALL_STEPS
        Handler->>Frontend: Normal response completion
    end
Loading

Last reviewed commit: 0c31891

greptile-apps[bot]

This comment was marked as resolved.

@github-actions
Copy link
Copy Markdown
Contributor

πŸ€– Claude Code Review Summary

PR Confidence: 4/5

All review comments addressed with a targeted fix; CI verification pending.

Unresolved Threads

No unresolved threads

Resolved Threads

Issue Rationale Link
Remove unused _limit destructured variable in DyadStepLimit.tsx Valid cleanup β€” variable was destructured but never used View
False positive step limit notification across multiple passes (5 threads) Valid bug β€” totalStepsExecuted >= MAX_TOOL_CALL_STEPS could falsely trigger when passes complete naturally. Fixed by tracking per-pass hitStepLimit boolean set only when stepCountIs() actually stops a pass. Per Principle #4: Transparent Over Magical, the pause notification should only appear when the agent was actually paused, not when it completed naturally. View
Product Principle Suggestions

No suggestions β€” principles were clear enough for all decisions.


πŸ€– Generated by Claude Code

@github-actions
Copy link
Copy Markdown
Contributor

βœ… Claude Code completed successfully

Summary

  • Fixed 6 review comments (all from trusted bots, all related to 2 distinct issues)
  • No CI failures fixable by code changes
Review Comments Addressed

Issue 1: Remove unused _limit variable in DyadStepLimit.tsx (gemini-code-assist)

  • Removed unused limit: _limit destructured property from component

Issue 2: False positive step limit notification across multiple passes (devin-ai-integration, chatgpt-codex-connector, cubic-dev-ai Γ—2, greptile-apps)

  • Added hitStepLimit boolean flag to track whether any individual pass was actually stopped by stepCountIs(MAX_TOOL_CALL_STEPS)
  • Changed post-loop check from totalStepsExecuted >= MAX_TOOL_CALL_STEPS to hitStepLimit
  • Prevents false "Paused" notifications when multiple passes naturally complete with combined steps >= 50
CI Check Analysis
  • claude-review: Fails due to wwwillchen-bot lacking write permissions β€” infrastructure issue, not fixable by code changes
  • e2e-tests shard 2/2: 2 failed + 3 flaky tests β€” pre-existing flaky tests also failing on main branch (setup_flow.spec.ts, select_component.spec.ts, etc.). Not related to this PR's changes.
  • build, lint, shard 1/2: All pass βœ…

Workflow run

@github-actions github-actions bot added cc:done needs-human:review-issue ai agent flagged an issue that requires human review and removed cc:pending labels Feb 28, 2026
@github-actions github-actions bot added cc:rebasing and removed cc:rebase needs-human:review-issue ai agent flagged an issue that requires human review cc:rebasing labels Mar 2, 2026
@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid β€” if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="e2e-tests/snapshots/local_agent_step_limit.spec.ts_local-agent---step-limit-pause-1.aria.yml">

<violation number="1" location="e2e-tests/snapshots/local_agent_step_limit.spec.ts_local-agent---step-limit-pause-1.aria.yml:175">
P2: This snapshot is too permissive and does not verify the new 50-call limit. Assert the exact number in the pause text so regressions in the configured threshold are caught.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

- img
- text: Read package.json
- img
- text: /Paused after \d+ tool calls/
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 2, 2026

Choose a reason for hiding this comment

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

P2: This snapshot is too permissive and does not verify the new 50-call limit. Assert the exact number in the pause text so regressions in the configured threshold are caught.

Prompt for AI agents
Check if this issue is valid β€” if so, understand the root cause and fix it. At e2e-tests/snapshots/local_agent_step_limit.spec.ts_local-agent---step-limit-pause-1.aria.yml, line 175:

<comment>This snapshot is too permissive and does not verify the new 50-call limit. Assert the exact number in the pause text so regressions in the configured threshold are caught.</comment>

<file context>
@@ -0,0 +1,214 @@
+- img
+- text: Read package.json
+- img
+- text: /Paused after \d+ tool calls/
+- button "Continue":
+  - img
</file context>
Fix with Cubic

wwwillchen and others added 2 commits March 2, 2026 15:37
- Increase MAX_TOOL_CALL_STEPS from 25 to 50 to allow longer multi-step tasks
- Add step limit detection to track total steps across all passes
- Show a clear <dyad-step-limit> message when the limit is reached
- Create DyadStepLimit component for displaying the pause notification
- Message instructs users to send "continue" to resume

Fixes dyad-sh#2754

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbf8403b56

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

<Button
variant="outline"
size="sm"
disabled={isLoading}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Disable Continue until current stream fully ends

The Continue action can be silently dropped because this button is enabled as soon as the <dyad-step-limit> chunk is rendered, but useStreamChat still treats the chat as actively streaming until onEnd and ignores duplicate stream requests for that chat. In that window, clicking Continue triggers streamMessage no-op behavior and the user has to click again later, which makes the pause/resume flow intermittently fail from the user’s perspective.

Useful? React with πŸ‘Β / πŸ‘Ž.

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c31891849

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1072 to +1073
// Track total steps for step limit detection
totalStepsExecuted += steps.length;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Count only tool-call steps before emitting pause notice

totalStepsExecuted is incremented with steps.length, but steps includes non-tool iterations (for example the final text-only step when a pass completes normally). This means the new <dyad-step-limit> branch can fire even when fewer than 50 tool calls occurred, so users may see a "Paused after N tool calls" card and Continue prompt after a successful completion rather than an actual step-limit stop.

Useful? React with πŸ‘Β / πŸ‘Ž.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

πŸ” Dyadbot Code Review Summary

Verdict: βœ… YES - Ready to merge

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

No HIGH or MEDIUM issues found beyond what's already discussed in existing comments.

Note: The major correctness concern β€” totalStepsExecuted >= MAX_TOOL_CALL_STEPS falsely triggering when the agent completes naturally across multiple passes β€” is already well-covered by 4 existing bot comments on this PR.

🟒 Low Priority Notes (4 items)
  • Inconsistent XML escaping β€” src/pro/main/ipc/handlers/local_agent/local_agent_handler.ts:1151 β€” The step limit message interpolates values directly without escapeXmlAttr()/escapeXmlContent(), unlike other XML tag constructions in this file (e.g., dyad-compaction, dyad-output). Values are integers so no actual risk, but inconsistent with codebase pattern.
  • Redundant header/body text β€” src/components/chat/DyadStepLimit.tsx β€” Header says "Paused after N tool calls" and body content says "Automatically paused after N tool calls." β€” these convey the same information with slightly different wording. Consider making the body more informative or removing it.
  • "Tool calls" terminology β€” src/components/chat/DyadStepLimit.tsx:47 β€” "Tool calls" is developer-facing terminology. While Dyad's audience is developers, "steps" or "actions" could be slightly more intuitive. Minor since the tool call concept is visible throughout the chat UI.
  • No ARIA live region β€” src/components/chat/DyadStepLimit.tsx β€” The pause notification card has no role="status" or aria-live attribute, so screen readers may not announce it when it appears at the end of a long streaming session.
🚫 Dropped False Positives (12 items)
  • No error handling around step limit DB update β€” Dropped: updateResponseInDb is called without individual try/catch throughout the entire function; this follows the existing pattern, not a new risk introduced by this PR.
  • isLoading not reset if streamMessage early-returns β€” Dropped: The !chatId guard protects before the call; overlaps with existing comment about disabling Continue until stream ends.
  • Test fixture boundary condition (exactly 50 turns) β€” Dropped: The test passes, confirming stepCountIs(50) semantics work as expected at this boundary.
  • Step limit tag pollutes conversation history β€” Dropped: This is the established pattern for all custom tags (dyad-compaction, dyad-output, etc.) in the codebase.
  • Magic number 50 in fixture β€” Dropped: Test fixtures should hardcode values; if the constant changes, the test SHOULD fail to catch the behavioral change.
  • Unreachable finalTurn is dead code β€” Dropped: Intentional test fixture pattern with an explanatory comment.
  • Comment explains the obvious β€” Dropped: Too nitpicky for the review.
  • No guidance when content empty β€” Dropped: Content is always set by the handler; the empty case cannot occur in practice.
  • Double-click on Continue button β€” Dropped: React 18 batches state updates synchronously in event handlers; disabled={isLoading} takes effect before a second click fires.
  • Continue button lacks accessible label β€” Dropped: Visible text "Continue" already provides the accessible name per ARIA spec.
  • No visual indication while streaming state β€” Dropped: The tag is emitted at the END of response processing; the pending state is extremely brief.
  • DyadCardContent empty container β€” Dropped: Subsumed by the redundant header/body text observation.

Generated by Dyadbot multi-agent code review

@github-actions github-actions bot added the needs-human:final-check ai agent thinks everything looks good - needs final review from human label Mar 2, 2026
@wwwillchen wwwillchen merged commit 005b72b into dyad-sh:main Mar 2, 2026
12 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 3, 2026

🎭 Playwright Test Results

βœ… All tests passed!

OS Passed Flaky Skipped
🍎 macOS 366 3 120
πŸͺŸ Windows 367 4 120

Total: 733 tests passed (7 flaky) (240 skipped)

⚠️ Flaky Tests

🍎 macOS

  • fix_error.spec.ts > fix error with AI (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > node.js install flow (passed after 2 retries)

πŸͺŸ Windows

  • chat_input.spec.ts > send button disabled during pending proposal - reject (passed after 1 retry)
  • edit_code.spec.ts > edit code (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • template-create-nextjs.spec.ts > create next.js app (passed after 1 retry)

πŸ“Š View full report

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

Labels

needs-human:final-check ai agent thinks everything looks good - needs final review from human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[session report] Agent stops before completing all tasks, requires manual "continue"

3 participants