Skip to content

Comments

fix(core): prevent duplicate LLM calls when message contains URL or triggers providers#6528

Open
nicolasdma wants to merge 1 commit intoelizaOS:developfrom
nicolasdma:fix/duplicate-llm-calls-url-messages
Open

fix(core): prevent duplicate LLM calls when message contains URL or triggers providers#6528
nicolasdma wants to merge 1 commit intoelizaOS:developfrom
nicolasdma:fix/duplicate-llm-calls-url-messages

Conversation

@nicolasdma
Copy link

@nicolasdma nicolasdma commented Feb 23, 2026

Relates to

Relates to #6486

Risks

Low — single condition removed from a boolean expression. No new code, no new logic paths.

Background

What does this PR do?

Removes the providers.length check from the isSimple determination in packages/typescript/src/services/message.ts.

What kind of change is this?

Bug fix (non-breaking change that fixes an issue).

Changes

When a user sends a message containing a URL, the LLM's first call (via runSingleShotCore) generates and streams the response text. It also returns providers: ["ATTACHMENTS"] because the prompt template instructs it to when it sees URLs.

The isSimple check at line 1883 previously treated "has providers" as "not simple":

const isSimple =
    responseContent?.actions &&
    responseContent.actions.length === 1 &&
    typeof responseContent.actions[0] === "string" &&
    responseContent.actions[0].toUpperCase() === "REPLY" &&
    (!responseContent.providers || responseContent.providers.length === 0);
//   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//   This condition causes the bug

This caused the message to go through the actions path, which triggered the REPLY action handler (reply.ts:60), making a second LLM call with replyTemplate and streaming another response — duplicating output and doubling token costs.

The fix: Remove the providers check. Providers enrich state (already handled at L863-871) but don't require re-generating the response. isSimple should only care about whether the action is REPLY (text already generated and streamed) vs something else (needs execution).

const isSimple =
    responseContent?.actions &&
    responseContent.actions.length === 1 &&
    typeof responseContent.actions[0] === "string" &&
    responseContent.actions[0].toUpperCase() === "REPLY";

Testing

  • Message with URL → single response (not duplicated)
  • Message without URL → works as before
  • Multi-action messages (REPLY + other) → still trigger actions path
  • Messages with non-REPLY actions → still trigger actions path

Greptile Summary

Removes the providers.length check from the isSimple boolean expression, preventing duplicate LLM calls when messages contain URLs or trigger provider enrichment.

Key Changes:

  • Removed condition (!responseContent.providers || responseContent.providers.length === 0) from isSimple check at line 1883
  • Messages with actions: ["REPLY"] now correctly use the "simple" path regardless of provider presence
  • Providers still enrich state (lines 863-871) but no longer force re-generation of already-streamed responses

Impact:

  • Eliminates duplicate streaming when URLs are detected (previously triggered ATTACHMENTS provider → action path → second LLM call)
  • Reduces token costs by avoiding unnecessary second LLM invocation
  • Response text from first runSingleShotCore call is now correctly used as final output

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Simple, surgical fix that removes a single condition causing unintended behavior. The logic is sound: providers enrich state (already handled separately at L863-871) but shouldn't force action-based execution when the response is already generated and streamed. No new code paths, no breaking changes.
  • No files require special attention

Important Files Changed

Filename Overview
packages/typescript/src/services/message.ts Removed providers check from isSimple determination to prevent duplicate LLM calls when URLs trigger provider enrichment

Last reviewed commit: 681b3d8

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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

@greptile-apps greptile-apps 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 file reviewed, no comments

Edit Code Review Agent Settings | Greptile

…riggers providers

Remove providers length check from isSimple determination. Providers
enrich state (already handled at L863-871) but don't require
re-generating the response. The previous check incorrectly treated
"has providers" as "not simple", causing messages with URLs to go
through the actions path and trigger a second LLM call via the REPLY
action handler.

Relates to elizaOS#6486
@nicolasdma nicolasdma force-pushed the fix/duplicate-llm-calls-url-messages branch from 681b3d8 to 3a304b6 Compare February 23, 2026 12:02
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