You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#7657 ("fix(react-core): wait for thread replay before sending prompts") added a guard in CopilotChat.tsx's waitForActiveRunToSettle that awaits pendingConnectionsRef.current.get(agent) — a promise wrapping agent.connect() — before allowing a new submission, specifically to prevent sending while a saved conversation is still replaying.
This doesn't help for agents built on @ag-ui/client's generic AbstractAgent/HttpAgent (e.g. @ag-ui/crewai's CrewAIAgent) that never override connect(). AbstractAgent.connect() is:
— always throws — and connectAgent()'s own catchError specifically swallows exactly that exception type, resolving the connection promise to an already-complete empty observable almost instantly. So the new guard has nothing real to await for this agent type: it resolves before any actual history replay has happened.
Repro
A CopilotKit app registers an @ag-ui/crewaiCrewAIAgent (or any other HttpAgent subclass that doesn't override connect()) as its agent, talking to a backend with a saved multi-turn conversation.
Reload the page / revisit an existing thread with history.
Immediately (before the replayed history visibly finishes rendering) type and send a new message.
The PR's own description scopes it to "Intelligence proxies" (ProxiedCopilotRuntimeAgent) hydrating through a delegate whose completion isn't otherwise visible — validated against "a real FastAPI/LangGraph SQLite backend." That's a narrower agent architecture than the generic AG-UI HttpAgent path. For HttpAgent-based agents, connectAgent() is a confirmed no-op (see above), so the new pendingConnectionsRef-based guard introduced in that PR never actually waits on this path's real replay work — whatever mechanism this agent type actually uses to load history isn't observed by the new guard at all.
Suggested direction
waitForActiveRunToSettle would need to also account for a replay that happens via an actual run (RUN_STARTED → ... → RUN_FINISHED), not only via connect()/connectAgent() — e.g. also awaiting agent.isRunning/activeRunCompletionPromise settling for whatever triggers the initial history load for a resolved threadId, regardless of whether that agent type implements connect().
⚠️ This is an AI-generated response. We've escalated this to our engineering team — someone will follow up in this thread shortly.
Engineering will need to verify this — the analysis is detailed and the scoping question about whether waitForActiveRunToSettle's pendingConnectionsRef guard covers the HttpAgent/AbstractAgent replay path is exactly the kind of thing that requires running the code.
What I can confirm from the source in context: waitForActiveRunToSettle in packages/react-core/src/v2/components/chat/CopilotChat.tsx does have a second guard — after the pendingConnectionsRef await — that checks agent.isRunning && activeRunCompletionPromise and awaits it (source, lines 862–873). If the initial history replay for HttpAgent-based agents fires as a real RUN_STARTED → RUN_FINISHED sequence and sets agent.isRunning = true before waitForActiveRunToSettle is called, that second guard would catch it. Whether agent.isRunning is reliably true at the moment a user submits during early replay — i.e., whether there's a window between the run starting and isRunning being observable — is the open question your report raises, and that's what the team will need to verify against the actual HttpAgent lifecycle.
🤖 Generated by CopilotKit AI Support · Documentation
Activity
copilotkit-outpost-bot commentedon Oct 7, 2026
Engineering will need to verify this — the analysis is detailed and the scoping question about whether
waitForActiveRunToSettle'spendingConnectionsRefguard covers theHttpAgent/AbstractAgentreplay path is exactly the kind of thing that requires running the code.What I can confirm from the source in context:
waitForActiveRunToSettleinpackages/react-core/src/v2/components/chat/CopilotChat.tsxdoes have a second guard — after thependingConnectionsRefawait — that checksagent.isRunning && activeRunCompletionPromiseand awaits it (source, lines 862–873). If the initial history replay forHttpAgent-based agents fires as a realRUN_STARTED → RUN_FINISHEDsequence and setsagent.isRunning = truebeforewaitForActiveRunToSettleis called, that second guard would catch it. Whetheragent.isRunningis reliablytrueat the moment a user submits during early replay — i.e., whether there's a window between the run starting andisRunningbeing observable — is the open question your report raises, and that's what the team will need to verify against the actualHttpAgentlifecycle.🤖 Generated by CopilotKit AI Support · Documentation
Was this helpful? React with 👍 or 👎