feat(ai-chat): raise step limit to 20 and force a final answer #4

Closed
Ghost wants to merge 1 commits from feat/ai-chat-step-limit-and-forced-final-answer into develop

Problem

The agent's per-turn step ceiling was stepCountIs(8). On research-heavy questions the model spent all 8 steps on tool calls and the turn ended with empty text — the user saw no answer and had to nudge with ? to start a new turn. Real incident from a chat that triggered this plan.

Changes

  • Raise stopWhen from stepCountIs(8) to stepCountIs(MAX_AGENT_STEPS = 20) so multi-search research questions are not cut off mid-investigation.
  • Add a prepareStep option that, on the last allowed step (stepNumber === 19), forces toolChoice: 'none' and appends a synthesis instruction to the system prompt — the model must write the best text answer it can from what it already gathered, never an empty turn.
  • Earlier steps return undefined → default behaviour, so natural early termination is unaffected.
  • The base system prompt is concatenated with the instruction (a bare override would lose persona/context).
  • Logic extracted into a pure exported helper prepareAgentStep(stepNumber, system) for unit testing, mirroring the existing compactToolOutput pattern.

Out of scope (per plan)

  • Configurable limit per workspace — kept as a code constant for now.
  • UI badge 'answer from incomplete data' — possible later extension.

Note for future bumps

At AI SDK v7 the per-step system field is renamed to instructions; on v6 (^6.0.134) system is correct — noted in a code comment.

Verification

  • pnpm --filter server test -- ai-chat.service — 10/10 pass (existing compactToolOutput + assistantParts suites plus the new prepareAgentStep block: undefined for steps 0/1/5/10/18, {toolChoice:'none', system} at 19, system preserves the base prompt and contains the instruction marker, off-by-one pin).
  • pnpm --filter server lint — no new errors (only the pre-existing common/helpers/utils.ts:3 no-require-imports).
  • onFinish / onError / onAbort and the maxOutputTokens comment are untouched.
## Problem The agent's per-turn step ceiling was `stepCountIs(8)`. On research-heavy questions the model spent all 8 steps on tool calls and the turn ended with **empty text** — the user saw no answer and had to nudge with `?` to start a new turn. Real incident from a chat that triggered this plan. ## Changes - Raise `stopWhen` from `stepCountIs(8)` to `stepCountIs(MAX_AGENT_STEPS = 20)` so multi-search research questions are not cut off mid-investigation. - Add a `prepareStep` option that, on the **last** allowed step (`stepNumber === 19`), forces `toolChoice: 'none'` and appends a synthesis instruction to the system prompt — the model must write the best text answer it can from what it already gathered, never an empty turn. - Earlier steps return `undefined` → default behaviour, so natural early termination is unaffected. - The base system prompt is **concatenated** with the instruction (a bare override would lose persona/context). - Logic extracted into a pure exported helper `prepareAgentStep(stepNumber, system)` for unit testing, mirroring the existing `compactToolOutput` pattern. ## Out of scope (per plan) - Configurable limit per workspace — kept as a code constant for now. - UI badge 'answer from incomplete data' — possible later extension. ## Note for future bumps At AI SDK v7 the per-step `system` field is renamed to `instructions`; on v6 (`^6.0.134`) `system` is correct — noted in a code comment. ## Verification - `pnpm --filter server test -- ai-chat.service` — 10/10 pass (existing `compactToolOutput` + `assistantParts` suites plus the new `prepareAgentStep` block: undefined for steps 0/1/5/10/18, `{toolChoice:'none', system}` at 19, system preserves the base prompt and contains the instruction marker, off-by-one pin). - `pnpm --filter server lint` — no new errors (only the pre-existing `common/helpers/utils.ts:3 no-require-imports`). - `onFinish` / `onError` / `onAbort` and the `maxOutputTokens` comment are untouched.
Ghost added 1 commit 2026-06-20 04:54:00 +03:00
The agent's per-turn step ceiling was 8. On research-heavy questions the
model spent all 8 steps on tool calls and the turn ended with empty text
- the user saw no answer and had to nudge with '?'. Two fixes:

- Raise stopWhen from stepCountIs(8) to stepCountIs(MAX_AGENT_STEPS = 20).
- On the LAST allowed step (stepNumber 19), forbid further tool calls
  (toolChoice: 'none') and append a synthesis instruction to the system
  prompt, so the model is forced to write the best answer it can from
  what it already gathered.

prepareStep returns undefined for every earlier step, so natural early
termination and the maxOutputTokens comment are untouched. The base
system prompt is CONCATENATED with the instruction (a bare override
would lose the persona/context). Logic extracted into a pure, exported
prepareAgentStep(stepNumber, system) helper for unit testing.

NOTE for future bumps: at AI SDK v7 the per-step 'system' field is
renamed to 'instructions'; on v6 (`^6.0.134`) 'system' is correct.
Ghost closed this pull request 2026-06-20 22:26:28 +03:00

Pull request closed

Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#4