Skip to content

fix: rewrite repeated tool call reminders to redirect instead of prohibit - #1518

Merged
RealKai42 merged 1 commit into
mainfrom
kaiyi/beijing-v2
Jul 9, 2026
Merged

fix: rewrite repeated tool call reminders to redirect instead of prohibit#1518
RealKai42 merged 1 commit into
mainfrom
kaiyi/beijing-v2

Conversation

@RealKai42

Copy link
Copy Markdown
Collaborator

Related Issue

None — the problem is explained below.

Problem

When the agent repeats the exact same tool call, the turn loop appends a <system-reminder> to the repeated tool result at streaks 3/5/8 (and force-stops the turn at 12). Two aspects of the current wording work against the goal:

  • All three tiers open with prohibition verdicts ("You are repeating the exact same tool call…", "Do not call this exact same tool with the exact same arguments again", "Stop all function calls immediately"). Anti-repeat interventions are far less reliable as bare prohibitions than as concrete substitute actions — a "don't do X" instruction gives the model nothing to do next and keeps X as the most salient thing in context.
  • Tier 2 echoes the repeated call's tool name, count, and full arguments back into the model's context. Repetition probability rises with every copy of a pattern present in the context, so the reminder replays the very call it wants suppressed. The reminders also persist in history, so by a streak of N the pattern has been restated at least 2N times across tool results and reminders.

Net effect: the reminder meant to break a loop instead keeps the loop's target maximally salient.

What changed

Rewrote the three reminder texts (r1/r2/r3) in the tool-repeat dedup logic so each tier states the situation factually and hands the model a concrete next action, mirroring the "tell the model what to do, not what to avoid" guidance:

  • r1 (streak 3–4): drops the verdict; states the fact, then asks the model to write one sentence declaring what new information the next call is expected to produce, and to act on that sentence — or continue with the evidence already gathered.
  • r2 (streak 5–7): keeps only the repeat count (tool name and arguments are no longer echoed) and forces an explicit choice among three concrete options: (1) run the cheapest falsification check of the current approach, (2) tell the user exactly what information or decision is needed and ask for it, (3) conclude with the evidence already gathered.
  • r3 (streak 8–11): replaces the bare "stop all function calls" with a final hand-off task — write the final response now (without further tool calls) covering the blocker, what each attempted approach established, and what is needed from the user. The streak-12 force-stop remains as the hard guarantee, so the softer voice is safe.

Deliberately out of scope: detection logic, thresholds (3/5/8/12), same-step dedup, force-stop behavior, and telemetry are all unchanged. makeReminderText2(toolName, repeatCount, args) is simplified to makeReminderText2(repeatCount) since the tool name and arguments are no longer injected.

Tests: assertions in tool-dedup.test.ts were updated to pin the new wording, including negative checks that tier texts do not leak into one another. 35 tool-dedup unit tests and 58 turn integration tests pass; typecheck and lint are clean.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

…ibit

The r1/r2/r3 reminders injected into repeated tool results led with
prohibition verdicts and, in r2, echoed the repeated tool name and full
arguments back into the context, reinforcing the very pattern they were
meant to break. Rewrite them to state the situation factually and hand
the model a concrete next action: an expectation-setting sentence for
the next call (r1), a forced decision menu of falsify / ask-user /
conclude (r2), and a final hand-off summary without further tool calls
(r3). Detection, thresholds (3/5/8/12), force-stop, and telemetry are
unchanged.
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 9950775

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 9, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@9950775
npx https://pkg.pr.new/@moonshot-ai/kimi-code@9950775

commit: 9950775

@RealKai42
RealKai42 merged commit fe9479d into main Jul 9, 2026
11 checks passed
@RealKai42
RealKai42 deleted the kaiyi/beijing-v2 branch July 9, 2026 09:06
7723qqq pushed a commit to 7723qqq/kimi-code that referenced this pull request Jul 11, 2026
…ibit (MoonshotAI#1518)

The r1/r2/r3 reminders injected into repeated tool results led with
prohibition verdicts and, in r2, echoed the repeated tool name and full
arguments back into the context, reinforcing the very pattern they were
meant to break. Rewrite them to state the situation factually and hand
the model a concrete next action: an expectation-setting sentence for
the next call (r1), a forced decision menu of falsify / ask-user /
conclude (r2), and a final hand-off summary without further tool calls
(r3). Detection, thresholds (3/5/8/12), force-stop, and telemetry are
unchanged.
sailist added a commit to sailist/kimi-code that referenced this pull request Jul 13, 2026
…th v1

- rewrite repeated tool call reminders to redirect instead of prohibit (port of v1 MoonshotAI#1518)
- simplify makeReminderText2 to (repeatCount), no longer echoing tool name and args
- treat dismissed AskUserQuestion as no answer, not the recommended pick (port of v1 MoonshotAI#1550)
- update toolDedupe test assertions and regenerate affected wire snapshots
sailist added a commit that referenced this pull request Jul 13, 2026
… with v1 (#1631)

* fix(agent-core-v2): surface provider rejection on post-refresh 401

- map a 401 that survives forced token refresh to PROVIDER_AUTH_ERROR
  carrying the provider's sanitized message, instead of a misleading
  AUTH_LOGIN_REQUIRED re-login prompt
- propagate provider auth errors through full compaction instead of
  wrapping them as compaction failure
- export sanitizeStatusErrorMessage for reuse

* fix(agent-core-v2): align repeat-reminder and AskUserQuestion copy with v1

- rewrite repeated tool call reminders to redirect instead of prohibit (port of v1 #1518)
- simplify makeReminderText2 to (repeatCount), no longer echoing tool name and args
- treat dismissed AskUserQuestion as no answer, not the recommended pick (port of v1 #1550)
- update toolDedupe test assertions and regenerate affected wire snapshots

* chore: add changeset for v2 reminder and question copy alignment

* fix(kap-server): drain in-flight heartbeat writes before unlinking the instance file

- count writes that passed the released check and await them in release()
  so their atomic rename cannot recreate the file after unlink
- harden the heartbeat test: 1ms cadence plus a post-release re-check
  catches the recreate-after-unlink race (verified failing on old code)

* docs(agent-core-v2): move toProviderAuthError rationale to the file header

Address Codex review: agent-core-v2 keeps comments in the top-of-file
header only, never beside functions
jannes-apollo added a commit to jannes-apollo/inspect_swe that referenced this pull request Jul 16, 2026
- mcp.json: translate http/sse MCP servers natively (fixes bridged_tools,
  which arrive as MCPServerConfigHTTP), honor stdio cwd, and map
  MCPServerConfig.tools -> kimi enabledTools
- repeat-reminder strip: match kimi's actual reminder texts in both wordings
  (rewritten in kimi-code 0.23.4, MoonshotAI/kimi-code#1518); strip escalation
  tiers 1-2 only, keeping the tier-3 "write your final response" reminder that
  precedes kimi's forced turn stop; document the behavior in kimi_code.qmd
- move the tool_call_id dedupe into the bridge filter (pre-generation) so
  rewritten ids land in recorded ModelEvents and live provider requests, not
  just the returned state; make the rewrite idempotent across bridge retries
- dispatch legacy str-first GenerateFilters with model.name, mirroring the
  bridge's own annotation-based dispatch
- centaur: don't bake --output-format text into the interactive alias (kimi
  rejects it outside prompt mode)
- raise at resolution time on musl platforms (kimi publishes glibc-only linux
  builds); document glibc+bash sandbox requirements
- escape user-supplied strings in config.toml via _format_value
- tests: cover the above; drop redundant patch in unknown-platform test

Co-Authored-By: Claude
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