Skip to main content

Cancel a run

A run in flight can be aborted with cancel() — on the session, or on the KoelChatController in Flutter. Cancellation is fire-and-forget by contract: it returns immediately and a stalled transport can never hang it.

final session = client.newSession();

// Start a run but do not await it.
final pending = session.send('Write a very long essay');

// Later — a stop button, a navigation away, a timeout:
session.cancel();

In Flutter, the controller forwards it:

ElevatedButton(
onPressed: controller.isStreaming ? controller.cancel : null,
child: const Text('Stop'),
);

What cancel guarantees​

  • Sub-budget teardown. The transport socket is torn down within the abort budget (NFR-8) — not whenever the stream generator next wakes.
  • No event escapes post-cancel. Once cancelled, no further AgUiEvent reaches your listeners, even from a backend that keeps sending.
  • It can never hang. cancel() does not await the teardown, so a backend that ignores the abort cannot block your UI.

This is the koel house cancel-correct stream teardown pattern — read it if you are writing your own transport or adapter, where you must implement the same guarantees.

Disposal cancels too​

Disposing the controller (or the client) cancels any run in flight as part of teardown — you do not need a separate cancel() before dispose(). The widget that creates the controller is the one that disposes it.