The Bitte AI Chat component is a React component that enables AI-powered chat interactions in your application. It supports both NEAR Protocol and EVM blockchain interactions through wallet integrations, allowing users to interact with smart contracts and perform transactions directly through the chat interface.
🔑 Before you begin, make sure you have:
A Bitte API Key - Get your beta BITTE_API_KEY
Quick Start (<10min)
Install package
Add the Chat Component
Setup API Route
Wallet Connection
1. Install Package
pnpm install @bitte-ai/chat
2. Add the Chat Component
import {BitteAiChat} from "@bitte-ai/chat";
import '@bitte-ai/chat/styles.css';
<BitteAiChat
agentId="your-agent-id"
apiUrl="/api/chat"
/>
3. Setup API Route
Create an API route in your Next.js application to proxy requests to the Bitte API to not expose your key.
Nextjs app router implementation:
import type { NextApiRequest, NextApiResponse } from 'next';
const {
BITTE_API_KEY,
BITTE_API_URL = 'https://ai-runtime-446257178793.europe-west1.run.app/chat',
} = process.env;
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const data = req.body;
const requestInit: RequestInit = {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${BITTE_API_KEY}`,
},
};
const upstreamResponse = await fetch(`${BITTE_API_URL}`, requestInit);
res.statusCode = upstreamResponse.status;
for (const [key, value] of Object.entries(upstreamResponse.headers)) {
if (key.toLowerCase() !== 'content-encoding') {
res.setHeader(key, value as string);
}
}
res.setHeader('Content-Type', upstreamResponse.headers.get('Content-Type') || 'application/json');
if (!upstreamResponse.body) {
return res.end();
}
const reader = upstreamResponse.body.getReader();
async function readChunk() {
const { done, value } = await reader.read();
if (done) {
return res.end();
}
res.write(value);
await readChunk();
}
await readChunk();
} catch (error) {
console.error('Error in chat API route:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
}
At this point the chat should already work but to be able to send transactions you will need to add a wallet connection
4. Add wallet connection
NEAR Integration
You can integrate with NEAR using either the NEAR Wallet Selector or a direct account connection. If you want to be able to send near transacitons through the chat you will need to define at least one of these
import { Account } from "near-api-js";
// get near account instance from near-api-js by instantiating a keypair
<BitteAiChat
agentId="your-agent-id"
apiUrl="/api/chat"
wallet={{ near: { account: nearAccount } }}
/>
EVM Integration
EVM integration uses WalletConnect with wagmi hooks:
interface BitteAiChatProps {
agentId: string; // ID of the AI agent to use
apiUrl: string; // Your API route path (e.g., "/api/chat")
historyApiUrl?: string; // Your history API route to keep context when signing transactions
wallet?: WalletOptions; // Wallet configuration
colors?: ChatComponentColors;
options?: {
agentName?: string; // Custom agent name
agentImage?: string; // Custom agent image URL
chatId?: string; // Custom chat ID
prompt?: string // Custom Initial prompt
localAgent?: {
pluginId: string;
accountId: string;
spec: BitteOpenAPISpec;
};
placeholderText?: string;
colors?: ChatComponentColors;
customComponents?: {
welcomeMessageComponent?: React.JSX.Element;
mobileInputExtraButton?: React.JSX.Element;
messageContainer?: React.ComponentType<MessageGroupComponentProps>;
chatContainer?: React.ComponentType<ChatContainerComponentProps>;
inputContainer?: React.ComponentType<InputContainerProps>;
sendButtonComponent?: React.ComponentType<SendButtonComponentProps>;
loadingIndicator?: React.ComponentType<LoadingIndicatorComponentProps>;
};
};
customToolComponents?: CustomToolComponent[];
}
export interface ReactToolComponent {
name: string;
component: React.ComponentType<CustomToolComponentProps>;
}
// Update CustomToolComponent type to align with BitteTool from primitives.ts
export type CustomToolComponent =
| PortfolioTool
| TransferTool
| SwapTool
| ReactToolComponent;
Custom Components
The BitteAiChat component provides several UI elements that can be customized via the customComponents under options prop. This enables full control over the appearance and behavior of key parts of the chat interface by passing in your own React components.
Available Custom Components
You can override the following built-in UI components:
✅ Tip: All custom components are optional. If not provided, the default components will be used.
Custom Tool Components
The BitteAiChat component supports embedding interactive, data-driven tools directly into the chat UI through the customToolComponents prop. These tools allow users to interact with structured data returned by your agent’s API, such as portfolios, token swaps, or custom workflows.
How Tool Rendering Works
When your AI agent responds with a message that includes a data field , and that data matches a known type (like PortfolioResponse, TransferFTData, etc.), the chat interface can automatically render the corresponding tool component — as long as a tool is registered in customToolComponents with a matching name.
The name must match:
The operation name in your agent’s OpenAPI spec
The name field in the tool component configuration
There is no need to wrap the response in a tool object — the chat package dynamically maps the data to the corresponding component based on the configured name and type.
Pre-Configured Tools
The @bitte-ai/chat package comes with built-in support for the following tools:
get-portfolio
swap
transfer-ft
As long as:
The agent's API response includes a data field that matches the correct type (PortfolioResponse, SwapFTData, or TransferFTData — all from @bitte-ai/types)
The OpenAPI spec defines the route using one of the above names (i.e. get-portfolio, swap, or transfer-ft as operation IDs or paths)
...then the matching tool UI will automatically be rendered — no manual configuration required.
These tools are auto-wired and will display a default UI out-of-the-box. You only need to use customToolComponents if you want to override these default UIs or add custom tools.
Example: Registering Tool Components
const customToolComponents = [
{
name: 'get-portfolio', // This should match the operationId or route name from your OpenAPI spec
component: (props) => (
<TokenList data={props.data as PortfolioResponse} />
),
},
{
name: 'swap',
component: (props) => (
<Swap data={props.data as SwapFTData} />
),
},
{
name: 'transfer-ft',
component: (props) => (
<Transfer data={props.data as TransferFTData} />
),
},
{
name: 'my-custom-tool',
component: (props) => <MyCustomComponent data={props.data} />,
},
];
Helps set up DCA plans to buy NEAR and other tokens
Investing
dcaagent.deltatrade.ai
SUI Defi Agent
check balances, swap, stake and more on SUI
Defi
bitte-sui-agent.vercel.app
Sui Explorer
Retrieve any blockchain data from SUI
Ecosystem
sui-explorer.vercel.app
Benqi Agent
Defi Agent for Benqi Protocol on Avalanche
Defi
benqi-agent.vercel.app
Bitte WETH Wraptor
Wrap and unwrap ETH.
Other
wraptor-agent.vercel.app
Bitte Distribute Tokens
Distribute tokens on EVM chains using csv files and more
Other
safe-airdrop-agent.vercel.app
Creating Custom Agents
Example Projects
Styling
The component can be customized using the colors prop:
type ChatComponentColors = {
generalBackground?: string; // Chat container background
messageBackground?: string; // Message bubble background
textColor?: string; // Text color
buttonColor?: string; // Button color
borderColor?: string; // Border color
};
Browser Redirects (Optional)
if you're having issues with your app or wallet containing redirects you can optionally use a history api to maintain context
Create an API route in your Next.js application that will allow your app if you want to save chat context when signing a transaction after getting redirected to the wallet.
Import and use BitteAiChat in your react app and select the agent that you would like to use, browse the available agents and their respective ids on the
The apiUrl corresponds to a proxy to not expose your api key on the client