fix(react-core): honor threadId prop on useAgent#6141
Open
davidmckayv wants to merge 1 commit into
Open
fix(react-core): honor threadId prop on useAgent#6141davidmckayv wants to merge 1 commit into
davidmckayv wants to merge 1 commit into
Conversation
UseAgentProps had no `threadId`, yet the shipped V2 React Native demo
calls `useAgent({ agentId: "default", threadId })`. Because the prop
didn't exist, it was silently dropped: the demo's thread state (and its
"New Chat" reset) never reached the agent, which ran under its own
auto-minted UUID. threadId was only ever sourced from a surrounding
`CopilotChatConfigurationProvider`, which the headless RN demo has none.
Accept an optional `threadId` on UseAgentProps and honor it. Resolution
precedence: an explicit `threadId` prop wins; otherwise fall back to the
chat configuration's threadId (gated on hasExplicitThreadId, as before).
When the prop is omitted, behavior is unchanged — fully backward
compatible. This makes the RN demo's existing usage work and unblocks
headless callers that have no chat-configuration provider in the tree.
Extends the threadId-propagation contract test with coverage for the
prop path (no provider, prop-over-config precedence, prop re-sync).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
davidmckayv
requested review from
jpr5,
marthakelly,
mme,
ranst91 and
tylerslaton
as code owners
July 23, 2026 21:55
@copilotkit/a2ui-renderer
@copilotkit/agentcore-runner
@copilotkit/angular
@copilotkit/channels
@copilotkit/channels-core
@copilotkit/channels-discord
@copilotkit/channels-intelligence
@copilotkit/channels-slack
@copilotkit/channels-teams
@copilotkit/channels-telegram
@copilotkit/channels-ui
@copilotkit/channels-whatsapp
@copilotkit/core
@copilotkit/react-core
@copilotkit/react-native
@copilotkit/react-textarea
@copilotkit/react-ui
@copilotkit/runtime
@copilotkit/runtime-client-gql
@copilotkit/sdk-js
@copilotkit/shared
@copilotkit/sqlite-runner
@copilotkit/voice
@copilotkit/vue
@copilotkit/web-components
@copilotkit/web-inspector
commit: |
Contributor
|
Size Change: +57 B (0%) Total Size: 1.19 MB 📦 View Changed
ℹ️ View Unchanged
|
davidmckayv
added a commit
that referenced
this pull request
Jul 24, 2026
Rewrites the React Native page into a production guide (Metro, polyfills,
provider options, runtime/model wiring, device + bench connectivity, frontend
tools, run lifecycle, voice), and corrects the source-backed inaccuracies found
in review. Every claim below was re-verified against the package source on main
(@copilotkit/react-native 1.63.2), not inferred.
Import surfaces (was "What's included" + "Headless imports")
- Documents all THREE entry points separately with the native peers each forces
Metro to resolve: /headless (none), root (expo-document-picker,
expo-file-system via useAttachments), /components (@gorhom/bottom-sheet,
react-native-streamdown).
- Removes the claim that the root barrel pulls @gorhom/bottom-sheet. It does
not -- the only import is src/components/CopilotModal.tsx, reachable solely
from /components. (The package's own source comments state this incorrectly;
that is what the previous draft was written from.)
- Warns that root's CopilotChat/CopilotModal are HEADLESS wrappers rendering
only children, while the same-named /components exports are the rendered
chat -- a silent blank-screen trap.
- The quickstart now imports from /headless throughout, matching its own advice
and keeping readers out of the release-bundle failure the page warns about.
- Corrects "the provider re-exports hooks" to the package, enumerates the
shared hooks, and drops "behave identically to the web SDK": React Native
ships its OWN useRenderTool (requires parameters, accepts handler, returns
ReactElement | null, no wildcard) and omits the web-only rendering hooks.
Metro
- Corrects the cause: jose is not a JWT/license dependency. It arrives via
telemetry (@copilotkit/shared -> @segment/analytics-node -> jose).
- Replaces the global unstable_conditionNames array with resolveRequest scoped
to jose (Metro's own documented recipe). unstable_conditionNames is an
UNORDERED SET of asserted conditions -- target priority comes from each
package's own exports key order, so reordering that array does nothing. The
previous config also applied browser globally and dropped Metro's default
react-native condition.
- Fixes version bounds: package exports arrived opt-in in RN 0.72 / Metro
0.76.1 and is default-on from Metro 0.82 / RN 0.79 (not "0.70+").
Polyfills
- Makes the quickstart canonical instead of correcting it later. Drops
"optional belt-and-suspenders".
- Documents the crypto ordering as a HARD requirement: CopilotKit's polyfill
and react-native-get-random-values are both first-writer-wins, so any
CopilotKit import evaluated first permanently locks in the non-cryptographic
Math.random fallback and silently no-ops the secure library.
Provider / runtime
- headers: a function form is evaluated when the PROVIDER RENDERS, memoized,
and pushed to the core -- never per request. Adds rotating-token guidance
(drive from state, or call copilotkit.setHeaders on refresh).
- cors: corrects the causal claim. CORS is browser-enforced; React Native's
native stack sends no Origin and never consults Access-Control-Allow-Origin,
so cors:true is irrelevant to native reachability (it matters for Expo Web).
Device connectivity
- Labels the adb reverse row Android-only and adds an iOS device row.
- Adds the missing `npx expo install expo-build-properties` step.
- Adds the iOS path, which was absent: ATS applies to debug and release alike,
expo-build-properties has no iOS ATS option, and since iOS 17 ATS rejects
raw IPs unless listed in NSExceptionDomains -- plus
NSLocalNetworkUsageDescription for the local-network permission gate. Notes
why NSAllowsLocalNetworking alone is insufficient.
Frontend tools
- Replaces the incorrect "useFrontendTool can carry a render function drawn as
the tool runs". The rendered RN chat reads a registry populated only by RN's
useRenderTool; a render passed to useFrontendTool is never drawn there and
yields the fallback "Called: <toolName>" stub.
Other
- Removes the useAgent({ threadId }) example: unsupported on main, does not
typecheck (TS2353), silently ignored. Recorded as a known limitation
pointing at #6141 instead, so this page no longer depends on that PR.
- Known limitations: drops the "No pre-built UI is required" positioning line;
corrects the markdown entry (the rendered chat DOES render markdown via
CopilotMarkdown/react-native-streamdown -- the old entry recommended the
wrong library); adds the threadId and web-only-hooks entries.
- Broadens the frontmatter description, which still promised only "get started".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
UseAgentProps(packages/react-core/src/v2/hooks/use-agent.tsx) exposed only{ agentId?, updates?, throttleMs? }— there was nothreadId. Yet the shipped V2 React Native demo calls:(
examples/v2/react-native/demo/src/ChatScreen.tsx)Because the prop didn't exist on the type, it was silently ignored. The demo's
threadIdstate — and its "New Chat" reset (setThreadId(generateThreadId())) — never reached the agent. The demo has no<CopilotChatConfigurationProvider>in its tree (seeApp.tsx), which was the only source the hook read threadId from, so the agent ran under its own auto-minted UUID the whole time. A misleading API: the demo advertised a supported prop that did nothing.Fix
Accept an optional
threadIdonUseAgentPropsand honor it. Resolution precedence:threadIdprop wins — lets headless callers (e.g. React Native) scope the run to a thread with no chat-configuration provider in the tree.hasExplicitThreadIdexactly as before.The threadId still lands on
agent.threadId, whichProxiedCopilotRuntimeAgentuses to address/agent/run,/agent/connect, and/agent/stop.Backward compatibility
Fully backward compatible:
threadIdis optional, and when omitted the behavior is byte-for-byte unchanged (config-sourced,hasExplicitThreadId-gated). No demo change is needed — the RN demo's existinguseAgent({ agentId, threadId })call now works as it always appeared to.Tests
Extends the existing threadId-propagation contract test (
packages/react-core/src/__tests__/threadid-propagation.contract.test.tsx) with the prop path:threadIdprop with noCopilotChatConfigurationProvider(the RN demo scenario)threadIdprop over the chat configuration's threadIdagent.threadIdwhen the prop changesThe pre-existing config-sourced invariants remain covered and unchanged.
🤖 Generated with Claude Code