Two findings from your dep dump:
1. You have two copies of @langchain/langgraph-sdk (1.5.5 + 1.9.22). Fix this first. @langchain/react@1.0.23 depends on the SDK, and the useStream hook, the transport (HttpAgentServerAdapter), and message reconciliation all live inside that package. Two copies = two module instances; a transport/client built from one version handed to a hook bound to the other → identity + values.messages reconciliation break, which looks exactly like “state wiped on submit.” Force one version:
"overrides": { "@langchain/langgraph-sdk": "1.9.22" } // pnpm: "resolutions" for yarn
rm -rf node_modules package-lock.json && npm install
npm ls @langchain/langgraph-sdk # must show ONE version, all deduped
2. “Will migrating to the React SDK fix it?” - no, not by itself. Old langchain/sdk and new @langchain/react useStream consume the same server contract. Durability comes from the backend (checkpointed thread state replayed in full each turn), not from the frontend package. Do migrate - but pair it with a real backend.
You already have langgraph-cli + langgraph-api, so just run the server:
langgraph dev # → http://localhost:2024
useStream({ apiUrl: "http://localhost:2024", assistantId: "agent" })
That’s why the official server URL works - it persists thread state and replays the full message list.
Caveat: langgraph-runtime-inmem keeps state in process memory - fine for dev, but lost on restart and across workers/serverless. For production back it with Postgres (@langchain/langgraph-checkpoint-postgres, which you already had in your other project).
If you insist on your own custom HTTP endpoint: use useStream({ transport: { stream } }) + toLangGraphEventStreamResponse(...), and emit the full values.messages snapshot every turn with stable IDs - a partial snapshot is treated as an explicit removal.