Skip to the demo
Demos

Streaming @task

Click Generate: the text below fills in word-by-word as the server writes the field in a loop. That's @task streaming field-level diffs — no flow:stream element, no re-render per chunk. Cancel aborts it mid-run.

streaming…
@expose answer = "";

@task async generate() {   // streams field writes as they happen
  this.answer = "";
  for await (const token of llm.stream(this.prompt, { signal: this.signal })) {
    if (this.cancelled) break;
    this.answer += token;   // → streams to the browser live
  }
}

<button onClick={this.generate} loadingAttr="disabled">Generate</button>
<button onClick={() => $flow.cancel()} showOnLoading>Cancel</button>
// bind the field reactively — updates token-by-token, no per-chunk re-render
<div text={this.answer} />