fix(core): Fix agent loop continuing after cancellation in letta_agent_v3 [LET-6006] (#5905)

* Fix agent loop continuing after cancellation in letta_agent_v3

Bug: When a run is cancelled, _check_run_cancellation() sets
self.should_continue=False and returns early from _step(), but the outer
for loop (line 245) continues to the next iteration, executing subsequent
steps even though cancellation was requested.

Symptom: User hits cancel during step 1, backend marks run as cancelled,
but agent continues executing steps 2, 3, etc.

Root cause: After the 'async for chunk in response' loop completes (line 255),
there was no check of self.should_continue before continuing to the next
iteration of the outer step loop.

Fix: Added 'if not self.should_continue: break' check after the inner loop
to exit the outer step loop when cancellation is detected. This makes v3
consistent with v2 which already had this check (line 306-307).

🐾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>

* add integration tests

* fix: misc fixes required to get cancellations to work on letta code localhost

---------

Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: Sarah Wooders <sarahwooders@gmail.com>
This commit is contained in:
Charles Packer
2025-11-02 19:47:31 -08:00
committed by Caren Thomas
parent a44c05040a
commit a6077f3927
6 changed files with 236 additions and 8 deletions

View File

@@ -1114,6 +1114,10 @@ def safe_create_task(coro, label: str = "background task"):
try:
await coro
except Exception as e:
# Don't log RunCancelledException as an error - it's expected when streams are cancelled
if e.__class__.__name__ == "RunCancelledException":
logger.info(f"{label} was cancelled (RunCancelledException)")
return
logger.exception(f"{label} failed with {type(e).__name__}: {e}")
task = asyncio.create_task(wrapper())