Skip to content

maxSteps of 0 silently disables the agent's step cap #7484

Description

@aglinxinyuan

What happened?

TexeraAgent caps its ReAct loop with stopWhen: stepCountIs(this.settings.maxSteps) (texera-agent.ts:529). In ai@7.0.48 that predicate is an equality test, not a ceiling:

// node_modules/ai/dist/index.js:4655
function isStepCount(stepCount) {
  return ({ steps }) => steps.length === stepCount;
}

It is evaluated after a step has run, so steps.length is always at least 1. With maxSteps: 0 the predicate is therefore never satisfied and the cap is silently disabled — a model that keeps emitting tool calls is never stopped by it. (A model that returns a plain text answer still terminates, because the loop ends on its own when there are no tool calls to service. The failure needs a tool-calling model, which is the normal case here.)

Nothing rejects the value. updateSettings assigns it unchecked:

// texera-agent.ts:379
if (updates.maxSteps !== undefined) {
  this.settings.maxSteps = updates.maxSteps;
}

and the HTTP settings endpoint declares it as maxSteps: t.Optional(t.Number()) (server.ts:244) with no minimum, so any client can turn the cap off. The default is 100, so this only bites when a value is supplied.

Negative values have the same problem for the same reason.

How to reproduce?

  1. Start the agent service and connect a client.
  2. Update the agent settings with maxSteps: 0 (accepted — no validation rejects it).
  3. Send a message that leads the model to keep calling tools.
  4. The loop is never stopped by the step cap.

Reproducing it in a unit test is possible but do not add one: because the run never ends, the test hangs the suite rather than failing it. This surfaced while writing coverage for sendMessage, and it is noted in that spec so nobody tries.

Version/Branch

1.3.0-incubating-SNAPSHOT (main)

Expected behavior

maxSteps should be validated at both boundaries — rejected at the API schema (t.Number({ minimum: 1 })) and clamped or rejected in updateSettings — so the cap cannot be disabled by configuration. Alternatively stopWhen should use a >= comparison rather than the SDK's equality predicate, which would also make the cap robust to a step count that overshoots.

Additional context

Found while raising texera-agent.ts coverage from 51% to 99.8%. The reachable-but-untestable nature of this path is the reason no regression test accompanies the report.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions