agents-0-22-0-11-b
Claude Code's read-only tools, web search on, ludion sync off
Question
How do I make useAgentChat update the UI on every token?
Answer key
- A correct answer says
- `useAgentChat` throttles UI updates to every 50ms by default; pass `throttle: false` to render every chunk or a number to change the interval.
- The stale answer
- useAgentChat re-renders on every streamed chunk unless you set `experimental_throttle`.
Answer
Pass `throttle: false` to `useAgentChat`:
```ts
const chat = useAgentChat({ agent, throttle: false });
```
By default, the installed `agents` package groups chat state updates into one re-render every 50 ms. The first chunk is never delayed. Setting `throttle: false` re-renders on every streamed chunk as it arrives (`node_modules/agents/dist/chat/react.d.ts:251-260`). Each chunk is usually a token or a small text delta. You can also pass a smaller number of milliseconds, like `throttle: 10`, if re-rendering on every chunk turns out to be too heavy. `experimental_throttle` is deprecated in favor of `throttle`.Grade
correct
The judge's reason: It says the default is a 50ms throttle, that throttle: false renders every chunk, and that a number changes the interval, and it doesn't present the stale behavior as current.
Session log
Tool call: Grep
{ "pattern": "useAgentChat|throttle", "output_mode": "content", "head_limit": 30 }Tool output
node_modules\rolldown\dist\shared\create-bundler-option-2b9QJDoZ.mjs:1999: throttle: 1e3, node_modules\rolldown\dist\shared\create-bundler-option-2b9QJDoZ.mjs:2000: throttleMin: 5, node_modules\rolldown\dist\shared\create-bundler-option-2b9QJDoZ.mjs:2239: const repeated = (this._lastLog.count || 0) - this.options.throttleMin; node_modules\rolldown\dist\shared\create-bundler-option-2b9QJDoZ.mjs:2257: if (diffTime < this.options.throttle) try { node_modules\rolldown\dist\shared\create-bundler-option-2b9QJDoZ.mjs:2267: if (this._lastLog.count > this.options.throttleMin) { node_modules\rolldown\dist\shared\create-bundler-option-2b9QJDoZ.mjs:2268: this._lastLog.timeout = setTimeout(resolveLog, this.options.throttle); node_modules\wrangler\wrangler-dist\cli.js:163067: "Asset upload concurrency throttled to 1 after a gateway error." node_modules\wrangler\wrangler-dist\cli.js:183398: if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file3, 5)) node_modules\wrangler\wrangler-dist\cli.js:183433: if (!this.fsw._throttle(EV.ADD, file3, 0)) node_modules\wrangler\wrangler-dist\cli.js:183482: _handleRead(directory, initialAdd, wh, target, dir2, depth, throttler) { node_modules\wrangler\wrangler-dist\cli.js:183484: throttler = this.fsw._throttle("readdir", directory, 1e3); node_modules\wrangler\wrangler-dist\cli.js:183485: if (!throttler) node_modules\wrangler\wrangler-dist\cli.js:183524: const wasThrottled = throttler ? throttler.clear() : false; node_modules\wrangler\wrangler-dist\cli.js:183533: this._handleRead(directory, false, wh, target, dir2, depth, throttler); node_modules\wrangler\wrangler-dist\cli.js:183556: let throttler; node_modules\wrangler\wrangler-dist\cli.js:183561: await this._handleRead(dir2, initialAdd, wh, target, dir2, depth, throttler); node_modules\wrangler\wrangler-dist\cli.js:183568: this._handleRead(dirPath, false, wh, target, dir2, depth, throttler); node_modules\wrangler\wrangler-dist\cli.js:183866: this._throttled = /* @__PURE__ */ new Map(); node_modules\wrangler\wrangler-dist\cli.js:184033: this._throttled.clear(); node_modules\wrangler\wrangler-dist\cli.js:184118: const isThrottled = !this._throttle(EVENTS.CHANGE, path107, 50); node_modules\wrangler\wrangler-dist\cli.js:184149: * @param actionType type being throttled node_modules\wrangler\wrangler-dist\cli.js:184154: _throttle(actionType, path107, timeout2) { node_modules\wrangler\wrangler-dist\cli.js:184155: if (!this._throttled.has(actionType)) { node_modules\wrangler\wrangler-dist\cli.js:184156: this._throttled.set(actionType, /* @__PURE__ */ new Map()); node_modules\wrangler\wrangler-dist\cli.js:184158: const action = this._throttled.get(actionType); node_modules\wrangler\wrangler-dist\cli.js:184160: throw new Error("invalid throttle"); node_modules\wrangler\wrangler-dist\cli.js:184297: if (!this._throttle("remove", path107, 100)) node_modules\workerd\worker.mjs:388:[Omitted long matching line] node_modules\workerd\worker.mjs:397:[Omitted long matching line] node_modules\workerd\worker.mjs:404:[Omitted long matching line] [Showing results with pagination = limit: 30]Tool call: Grep
{ "pattern": "throttle|Throttle", "path": "node_modules/@cloudflare/ai-chat", "output_mode": "content", "head_limit": 30 }Tool output (error)
Path does not exist: node_modules/@cloudflare/ai-chat. Note: your current working directory is C:\Users\haya0\AppData\Local\Temp\ludion-bench-l4vkWh\work.Tool call: Grep
{ "pattern": "useAgentChat", "path": "node_modules", "glob": "*.d.ts", "head_limit": 10 }Tool output
Found 4 files node_modules\agents\dist\ws-chat-transport-BbT1A5Lc.d.ts node_modules\agents\dist\socket-address.d.ts node_modules\agents\dist\react.d.ts node_modules\agents\dist\chat\react.d.tsTool call: Grep
{ "pattern": "throttle|Throttle|UseAgentChatOptions|experimental_", "path": "node_modules/agents/dist/chat/react.d.ts", "output_mode": "content", "-C": 4 }Tool output
222-}) => void | Promise<void>; 223-/** 224- * Options for the useAgentChat hook 225- */ 226:type UseAgentChatOptions< 227- State = unknown, 228- ChatMessage extends UIMessage = UIMessage 229-> = Omit< 230- UseChatParams<ChatMessage>, 231: "fetch" | "onToolCall" | "throttle" | "experimental_throttle" 232-> & { 233- /** Agent connection from useAgent (accepts both typed and untyped agents) */ agent: AgentConnection & { 234- agent: string; 235- name: string; -- 251- /** 252- * Milliseconds to coalesce chat state updates before re-rendering, 253- * defaulting to 50. 254- * 255: * Streaming writes chat state once per chunk, so without a throttle a fast 256- * burst of chunks renders once per chunk. The first chunk is never delayed. 257- * Pass `false` to render every chunk as it arrives. 258- */ 259: throttle?: number | false /** @deprecated Use `throttle`. */; 260: experimental_throttle?: number; 261- /** 262- * Callback for handling client-side tool execution. 263- * Called when a tool without server-side `execute` is invoked by the LLM. 264- * It fires once the response stream ends, for each tool call still waiting -- 303- * @deprecated Use `onToolCall` callback instead for automatic tool execution. 304- * @description Whether to automatically resolve tool calls that do not require human interaction. 305- * @experimental 306- */ 307: experimental_automaticToolResolution?: boolean; 308- /** 309- * Tools that can be executed on the client. Tool schemas are automatically 310- * sent to the server and tool calls are routed back for client execution. 311- * -- 421-declare function useAgentChat< 422- State = unknown, 423- ChatMessage extends UIMessage = UIMessage 424->( 425: options: UseAgentChatOptions<State, ChatMessage> 426-): Omit<ReturnType<typeof useChat<ChatMessage>>, "addToolOutput"> & { 427- clearHistory: () => void; 428- /** 429- * Provide output for a tool call. Use this for tools that require user interaction -- 486- JSONSchemaType, 487- OnToolCallCallback, 488- PrepareSendMessagesRequestOptions, 489- PrepareSendMessagesRequestResult, 490: UseAgentChatOptions, 491- WebSocketChatTransport, 492- type WebSocketChatTransportOptions, 493- detectToolsRequiringConfirmation, 494- extractClientToolSchemas,Agent
Pass `throttle: false` to `useAgentChat`: ```ts const chat = useAgentChat({ agent, throttle: false }); ``` By default, the installed `agents` package groups chat state updates into one re-render every 50 ms. The first chunk is never delayed. Setting `throttle: false` re-renders on every streamed chunk as it arrives (`node_modules/agents/dist/chat/react.d.ts:251-260`). Each chunk is usually a token or a small text delta. You can also pass a smaller number of milliseconds, like `throttle: 10`, if re-rendering on every chunk turns out to be too heavy. `experimental_throttle` is deprecated in favor of `throttle`.