maxSteps of 0 silently disables the agent's step cap
- Dominant language
- Scala
- Stars
- 314
- Forks
- 187
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 214
Description
### What happened?
`TexeraAgent` caps its ReAct loop with `stopWhen: stepCountIs(this.settings.maxSteps)` ([texera-agent.ts:529](https://github.com/apache/texera/blob/main/agent-service/src/agent/texera-agent.ts#L529)). In `ai@7.0.48` that predicate is an **equality** test, not a ceiling:
```js
// 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:
```ts
// 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](https://github.com/apache/texera/blob/main/agent-service/src/server.ts#L244)) 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.
Contributor guide
Assessment
This issue has not been assessed yet.