Skip to content

fix(cli): auto-continue max iterations in --yolo mode#1737

Open
frntn wants to merge 4 commits intodocker:mainfrom
frntn:frntn/yolo-auto-continue-max-iterations
Open

fix(cli): auto-continue max iterations in --yolo mode#1737
frntn wants to merge 4 commits intodocker:mainfrom
frntn:frntn/yolo-auto-continue-max-iterations

Conversation

@frntn
Copy link

@frntn frntn commented Feb 15, 2026

Problem

When running cagent exec --yolo in non-interactive mode (stdin closed/piped),
hitting the max iterations limit triggers a stdin prompt that immediately fails
with "Failed to read input, exiting...".

This is inconsistent: --yolo auto-approves tool calls but not iteration extensions.

Fix

  • Auto-approve iteration extensions in --yolo mode (capped at 5 to prevent infinite loops)
  • Handle MaxIterationsReachedEvent in JSON output mode (was completely missing, causing runtime hang)
  • Extract shared logic into handleMaxIterationsAutoApprove helper to avoid duplication between normal and JSON paths

Test plan

  • 5 new tests covering: yolo auto-approve, safety cap, JSON mode, reject without yolo, JSON safety cap
  • golangci-lint run ./pkg/cli/... → 0 issues
  • go test ./pkg/cli/... → 16/16 PASS

When running in non-interactive mode with --yolo (e.g. `cagent exec
--yolo`), reaching max_iterations triggers a stdin prompt that fails
immediately with "Failed to read input, exiting..." since stdin is
piped or closed.

This fix proposal makes --yolo consistent: it now auto-approves
iteration extensions just like it auto-approves tool calls. A safety
cap of 5 extensions (+50 iterations) prevents infinite loops.

TL;DR : in --yolo mode, cagent now auto-approve the "max-iterations"
continuation (up to 5 times) instead of prompting stdin (which fails
immediately in non-interactive/piped contexts)

Signed-off-by: Matthieu FRONTON <m@tthieu.fr>
The JSON event loop (`--json`) did not handle MaxIterationsReachedEvent
at all, causing the runtime to hang on resumeChan indefinitely. Apply
the same auto-continue logic as the normal output path: auto-approve
in --yolo mode (with safety cap), reject otherwise.

Signed-off-by: Matthieu FRONTON <m@tthieu.fr>
Cover --yolo auto-continue behavior for MaxIterationsReachedEvent in
both normal and JSON output modes, including safety cap enforcement.

Signed-off-by: Matthieu FRONTON <m@tthieu.fr>
Deduplicate MaxIterationsReachedEvent logic between JSON and normal
output modes into a single helper with a ternary return type
(continue/stop/prompt).

Signed-off-by: Matthieu FRONTON <m@tthieu.fr>
@frntn frntn requested a review from a team as a code owner February 15, 2026 01:21
@krissetto
Copy link
Contributor

I'm not really sure of this.. The max iterations feature was designed exactly for this purpose, to not iterate forever. Auto approving that confirmation prompt silently when using --yolo could lead to unexpected (and potentially very expensive) consequences for the user.

IMHO a better approach is just to set --max-iterations 999 or some other very high value, so at least what's happening is explicitly chosen by the user. WDYT?

@frntn
Copy link
Author

frntn commented Feb 17, 2026

Thanks for the review @krissetto

I had the same initial thought, but while running benchmarks on multiple coding agents using harbor framework (including cagent, which turns out to be one of my fav) I realized two things :

  1. bumping max-iterations is workaround, the bug remains that if the agent reaches that limit in non-interactive mode, the runtime tries to prompt a user that doesn't exist and crashes
  2. It's a consistency fix for yolo semantics which already auto-approves tool calls. I opted for full auto-approve, but one specific prompt still requires manual input (and breaks when there's no interactive terminal). That's not a safety net but a bug as I cannot reply "yes". The fix aligns the behavior with yolo semantic which means "auto-approve everything". A safety cap still prevents runaways

Bonus: This PR also fixes the JSON output mode, which was completely missing handling for MaxIterationsReachedEvent and caused a runtime hang.

Does that make more sense to you?
It's really a practical fix from what I experienced and expected, not some theoretical one :)

@krissetto
Copy link
Contributor

@frntn I do agree it could be nice, just not totally sure its the right move. If we go with it, we need to document the behavior properly too both in the --yolo and --max-iteration sections to make it very clear to users.

Agree we need to handle the exec command better in non-interactive scenarios though.

To be clear, I'm not strongly against the change. Let me stew on it just a bit and get back to you

@frntn
Copy link
Author

frntn commented Feb 17, 2026

Maybe using a proper wording in the description like "soft-limit" and "hard-limit" can help

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.

2 participants