agentskit.js

@agentskit/react-native — for agents

React Native / Expo binding — same `useChat` contract as `@agentskit/react`, Metro + Hermes safe with streaming polyfill guidance.

#Purpose

React Native binding for the ChatReturn contract from @agentskit/core. Shares the same hook API as @agentskit/react but ships without any DOM dependency, making it safe for Metro bundler and the Hermes JS engine used in React Native and Expo.

#Install

npm install @agentskit/react-native
# peers:
npm install react react-native

#Primary exports

  • useChat(config): ChatReturn — identical contract to @agentskit/react, imported from pure React (no DOM).
  • ChatContainerScrollView wrapper with auto-scroll to end.
  • Message — message → View + Text; role/status via accessibilityLabel.
  • InputBarchat: ChatReturnTextInput + Send Pressable; sends on submit, disabled when empty/streaming.
  • Markdowncontent + streamingText.
  • CodeBlockcode, language, copyableView + Text + optional copy Pressable.
  • ToolCallViewtoolCall with collapsible details.
  • ThinkingIndicatorvisible + label; null when not visible.
  • ToolConfirmationtoolCall, onApprove, onDeny; null unless status === 'requires_confirmation'.

Headless components render React Native primitives and expose stable testIDs (ak-message, ak-input, ak-send, …) in place of the web binding's data-ak-* attributes — the same parity contract, surfaced through RN's native testID.

#Minimal example

import { useChat } from '@agentskit/react-native'
import { anthropic } from '@agentskit/adapters'
import { View, TextInput, FlatList, Pressable, Text } from 'react-native'

const adapter = anthropic({ apiKey: process.env.ANTHROPIC_KEY, model: 'claude-sonnet-4-6' })

export function Chat() {
  const chat = useChat({ adapter })
  return (
    <View style={{ flex: 1 }}>
      <FlatList
        data={chat.messages}
        keyExtractor={m => m.id}
        renderItem={({ item }) => <Text>{item.role}: {item.content}</Text>}
      />
      <TextInput value={chat.input} onChangeText={chat.setInput} />
      <Pressable onPress={() => chat.send(chat.input)}><Text>Send</Text></Pressable>
    </View>
  )
}

#Common patterns

  • Streaming polyfills required: Hermes does not ship TextDecoder or the Web Streams API. Install react-native-polyfill-globals and call polyfillGlobal('TextDecoder', ...) at the top of your entry file before any AgentsKit import. Missing polyfills fail predictably (thrown / rejected stream errors) rather than failing silently — do not catch-and-ignore those errors at the app boundary without surfacing them.
  • No Node built-ins: Metro does not polyfill Node modules (Buffer, stream, crypto). If an adapter dependency pulls them in, add the react-native field in the adapter's package.json or use a Metro resolver alias.
  • Expo managed workflow: add the polyfill in app/_layout.tsx (or App.tsx) as the very first import; do not rely on Babel plugins to hoist polyfills after module initialisation.
  • Keyboard avoiding: wrap the input in <KeyboardAvoidingView> and use FlatList's inverted prop + onContentSizeChange scroll-to-end for a chat-like feel.

#Source

Explore nearby

✎ Edit this page on GitHub·Found a problem? Open an issue →·How to contribute →

On this page

Ask the docs
Ask anything about AgentsKit. Answers come from the docs corpus and cite their sources.