Skip to content

feat(workflow-executor): let an MCP step make several tool calls - #1991

Open
hercemer42 wants to merge 3 commits into
mainfrom
feature/prd-1485-agent-nodejs-mcp-step-multi-call-loop-over-the-allowed-tools
Open

hercemer42 wants to merge 3 commits into
mainfrom
feature/prd-1485-agent-nodejs-mcp-step-multi-call-loop-over-the-allowed-tools

Conversation

@hercemer42

@hercemer42 hercemer42 commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Lets an MCP step make several tool calls over its allowed tools, one at a time, before giving its answer. Under confirmation, each call is approved on its own.

fixes PRD-1485

What changes

  1. Several calls per step. Before: the AI picked exactly one tool, then a second AI call summarized its result. After: the AI calls the allowed tools one at a time, sees every previous result, and ends with complete-step, whose summary becomes formattedResponse. A step that asks for an 11th call fails.
  2. Run record. Before: executionParams / executionResult described the one call. After: McpStepExecutionData.toolCalls lists every executed call ({ name, sourceId, input, result }). executionParams and toolResult hold the last call, and executionResult keeps its shape.
  3. Confirmation. Before: one approval ran the one call. After: each proposed call pauses as pendingData with the previous confirmation cleared. Accepting it runs that call and continues; rejecting it skips the step and keeps toolCalls.
  4. Interruptions. Automatic mode stays executing from the first call to the final answer, so a crash still raises the existing interrupted error. A re-authentication pause keeps the completed calls and resumes from them, so they never run twice. A step that has timed out starts no further AI decision or tool call.

Not tested manually against a live executor: covered by the unit and integration suites (mcp-step-executor.test.ts, workflow-execution.test.ts).

Release plan

Ships last in PRD-130's stage 2, after PRD-1486 (forestadmin run view), so the run view already renders several calls when this executor emits them. No floor: the loop adds no field the orchestrator or front gates on, and PRD-1482's allow-list floor still applies.

Decisions

  • PRD-130: 5 functional · 5 unticked
  • PRD-1485: 3 architectural · 2 unticked

Squash message

feat(workflow-executor): let an MCP step make several tool calls

An MCP step could call exactly one tool, then summarized its result in a
second AI call, so a task needing a lookup before an action took several
steps. The step now loops over its allowed tools: the AI makes one call at a
time, sees every previous result, and ends with complete-step, whose summary
becomes formattedResponse. Every executed call is recorded in toolCalls, a
step is capped at 10 calls, and each call is confirmed on its own under
AutomatedWithConfirmation. A step stays executing from its first call to its
final answer, a re-authentication pause resumes from the completed calls,
and a timed-out step starts no further call. A step ending without its
answer (handled manually, rejected, failed) lists the calls it made in the
summary later steps read.

Definition of Done

General

  • Write an explicit title for the Pull Request, following Conventional Commits specification
  • Test manually the implemented changes
  • Validate the code quality (indentation, syntax, style, simplicity, readability)

Security

  • Consider the security impact of the changes made

🤖 Generated with Claude Code

Note

Let MCP steps in workflow-executor make multiple tool calls in a loop

  • Replaces single-shot tool selection in McpStepExecutor with an iterative loop. The model now sees a complete-step tool and a bounded list of scoped remote tools, and it chooses either another tool call or a final summary after each result.
  • Persists an ordered call history in McpStepExecutionData.toolCalls. The last call is still written to executionParams for single-call readers, and the model's final summary becomes the formatted response.
  • Adds a ten-call limit per step. Exceeding it raises the new McpToolCallLimitError, and the model is instructed to narrow its prompt use when it hits the limit.
  • Confirmation, timeout, re-auth pause, and redispatch paths now work per call. Each proposed call in confirmation mode pauses for user approval, timeouts abort mid-step without marking completion, and redispatched steps resume from persisted calls instead of repeating them.
  • Behavioral Change: McpStepExecutor.selectTool and formatToolResult are removed, and persisted MCP records gain the toolCalls field (see step-execution-data.ts). Steps that previously ended after one tool call now continue until the model calls complete-step.

Macroscope summarized 114c6e7.

An MCP step could call exactly one tool, then a separate AI call summarized
its result. Tasks that need a lookup before an action (find a user, then
open a ticket for them) could not be done in one step.

The step now runs a loop over its allowed tools: the AI makes one call at
a time, sees every previous result, and ends by calling complete-step,
whose summary becomes formattedResponse. Each executed call is recorded in
toolCalls; executionParams and toolResult keep the last call so readers of
the single-call shape still work. A step is capped at 10 calls.

Automatic mode stays 'executing' from the first call to the final answer,
so an interruption still raises the existing StepStateError. Under
confirmation every proposed call pauses with its confirmation cleared, and
a rejection keeps the completed calls. A re-authentication pause keeps the
completed calls and resumes from them, so they never run twice.

Refs: PRD-1485

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Oct 8, 2026

Copy link
Copy Markdown

PRD-1485

Comment thread packages/workflow-executor/src/executors/mcp-step-executor.ts
@qltysh

qltysh Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Qlty


Coverage Impact

This PR will not change total coverage.

Modified Files with Diff Coverage (4)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
...orkflow-executor/src/executors/summary/step-summary-builder.ts100.0%
Coverage rating: A Coverage rating: A
packages/workflow-executor/src/errors.ts100.0%
Coverage rating: A Coverage rating: A
packages/workflow-executor/src/executors/mcp-step-executor.ts100.0%
Coverage rating: A Coverage rating: A
...ow-executor/src/executors/summary/step-execution-formatters.ts100.0%
Total100.0%
🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

The base step executor reports a timeout without cancelling the work, so a
loop that outlived its step timeout went on asking the AI and calling tools
in the background, and could mark the step done after it was reported as
failed. The loop now checks the step's deadline before each AI decision
and each tool call.

Refs: PRD-1485

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hercemer42
hercemer42 marked this pull request as ready for review October 8, 2026 14:58
…P step made

An MCP step handled manually, rejected or failed after some calls left later
steps a summary naming only the proposed call: the calls that already ran,
side effects included, were invisible to the AI of every following step.
Such a step's summary now lists its calls with their results, and no longer
presents an approved call as merely proposed.

Refs: PRD-1485

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant