Sophisticated AI chatbot platform for Russian marketplace sellers featuring real-time streaming, LangGraph integration, and advanced tool execution capabilities.
Experience the real-time streaming and tool execution capabilities
Server-Sent Events implementation with chunk-based content delivery
LangGraph-powered AI agent with dynamic marketplace tool integration
Optimized chat interface across all devices and screen sizes
Solving complex e-commerce challenges with intelligent AI
Russian marketplace sellers on Wildberries needed an intelligent way to analyze their business data, manage products, and optimize performance through natural language interactions.
Built a sophisticated AI platform that bridges natural language conversations with complex marketplace operations through real-time streaming and intelligent tool execution.
Delivered a production-ready platform that transforms how sellers interact with their marketplace data, providing instant insights and automated management capabilities.
Server-Sent Events streaming with conversation persistence
LangGraph state machine with dynamic tool execution
AES-256-GCM encryption with Row Level Security
Comprehensive marketplace data analysis and insights
Mobile-first chat interface with adaptive layouts
User isolation and resource management for SaaS
Deep dive into the sophisticated architecture and implementation
Multi-layered architecture featuring Next.js frontend, Express.js API layer, LangGraph AI agent system, and Supabase database with real-time streaming capabilities.
Challenge: Implementing real-time AI response streaming with tool execution support and graceful error handling.
Solution: Built custom SSE system with event-based architecture supporting conversation chunks, tool execution events, and mid-stream cancellation.
// Custom SSE implementation with tool execution events
export class StreamController {
private encoder = new TextEncoder();
private controller: ReadableStreamDefaultController;
sendEvent(event: string, data: any): void { ... }
sendChunk(content: string): void { ... }
// ... more methods
}
// Custom SSE implementation with tool execution events
export class StreamController {
private encoder = new TextEncoder();
private controller: ReadableStreamDefaultController;
constructor(controller: ReadableStreamDefaultController) {
this.controller = controller;
}
sendEvent(event: string, data: any): void {
const eventData = JSON.stringify(data);
this.controller.enqueue(
this.encoder.encode(`event: ${event}\ndata: ${eventData}\n\n`)
);
}
sendChunk(content: string): void {
this.sendEvent('chunk', content);
}
sendToolExecution(toolEvents: Array<{message: string, toolName: string}>): void {
this.sendEvent('tool_execution', toolEvents);
}
sendToolComplete(toolEvent: {message: string, toolName: string, status: 'success' | 'error'}): void {
this.sendEvent('tool_complete', toolEvent);
}
sendError(error: string): void {
this.sendEvent('error', { error });
}
sendEnd(): void {
this.sendEvent('end', {});
this.controller.close();
}
close(): void {
this.controller.close();
}
}
Impact: Provides ChatGPT-like real-time experience with transparent tool execution and streaming responses.
Challenge: Creating intelligent AI agent that can dynamically execute marketplace tools while maintaining conversation context.
Solution: Implemented LangGraph state machine with tool binding, enabling seamless transitions between conversation and API operations.
// LangGraph agent with dynamic tool execution
private createAgent(userId?: string, includeWildberriesTools: boolean = false) {
const model = this.createChatModel();
const tools = includeWildberriesTools && userId ? this.createTools(userId) : [];
// Define agent node, conditional logic, and build graph
return workflow.compile();
}
// LangGraph agent with dynamic tool execution
private createAgent(userId?: string, includeWildberriesTools: boolean = false) {
const model = this.createChatModel();
// Create tools if needed
const tools = includeWildberriesTools && userId ? this.createTools(userId) : [];
const toolNode = tools.length > 0 ? new ToolNode(tools) : null;
// Bind tools to model if available
const boundModel = tools.length > 0 ? model.bindTools(tools) : model;
// Define agent node
const callModel = async (state: typeof AgentState.State) => {
try {
//console.log('state.messages', state.messages);
const response = await boundModel.invoke(state.messages);
console.log('response', response);
// Track token usage if we have userId
if (state.userId && response.usage_metadata) {
await this.trackTokenUsageFromMetadata(
response.usage_metadata,
state.modelName || MODEL_CONFIGS.GPT4O_MINI,
state.userId
);
}
return { messages: [response] };
} catch (error) {
logger.error('Error in callModel node:', error);
throw error;
}
};
// Define conditional logic
const shouldContinue = (state: typeof AgentState.State) => {
const messages = state.messages;
const lastMessage = messages[messages.length - 1] as AIMessage;
// If no tools are available or no tool calls, end
if (!tools.length || !lastMessage.tool_calls?.length) {
return END;
}
return "tools";
};
// Build the graph
const workflow = new StateGraph(AgentState)
.addNode("agent", callModel)
.addEdge("__start__", "agent");
// Add tools node and edges if we have tools
if (toolNode && tools.length > 0) {
workflow
.addNode("tools", toolNode)
.addConditionalEdges("agent", shouldContinue)
.addEdge("tools", "agent");
} else {
workflow.addEdge("agent", END);
}
return workflow.compile();
}
Impact: Enables complex multi-step workflows like product analysis and pricing optimization in single conversation flow.
Challenge: Securing sensitive marketplace API keys while implementing fair usage policies for SaaS platform.
Solution: Comprehensive security with AES-256-GCM encryption, Row Level Security, real-time usage tracking, and audit logging.
// AES-256-GCM API key encryption
export class ApiKeysService {
private readonly ALGORITHM = 'aes-256-gcm';
private decryptApiKey(encryptedData: string, iv: string, tag: string): string { ... }
async getApiKey(userId: string, service: string): Promise { ... }
}
// AES-256-GCM API key encryption
export class ApiKeysService {
private supabase: SupabaseClient;
private readonly ENCRYPTION_KEY: string;
private readonly ALGORITHM = 'aes-256-gcm';
constructor() {
this.supabase = getSupabaseClient();
this.ENCRYPTION_KEY = process.env.API_KEYS_ENCRYPTION_KEY || '';
if (!this.ENCRYPTION_KEY) {
logger.error('API_KEYS_ENCRYPTION_KEY not set in environment variables');
throw new Error('API_KEYS_ENCRYPTION_KEY not set in environment variables');
}
}
/**
* Decrypt an API key
*/
private decryptApiKey(encryptedData: string, iv: string, tag: string): string {
const key = Buffer.from(this.ENCRYPTION_KEY, 'hex');
const decipher = crypto.createDecipheriv(this.ALGORITHM, key, Buffer.from(iv, 'hex'));
decipher.setAuthTag(Buffer.from(tag, 'hex'));
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
/**
* Get an API key for a user and service
*/
async getApiKey(userId: string, service: string): Promise {
try {
const { data, error } = await this.supabase
.from('user_api_keys')
.select('api_key')
.eq('user_id', userId)
.eq('service', service.toLowerCase())
.single();
if (error) {
if (error.code === 'PGRST116') {
// No rows returned
return null;
}
logger.error('Failed to get API key', {
error: error.message,
userId,
service
});
throw new Error(`Failed to retrieve API key: ${error.message}`);
}
if (!data || !data.api_key) {
return null;
}
// Decrypt the API key
const [iv, tag, encrypted] = data.api_key.split(':');
const decryptedApiKey = this.decryptApiKey(encrypted, iv, tag);
return decryptedApiKey;
} catch (error) {
logger.error('Error getting API key', {
error: error instanceof Error ? error.message : String(error),
userId,
service
});
throw error;
}
}
/...
}
Impact: Achieved enterprise-grade security compliance with comprehensive encryption and audit logging.
Challenge: Integrating complex, rate-limited Wildberries marketplace APIs with intelligent error handling for AI consumption.
Solution: Built comprehensive service layer with automatic retry logic, Zod validation, and seamless AI-to-API communication.
// Robust marketplace API integration
export function getWildberriesSellerProductCardsTool(userId: string) {
return tool(async (input) => {
const apiKey = await getWildberriesApiKey(userId);
const response = await axios.post('https://content-api-sandbox.wildberries.ru/...');
return JSON.stringify({ success: true, data: response.data });
}, { name: "get_wildberries_seller_product_cards", ... });
}
// Robust marketplace API integration
/**
* Create a Wildberries Seller Products tool for fetching seller's listed products
* Based on: https://dev.wildberries.ru/openapi/work-with-products#tag/Kartochki-tovarov/paths/~1content~1v2~1get~1cards~1list/post
*/
export function getWildberriesSellerProductCardsTool(userId: string) {
return tool(
async (input) => {
try {
// Get the user's Wildberries API key
const apiKey = await getWildberriesApiKey(userId);
if (!apiKey) {
return JSON.stringify({
error: "I couldn't find your Wildberries API key.",
success: false,
});
}
// Build request body from validated input
const requestBody = {
settings: {
cursor: {
limit: input.limit || 100,
...(input.updatedAt && { updatedAt: input.updatedAt }),
...(input.nmID && { nmID: input.nmID })
},
filter: {
textSearch: input.textSearch || "",
allowedCategoriesOnly: input.allowedCategoriesOnly || false
}
},
...(input.withPhoto !== undefined && { withPhoto: input.withPhoto })
};
logger.info('Making Wildberries Seller Products API request', {
userId,
endpoint: '/content/v2/get/cards/list',
requestBody
});
// Make POST request to Wildberries Content API
const response = await axios.post(
'https://content-api-sandbox.wildberries.ru/content/v2/get/cards/list',
requestBody,
{
headers: {
'Authorization': apiKey,
'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'MP-Bot/1.0'
},
timeout: 30000
}
);
logger.info('Wildberries Seller Products API request successful', {
userId,
statusCode: response.status,
cardsCount: response.data?.cards?.length || 0,
cursor: response.data?.cursor
});
// Return structured response as string (required by LangChain tools)
return JSON.stringify({
success: true,
data: response.data,
totalCards: response.data?.cards?.length || 0,
cursor: response.data?.cursor,
requestParams: requestBody,
metadata: {
endpoint: "get_wildberries_seller_product_cards",
rateLimit: "100 requests per minute",
apiCategory: "Content"
}
});
} catch (error) {
return handleWildberriesError(error, userId);
}
},
{
name: "get_wildberries_seller_product_cards",
description: `Fetch seller's own listed product cards from Wildberries.
This tool retrieves the seller's product inventory, including product details, prices, characteristics, and status.
Use this when users ask about:
- Their own products listed on Wildberries
- Inventory management
- Product cards and their details
- Product status and characteristics
- Managing seller's catalog`,
schema: getWildberriesSellerProductCardsSchema
}
);
}
Impact: Achieved robust marketplace integration with comprehensive error handling and graceful degradation.
Modern technologies powering enterprise-grade AI platform
Comprehensive database schema featuring user management, conversation persistence, encrypted API key storage, token usage tracking, and Row Level Security (RLS) policies.
Custom SSE implementation with streaming responses and efficient memory management
AES-256-GCM encryption, Row Level Security, CSRF protection, and comprehensive audit logging
Modular design with horizontal scaling capabilities and multi-tenant resource management
45% test coverage, comprehensive error handling, performance monitoring, and deployment optimization
Key challenges overcome and lessons learned
Designed scalable agent architecture with comprehensive documentation for future expansion to specialized AI agents
Built robust Express.js API with enterprise security, comprehensive error handling, and efficient database operations
Implemented sophisticated LangGraph agent with tool execution capabilities and real-time streaming responses
Created responsive Next.js frontend with real-time chat interface, advanced markdown rendering, and mobile optimization
Integrated complex marketplace APIs with rate limiting and seamless AI tool execution
Achieved enterprise-grade performance with comprehensive testing, monitoring, and security auditing
Implementing ChatGPT-like streaming with tool execution transparency required custom SSE architecture with event processing and graceful error handling.
Securing sensitive API keys while maintaining user experience required comprehensive encryption and usage tracking implementation.
Creating responsive chat interface that works seamlessly across devices while maintaining real-time performance was technically challenging.
Measurable outcomes and technical achievements
Deep understanding of LangGraph state machines, tool orchestration, and AI agent workflows for complex business applications.
Advanced expertise in Server-Sent Events, streaming architectures, and real-time communication patterns for web applications.
Comprehensive knowledge of encryption, authentication, usage tracking, and security best practices for SaaS platforms.
Expand to specialized AI agents for product management, analytics, pricing strategy, and customer support with intelligent routing.
Implement machine learning models for predictive analytics, market trend analysis, and automated business insights.
Adding file upload functionality to the bot will enhance the user experience and make the bot more user-friendly.