Skip to content

fix(langchain): make write_todos calls tool-only to stop duplicated plan text#38132

Draft
Mason Daugherty (mdrxy) wants to merge 1 commit into
masterfrom
open-swe/write-todos-tool-only-text
Draft

fix(langchain): make write_todos calls tool-only to stop duplicated plan text#38132
Mason Daugherty (mdrxy) wants to merge 1 commit into
masterfrom
open-swe/write-todos-tool-only-text

Conversation

@mdrxy

Copy link
Copy Markdown
Member

When TodoListMiddleware drives an agent, some models (notably Claude Sonnet) emit user-facing plan text — e.g. Plan: ... Does this plan look good?before/alongside a write_todos tool call, and then emit nearly the same plan/question again after the tool result. Streaming consumers (like dcode) render both, so the user sees the same planning message twice.

This is a side effect of the contract added in #37643: that change told the model to land its substantive/user-facing answer after the final write_todos result (so the loop-terminating AIMessage isn't empty), but it never said not to also put that same plan/status/question before or in the same assistant message as the call. This PR closes that gap.

The default WRITE_TODOS_SYSTEM_PROMPT and WRITE_TODOS_TOOL_DESCRIPTION now spell out a boundary rule: a write_todos call updates todo state only — the assistant message containing the call must be tool-only, with no user-facing plan text, status updates, approval questions, or final answers. That content is sent once, after the tool result returns. The #37643 contract is preserved: substantive/final answers still land after the relevant write_todos result, not before it.

Before: model narrates the plan, calls write_todos, then repeats the plan after the result → duplicate. After: model calls write_todos tool-only, then sends the plan/question/answer once after the result.

Unit tests assert both default prompts contain the tool-only boundary language and still preserve the "answer after the call" contract.

Related: #37643

A note for transparency: this contribution was prepared with the help of an AI agent.

Made by Open SWE

… plan text

Add a boundary rule to the `TodoListMiddleware` default prompt and tool
description: when calling `write_todos`, the assistant message must be
tool-only. User-facing plan text, status updates, approval questions, and
final answers should not appear in the same message as the call — they are
sent once, after the tool result returns. This stops streaming consumers
from showing the same plan/question twice (before and after the call) while
preserving #37643's contract that the final answer lands after the call.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
@github-actions github-actions Bot added fix For PRs that implement a fix internal langchain `langchain` package issues & PRs size: XS < 50 LOC labels Jun 13, 2026
@mdrxy Mason Daugherty (mdrxy) marked this pull request as ready for review June 13, 2026 06:42

@open-swe open-swe Bot left a comment

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.

✅ Open SWE Review: No issues found

Open SWE reviewed this PR and found no potential bugs to report.

Open in WebView Open SWE trace

mohamedtaqysalmi

This comment was marked as spam.

@mdrxy Mason Daugherty (mdrxy) marked this pull request as draft July 6, 2026 05:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix For PRs that implement a fix internal langchain `langchain` package issues & PRs size: XS < 50 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants