cloudflare / cloudflare/agents
useAgentChat: getInitialMessages fetches the previous instance on `name` change (socket URL lags one render)
- Dominant language
- TypeScript
- Stars
- 5.6k
- Forks
- 711
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 53
Description
### Which SDK / package
`agents` (react) + `@cloudflare/ai-chat` (react) — `useAgent` + `useAgentChat`.
### Version
`agents@0.17.3`, `@cloudflare/ai-chat@0.9.3` (latest at time of writing).
### Summary
When an app switches the agent instance by **changing the `name` passed to `useAgent`** (e.g. switching between chat conversations, where each conversation is a distinct DO instance), `useAgentChat` fetches `get-messages` for the **previous** instance, not the new one. The target instance's history never loads.
Root cause: the initial-messages URL is derived from the live socket, and the socket lags the `name` prop by one render.
### Root cause
- `useAgentChat`'s `defaultGetInitialMessagesFetch` builds the request from `agentUrlString` (the agent's socket URL): `getMessagesUrl = new URL(url); getMessagesUrl.pathname += "/get-messages"`.
- That `url` comes from the socket returned by `useAgent` → `usePartySocket` → `useStableSocket`, where the socket is held in `useState` and replaced via `setSocket` inside an effect when the memo key changes.
- So on the render where `name` changes, `useAgent` still returns the **old** socket (the `setSocket` for the new one runs in a later commit). Its URL still points at the previous instance.
- `useAgentChat` creates the `getInitialMessages` promise during that same render (consumed via `use(promise)`), so it fetches `.../agents///get-messages` → 404/empty for the intended instance.
- `GetInitialMessagesOptions` only exposes `{ agent, name, url }`, and `name` there is `agent.name` (identity-derived, also lagged), so a custom `getInitialMessages` override can't get the intended target name from the options either — it has to reach outside the SDK for the current `name` prop.
### Reproduction
1. Mount `useAgent({ agent: "ChatAgent", name })` + `useAgentChat({ agent })` once.
2. Change `name` from instance A to instance B (both have persisted history), e.g. inside a `startTransition`.
3. Observe the network: `get-messages` is requested for instance **A** (or a stale id), not **B**. B's history never loads.
The official docs only ever show a **stable** `name` (`name: userId`), so this path isn't covered by examples — but changing `name` is otherwise supported (the socket re-keys on `addressKey`).
### Impact
Any app that reuses one mounted `useAgentChat` across multiple agent instances (a very natural "chat session switcher" UX) silently loads the wrong instance's history on switch.
### Suggested fix
Derive the `get-messages` URL / `name` passed to `getInitialMessages` from the **current `name` prop** (synchronous) rather than the lagged socket URL — e.g. compute the messages URL from `options.name`/`host` the same way `getAgentMessages` does, instead of from `agent.url`. At minimum, pass the intended (prop-derived) `name` into `GetInitialMessagesOptions` so overrides can build a correct URL without reaching outside the SDK.
### Workaround (for others hitting this)
Pass a custom `getInitialMessages` that ignores the SDK-provided `url`/`name` and builds the request from your own source-of-truth session id (the value you pass as `name`), not from the socket.
Contributor guide
Assessment
This issue has not been assessed yet.