The conversational AI SDK for iOS apps.
FinClip ChatKit is an embeddable SDK that lets you build intelligent, context-aware conversational experiences directly inside your iOS apps. It provides a drop-in chat interface, secure sandbox for agent actions, and native bridges for agent protocols such as AG-UI, OpenAI Apps SDK, and MCP-UI — all in one package.
Built for developers who want to add AI chat and agent-assisted actions quickly, ChatKit combines native UI performance with context awareness and security. It brings together real-time text streaming, multimedia rendering, and policy-based sandbox execution — so your app can talk, act, and reason safely.
Whether you’re building a personal assistant, support bot, or workflow automation tool, ChatKit helps you ship a production-ready conversational experience in hours instead of weeks.
Modern AI assistants need more than just text back-and-forth—they need to understand context, execute actions safely, and integrate seamlessly into your app's existing flows. ChatKit delivers:
🧠 Context-Aware Intelligence
Automatically captures rich device signals—location, time, sensors, network status, calendar events—so your AI understands the user's situation without extra work from you. Context providers run efficiently in the background, enriching every conversation with relevant environmental data.
🎨 Production-Ready UI Components
Ship chat experiences in hours, not weeks. Drop-in view controllers with rich message rendering (Markdown, multimedia, forms, buttons, cards), real-time streaming text, typing indicators, and support for press-to-talk speech input. Light/dark mode and full theming support included.
🔒 Security-First Architecture
Every AI-initiated action runs through a capability-based sandbox with fine-grained policy controls. Require explicit user consent, enforce rate limits, set sensitivity levels, and maintain complete audit trails—all built-in. Your users stay in control, always.
💾 Persistent Conversation Management
Multi-session support with automatic persistence. Track conversation history, resume sessions across app launches, manage multiple agents, and sync seamlessly with cloud storage—all handled by the framework's integrated storage layer.
🔌 Flexible Integration
High-level APIs for rapid development (20-30 lines to a working chat UI) or low-level APIs when you need maximum control. Works with WebSocket/HTTP backends, supports custom network adapters, and embeds easily in navigation stacks, sheets, drawers, or tabs.
📱 Native Performance
Pure iOS/Swift implementation with native WKWebView rendering for interactive components. No cross-platform compromises—built specifically for iOS with optimal memory usage and smooth 60fps scrolling even with hundreds of messages.
ChatKit is designed for extensibility through a powerful provider system—a lightweight, plugin-like architecture that lets developers deeply customize how ChatKit behaves and interacts with users. By registering or replacing providers, you can adapt ChatKit to new use cases, integrate with enterprise infrastructure, or deliver richer, more contextual AI experiences.
Developers can create custom context providers—“mini” interfaces that collect structured user input or contextual data (such as maps, calendars, or forms) and attach this information to user queries before sending them to the agent or LLM. These transient UIs can appear dynamically when the agent requests more context or when users trigger a context collection action. For example, you might present a date picker when scheduling, or a map interface for location selection, seamlessly gathering structured data to enhance agent reasoning.
Plug in any speech recognition engine using an ASR (Automatic Speech Recognition) provider. Whether you need Deepgram, OpenAI Whisper, Apple Dictation, or an enterprise-compliant speech engine, ChatKit allows you to swap or extend ASR providers to capture voice input, adapt to language requirements, or meet compliance needs—all without modifying the core SDK.
Developers can inject custom auto-title generation logic to automatically name chat sessions or improve user experience. For instance, you could use a summary of the conversation, the user’s first message, or a custom LLM-based summarizer to generate descriptive and relevant session titles.
Each provider acts like a lightweight plugin: register, replace, or extend them easily to make your ChatKit-based app more powerful and contextually aware. Mix and match providers to support new modalities, enterprise integrations, or unique workflows—without forking or rewriting the SDK.
ChatKit’s provider system makes it easy to go from a simple chat box to a deeply contextual, multimodal AI experience.
- Customer support bots with agent handoff and rich media attachments
- Personal AI assistants that access device sensors and calendar to help users
- In-app shopping advisors that understand user preferences and purchase history
- Health coaching apps with context-aware recommendations based on time and location
- Enterprise automation tools where AI proposes actions requiring user approval
- Educational tutors with interactive forms, quizzes, and progress tracking
ChatKit is part of the FinClip Agentic Middleware ecosystem, but it’s fully open and server-agnostic — you’re never locked to FinClip servers. Because it natively supports the AG-UI protocol, developers can host their own agent servers or build custom ones that speak AG-UI, enabling full control over backend logic, privacy, and data.
You can even combine AG-UI with MCP-UI or the OpenAI Apps SDK to provide generative UI capabilities. ChatKit will seamlessly interoperate with any compliant AG-UI or MCP-UI server, automatically rendering dynamic, agent-generated UI elements (buttons, forms, cards, etc.) within your iOS app.
ChatKit acts as the mobile-side runtime bridge for agent protocols like AG-UI (Agent UI) and MCP-UI (Model Context Protocol UI). Together, these protocols enable generative UI — where conversations dynamically generate interactive elements such as buttons, forms, and cards, rendered securely in iOS.
1. Add dependency to your Package.swift:
dependencies: [
.package(url: "https://github.com/Geeksfino/finclip-chatkit.git", from: "0.6.1")
]2. Initialize coordinator at app launch:
import UIKit
import FinClipChatKit
// In SceneDelegate or AppDelegate
let config = NeuronKitConfig.default(serverURL: URL(string: "http://127.0.0.1:3000/agent")!)
.withUserId("demo-user")
let coordinator = ChatKitCoordinator(config: config)3. Create conversation and show chat UI:
// When user taps "New Chat" button
Task { @MainActor in
let agentId = UUID(uuidString: "E1E72B3D-845D-4F5D-B6CA-5550F2643E6B")!
let (record, conversation) = try await coordinator.startConversation(
agentId: agentId,
title: nil,
agentName: "My Agent"
)
// Show ready-made chat UI
let chatVC = ChatKitConversationViewController(
record: record,
conversation: conversation,
coordinator: coordinator,
configuration: .default
)
navigationController?.pushViewController(chatVC, animated: true)
}That's it! You now have a working AI chat app with persistent storage and full-featured UI.
📖 For detailed examples: See Quick Start Guide for Swift and Objective-C skeleton code.
ChatKit provides a unified way to attach context to messages using ChatKitContextItemFactory. This factory creates ConversationContextItem instances from simple metadata dictionaries, making it easy to send programmatic context.
Swift Example:
import FinClipChatKit
// Create context metadata
let context: [String: Any] = [
"type": "strategy",
"strategyId": "123",
"strategyTitle": "Growth Strategy"
]
// Create context item using factory
let contextItem = ChatKitContextItemFactory.metadata(context, type: "strategy")
// Send message with context
try await conversation.sendMessage(
"Tell me about this strategy",
contextItems: [contextItem]
)Multiple Context Items:
// Create multiple context items
let strategyContext = ChatKitContextItemFactory.metadata(
["strategyId": "123", "strategyTitle": "Growth"],
type: "strategy"
)
let userContext = ChatKitContextItemFactory.metadata(
["userId": "456", "userRole": "premium"],
type: "user"
)
try await conversation.sendMessage(
"Analyze this strategy for my account",
contextItems: [strategyContext, userContext]
)Objective-C Example:
#import <FinClipChatKit/FinClipChatKit-Swift.h>
// Create metadata dictionary
NSDictionary *metadata = @{
@"type": @"strategy",
@"strategyId": @"123",
@"strategyTitle": @"Growth Strategy"
};
// Create context dictionary using factory
NSDictionary *contextDict = [ChatKitContextItemFactory
contextDictionaryFromMetadata:metadata
type:@"strategy"
displayName:nil];
// Use with runtime's sendMessage method
// Note: You'll need to access the runtime and sessionId from your conversationFor more details, see the Developer Guide and Objective-C Guide.
Start with the right guide for your needs:
- Quick Start Guide - Minimal skeleton code (Swift & Objective-C) - Start here!
- Getting Started Guide - Detailed walkthrough with explanations
- Swift Developer Guide - Comprehensive Swift guide from beginner to expert
- Objective-C Developer Guide - Complete Objective-C guide with API reference
- API Levels Guide - Understanding high-level vs low-level APIs
- Component Embedding Guide - Embed components in sheets, drawers, tabs (Swift & Objective-C)
- Build Tooling Guide - Reproducible builds with Makefile and XcodeGen
- Architecture Overview - Understanding the framework structure
- Customize UI Guide - Styling and theming
- Troubleshooting Guide - Common issues and solutions
- Integration Guide - SPM, CocoaPods, deployment
📑 Full Documentation Index - Complete navigation and learning paths
Explore fully working examples in demo-apps/iOS/:
Demonstrates high-level APIs with minimal code.
cd demo-apps/iOS/Simple
make runWhat it demonstrates:
- High-level APIs (
ChatKitCoordinator,ChatKitConversationViewController) - Drawer-based navigation pattern
- Component embedding
- Standard build tooling (Makefile, XcodeGen)
See: Simple README
Objective-C version using high-level APIs.
cd demo-apps/iOS/SimpleObjC
make runWhat it demonstrates:
- Objective-C high-level APIs (
CKTChatKitCoordinator,ChatKitConversationViewController) - Navigation-based flow
- Remote dependency usage
See: SimpleObjC README
Explore comprehensive Android example apps in demo-apps/Android/:
A complete example app with 7 different scenarios demonstrating various features of the ChatKit Android SDK.
cd demo-apps/Android
make runWhat it demonstrates:
- Simple Chat - Minimal integration example
- Configuration - Customize chat UI
- Conversation Management - CRUD operations
- Context Providers - Device/network context
- Compose Example - Jetpack Compose integration
- Full Feature - All features combined
- Advanced APIs - Low-level APIs & customization
See: Android Demo README | 中文
- ✅ ChatKitCoordinator - Safe runtime lifecycle management
- ✅ ChatKitConversationManager - Optional multi-conversation tracking
- ✅ NeuronRuntime - AI agent orchestration
- ✅ Conversation API - Session management and messaging
- ✅ Persistent Storage - Automatic conversation persistence (convstore)
- ✅ Reactive Updates - Combine publishers for UI binding
- ✅ ChatKitConversationViewController - Ready-made chat UI component
- ✅ ChatKitConversationListViewController - Ready-made conversation list component
- ✅ Message Bubbles - User and agent message rendering
- ✅ Input Composer - Rich text input with attachments
- ✅ Typing Indicators - Real-time typing feedback
- ✅ Customizable Themes - Light/dark mode support
- ✅ ConversationManager - Track multiple sessions automatically
- ✅ ConversationRecord - Lightweight metadata model
- ✅ Auto-persistence - Saves conversations to convstore
- ✅ Auto-titling - Uses first user message as title
- ✅ Reactive list - Publisher for conversation updates
ChatKit provides comprehensive support for modern AI agent protocols and UI conventions, enabling seamless integration with the broader AI ecosystem.
ChatKit includes full AG-UI (Agent UI) protocol support through NeuronKit, enabling you to build intelligent copilot applications compatible with AG-UI servers (equivalent to CopilotKit for web).
Key Features:
- ✅ Full SSE Event Support - All AG-UI event types (
RUN_*,TEXT_MESSAGE_*,TOOL_CALL_*, etc.) - ✅ Typed Tool Arguments - Preserves JSON types (numbers, booleans, objects, arrays) instead of converting to strings
- ✅ Multi-Session SSE - Multiple concurrent conversation sessions with separate SSE connections
- ✅ Text Streaming - Real-time incremental text streaming with sequence tracking
- ✅ Tool/Function Calls - Agent requests tool execution with proper consent flow via Sandbox PDP
- ✅ Thread Management - Track conversation threads with
runIdand metadata - ✅ Bidirectional Communication - HTTP POST for outbound messages, SSE for inbound streaming
Usage:
import FinClipChatKit
let config = NeuronKitConfig.default(serverURL: URL(string: "https://your-agui-server.com/agent")!)
.withUserId("user-123")
let coordinator = ChatKitCoordinator(config: config)
// Configure AG-UI adapter
let aguiAdapter = AGUI_Adapter(
baseEventURL: URL(string: "https://your-agui-server.com/agent")!,
connectionMode: .postStream // POST with SSE responses
)
coordinator.runtime.setNetworkAdapter(aguiAdapter)
// Start conversation - AG-UI protocol is automatically used
let (record, conversation) = try await coordinator.startConversation(
agentId: agentId,
title: nil,
agentName: "My Agent"
)Connection Modes:
- POST Stream (Recommended): Single endpoint for both sending messages and receiving SSE responses
- Event Stream: Separate endpoints for SSE connection and message sending
ChatKit includes an OpenAI Bridge that provides compatibility with OpenAI Apps SDK widgets, enabling you to use widgets designed for OpenAI's chatkit-js without modification.
Key Features:
- ✅
window.openaiAPI - Full JavaScript API compatibility - ✅ Promise-Based Architecture - Async/await support for tool calls and state operations
- ✅ State Management - Built-in
setState()andgetState()for widget state persistence - ✅ Event System - Support for
on()andoff()event handlers - ✅ Native Integration - Uses WKWebView and WKScriptMessageHandler for secure bridge communication
Usage: Widgets from OpenAI Apps SDK-based MCP servers are automatically rendered in ChatKit's conversation UI. The bridge handles all JavaScript-to-native communication transparently.
JavaScript API (in widgets):
// Promise-based tool calls
window.openai.callTool({
name: "get_weather",
parameters: { location: "San Francisco" }
}).then(result => {
console.log("Weather:", result);
});
// State management
window.openai.setState({ count: 5 });
const state = window.openai.getState(); // { count: 5 }ChatKit provides comprehensive support for MCP-UI (Model Context Protocol UI), enabling native iOS rendering of interactive web-based UI components from MCP servers.
Key Features:
- ✅ Native WKWebView Rendering - Secure, sandboxed execution for web compatibility
- ✅ Fire-and-Forget Actions - Simple action pattern (
callTool,triggerIntent,submitPrompt,notify,openLink) - ✅ Auto-Resize Support - Dynamic content sizing via
reportSize() - ✅ Render Data Injection - Dynamic content injection for widget personalization
- ✅ Security Sandboxing - WKWebView with Content Security Policy (CSP) enforcement
- ✅ Multiple Content Types - Support for HTML (
text/html), external URLs (text/uri-list), and remote DOM scripts
Usage: MCP-UI widgets are automatically detected and rendered in ChatKit's conversation UI. Actions from widgets are handled through the conversation's delegate methods.
JavaScript API (in widgets):
// Call a tool/function on the backend
window.mcpUI.callTool("search", { query: "example" });
// Trigger an intent
window.mcpUI.triggerIntent("book_flight", { destination: "NYC" });
// Submit a new prompt
window.mcpUI.submitPrompt("Tell me more about...");
// Show a notification
window.mcpUI.notify("Operation completed", "success");
// Open a link
window.mcpUI.openLink("https://example.com");
// Report widget size for auto-resize
window.mcpUI.reportSize(450);| Feature | AG-UI | OpenAI Bridge | MCP-UI |
|---|---|---|---|
| Purpose | Network protocol for agent communication | Widget compatibility layer | UI component rendering |
| API Style | SSE + HTTP POST | Promise-based (window.openai) |
Fire-and-forget (window.mcpUI) |
| State Management | Conversation-level | Widget-level (setState/getState) |
Manual (in widget) |
| Tool Calls | Full consent flow via Sandbox | Promise-based with responses | Fire-and-forget |
| Text Streaming | ✅ Real-time incremental | N/A | N/A |
| Multi-Session | ✅ Yes | N/A | N/A |
| Best For | Agent orchestration & communication | OpenAI Apps SDK widgets | MCP-UI ecosystem widgets |
Integration: All three conventions work seamlessly together in ChatKit. AG-UI handles agent communication, while widgets are automatically rendered using either the OpenAI Bridge or MCP-UI support depending on the widget type.
ChatKit provides multiple API levels to suit different needs:
Ready-made components for rapid development:
ChatKitCoordinator- Runtime lifecycle managementChatKitConversationViewController- Complete chat UIChatKitConversationListViewController- Conversation list UI- Minimal code (20-30 lines for basic chat)
Best for: Most applications, standard chat UI, rapid development
See: API Levels Guide | Simple Demo
Direct access for maximum flexibility:
- Direct runtime access
- Manual UI binding
- Custom implementations
- More code (200+ lines), more control
Best for: Custom UI requirements, specialized layouts
See: API Levels Guide
Customize framework behavior without modifying code:
- Context Providers - Attach location, calendar, etc.
- ASR Providers - Custom speech recognition
- Title Generation Providers - Custom conversation titles
See: API Levels Guide
Option 1: Package.swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyApp",
platforms: [.iOS(.v16)],
dependencies: [
.package(url: "https://github.com/Geeksfino/finclip-chatkit.git", from: "0.6.1")
],
targets: [
.target(
name: "MyApp",
dependencies: [
.product(name: "ChatKit", package: "finclip-chatkit")
]
)
]
)Option 2: Xcode
- File → Add Package Dependencies
- Enter:
https://github.com/Geeksfino/finclip-chatkit.git - Select version:
0.6.1or later
pod 'ChatKit', :podspec => 'https://raw.githubusercontent.com/Geeksfino/finclip-chatkit/main/ChatKit.podspec'Then run:
pod installNote: We use a direct podspec URL because the "ChatKit" name on CocoaPods trunk is occupied by a different project.
-
Initialize coordinator once at app launch
// In SceneDelegate or AppDelegate let coordinator = ChatKitCoordinator(config: config)
-
Use high-level APIs for standard chat UI
// Create conversation let (record, conversation) = try await coordinator.startConversation(...) // Show ready-made chat UI let chatVC = ChatKitConversationViewController( record: record, conversation: conversation, coordinator: coordinator, configuration: .default )
-
Use ConversationManager for multi-session apps
let manager = ChatKitConversationManager() manager.attach(runtime: coordinator.runtime)
-
Observe reactively with Combine
manager.recordsPublisher .sink { records in /* update UI */ } .store(in: &cancellables)
-
Embed components in any container
// Navigation, sheet, drawer, tab - all work! navigationController?.pushViewController(chatVC, animated: true)
-
Don't create conversations at app launch
// ❌ BAD: Too early, user hasn't requested it func application(...) -> Bool { let coordinator = ChatKitCoordinator(config: config) let conversation = try await coordinator.startConversation(...) // Don't! }
-
Don't create multiple coordinators
// ❌ BAD: Creates multiple runtimes func newChat() { let coordinator = ChatKitCoordinator(config: config) // Don't! }
-
Don't forget to store coordinator
// ❌ BAD: Gets deallocated immediately func setup() { let coordinator = ChatKitCoordinator(config: config) // Oops, released when function returns }
-
Don't use low-level APIs unless necessary
// ❌ BAD: Unnecessary complexity for standard use case let hosting = ChatHostingController() let adapter = ChatKitAdapter(chatView: hosting.chatView) conversation.bindUI(adapter) // Too verbose! // ✅ GOOD: Use high-level component let chatVC = ChatKitConversationViewController(...) // Simple!
-
Don't edit generated Xcode projects
// ❌ BAD: Changes lost on regeneration // Edit .xcodeproj directly // ✅ GOOD: Edit project.yml, then regenerate // make generate
Solution: Update to v0.6.1 or later
.package(url: "https://github.com/Geeksfino/finclip-chatkit.git", from: "0.6.1")Solution: Use .persistent storage
NeuronKitConfig(..., storage: .persistent)See the full Troubleshooting Guide.
Follow this progressive path to master ChatKit:
-
Quick Start → Quick Start Guide
- Minimal skeleton code (5 minutes)
- Swift and Objective-C examples
-
Learn the Basics → Getting Started Guide
- Detailed walkthrough
- Key concepts explained
-
Understand APIs → API Levels Guide
- High-level vs low-level APIs
- When to use each
-
Build Features
- Swift: Swift Developer Guide - Multiple conversations, history, advanced patterns
- Objective-C: Objective-C Developer Guide - Multiple conversations, list UI, API reference
-
Customize & Embed → Component Embedding Guide
- Embed in sheets, drawers, tabs
- Custom container patterns
-
Set Up Builds → Build Tooling Guide
- Reproducible builds
- Makefile and XcodeGen
-
Study Examples →
demo-apps/iOS/Simple/,demo-apps/iOS/SimpleObjC/, anddemo-apps/Android/- Complete working examples
- High-level API patterns
- iOS and Android platform examples
We welcome contributions! Please:
- Open an issue for bugs or feature requests
- Submit pull requests with improvements
- Update documentation for new features
- Add tests for new functionality
See LICENSE for details.
- Documentation:
docs/ - Examples:
demo-apps/iOS/anddemo-apps/Android/ - Issues: GitHub Issues
- Discussions: GitHub Discussions
From the examples and documentation:
- ✅ High-level APIs for rapid development
- ✅ Safe runtime lifecycle management with
ChatKitCoordinator - ✅ Ready-made UI components (
ChatKitConversationViewController,ChatKitConversationListViewController) - ✅ Component embedding in various containers (navigation, sheets, drawers, tabs)
- ✅ Managing multiple conversations with
ChatKitConversationManager - ✅ Provider mechanisms (context, ASR, title generation)
- ✅ Reproducible builds with Makefile and XcodeGen
- ✅ Best practices and common pitfalls
ChatKit examples use standardized build tools for reproducibility:
- XcodeGen - Generate Xcode projects from YAML
- Makefile - Standardized build commands
- project.yml - Version-controlled project configuration
See: Build Tooling Guide for complete instructions.
Quick start:
cd demo-apps/iOS/Simple
make generate # Generate Xcode project
make run # Build and run on simulatorReady to build? Start with Quick Start Guide →
Made by the FinClip team