Conversations
The Conversation class manages multi-turn dialog with automatic history tracking, session management, and serialization. It wraps the low-level chaos.chat.responses.create() call and maintains an ordered list of InputItem messages.
import { Chaos, Conversation } from '@chaoslabs/ai-sdk';
import type { ConversationOptions, ConversationStats } from '@chaoslabs/ai-sdk';ConversationOptions
Passed to the Conversation constructor to configure the session.
export interface ConversationOptions {
/** Model to use (defaults to WALLET_MODEL) */
model?: string;
/** Maximum number of messages to keep in history */
maxHistoryLength?: number;
/** User identifier */
userId: string;
/** Array of wallet addresses across multiple chains */
wallets?: Array<{ address: string; chain: string }>;
/** Optional initial session ID (auto-generated if not provided) */
sessionId?: string;
/** Optional wallet context override for deterministic testing */
walletContextOverride?: WalletContextOverride;
}| Property | Type | Required | Default | Description |
|---|---|---|---|---|
userId | string | Yes | - | Unique user identifier |
model | string | No | WALLET_MODEL | Model to use for requests |
maxHistoryLength | number | No | 50 | Maximum messages retained in history |
wallets | Array<{ address, chain }> | No | - | Wallet addresses for DeFi operations |
sessionId | string | No | Auto-generated | Initial session identifier |
walletContextOverride | WalletContextOverride | No | - | Override wallet context for deterministic testing |
ConversationStats
Statistics about the conversation, accessible via the stats getter.
export interface ConversationStats {
/** Number of user turns */
userTurns: number;
/** Number of assistant turns */
assistantTurns: number;
/** Total messages in history */
totalMessages: number;
/** Session ID */
sessionId: string;
/** When the conversation started */
startedAt: Date;
/** When the last message was sent */
lastMessageAt: Date | null;
}Constructor
Creates a new conversation bound to a Chaos client instance.
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
const conversation = new Conversation(chaos, {
userId: 'user-123',
wallets: [
{ address: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD21', chain: 'ethereum' },
{ address: '0x8ba1f109551bD432803012645Hac136c22C501a', chain: 'base' },
],
maxHistoryLength: 100,
});Methods
send(message)
Send a message and get a response. History is managed automatically: the user message is appended before the request, and the assistant reply is appended after a successful response.
async send(message: string): Promise<ChatCreateResponse>;
// Usage
const response1 = await conversation.send("What's my portfolio value?");
const response2 = await conversation.send('Which asset has the highest allocation?');
// response2 has full context from response1fork()
Create a branch of the conversation. The forked conversation has the same history but a new session ID, allowing you to explore alternate dialog paths without affecting the original.
fork(): Conversation;
// Usage
const forked = conversation.fork();
const altResponse = await forked.send('What if I deposit into Aave instead?');
// Original conversation is unchangedreset()
Reset the conversation to start fresh. Clears history, resets counters, and generates a new session ID.
reset(): void;
// Usage
conversation.reset();
// History is empty, new session ID generatedclearHistory()
Clear the history and counters but keep the same session ID.
clearHistory(): void;
// Usage
conversation.clearHistory();
// Same session ID, empty historyaddUserMessage / addAssistantMessage / addSystemMessage
Manually inject messages into the history without sending a request. Useful for restoring conversation state or injecting system context.
addUserMessage(content: string): void;
addAssistantMessage(content: string): void;
addSystemMessage(content: string): void;
// Usage: pre-seed a conversation
conversation.addSystemMessage('You are a DeFi portfolio assistant.');
conversation.addUserMessage('What is Aave?');
conversation.addAssistantMessage('Aave is a decentralized lending protocol...');
// Next send() will include all three messages as context
const response = await conversation.send('How do I deposit into it?');Accessors
| Accessor | Type | Description |
|---|---|---|
sessionId | string | Current session ID |
messages | readonly InputItem[] | Copy of the conversation history |
stats | ConversationStats | Current conversation statistics |
Serialization
Conversations can be serialized to JSON and restored later, enabling persistence across sessions.
toJSON()
toJSON(): {
sessionId: string;
history: InputItem[];
metadata: RequestMetadata;
stats: ConversationStats;
};
// Usage
const data = conversation.toJSON();
const json = JSON.stringify(data);
// Store in database, file, localStorage, etc.fromJSON()
static fromJSON(
client: Chaos,
data: {
sessionId: string;
history: InputItem[];
metadata: RequestMetadata;
}
): Conversation;
// Usage
const stored = JSON.parse(savedJson);
const restored = Conversation.fromJSON(chaos, stored);
const response = await restored.send('Continue where we left off');Full Example
import { Chaos, Conversation, extractText, hasRisks } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
const conversation = new Conversation(chaos, {
userId: 'user-123',
wallets: [{ address: '0x742d35Cc...', chain: 'ethereum' }],
});
// Turn 1: Ask about portfolio
const r1 = await conversation.send("What's my portfolio value?");
console.log(extractText(r1));
// Turn 2: Follow-up with context
const r2 = await conversation.send('Which asset has the highest allocation?');
console.log(extractText(r2));
// Turn 3: Action with risk check
const r3 = await conversation.send('Swap 50% of my ETH to USDC');
if (hasRisks(r3)) {
console.log('Review risks before signing');
}
// Check stats
console.log(conversation.stats);
// { userTurns: 3, assistantTurns: 3, totalMessages: 6, ... }
// Persist for later
const snapshot = JSON.stringify(conversation.toJSON());
// Restore later
const restored = Conversation.fromJSON(chaos, JSON.parse(snapshot));
const r4 = await restored.send('Actually, make it 25% instead');