Browser JavaScript (ESM)

This guide shows how to use the Athena Intelligence SDK directly in the browser using ESM imports from CDN. Perfect for rapid prototyping, demos, and simple web applications without build tools.

Key features:

  • No build process required - works directly in the browser
  • Full SDK functionality available via ESM imports
  • Type safety with JSDoc comments
  • Real-time interaction examples
  • Production-ready patterns for browser applications
1

Basic ESM Import Setup

Use the SDK directly in your browser with ESM imports:

// Import the SDK from ESM CDN
import { AthenaIntelligenceClient, AthenaIntelligenceError } from 'https://esm.run/@athenaintel/sdk';
// Basic client initialization (uses default production API)
const client = new AthenaIntelligenceClient({
apiKey: API_KEY, // Assumes API_KEY is defined globally
});
// Override baseUrl for custom API endpoints
const customClient = new AthenaIntelligenceClient({
apiKey: API_KEY,
baseUrl: 'https://your-custom-api.example.com', // Custom API endpoint
});
// Use development/localhost environment
const devClient = new AthenaIntelligenceClient({
apiKey: API_KEY,
baseUrl: 'http://localhost:8000', // Local development server
});
console.log('Athena Intelligence client initialized');
2

Simple Agent Interaction

Execute basic agent requests with full error handling:

async function runSimpleAgent() {
try {
console.log('๐Ÿค– Running General Agent...');
const response = await client.agents.general.invoke({
config: {
model: 'gpt-4-turbo-preview',
enabled_tools: ['search'],
},
messages: [
{
content: 'Search for the latest news about artificial intelligence',
role: 'user',
type: 'user',
},
],
});
console.log('โœ… Response received');
// Extract the response content safely
const messages = response.messages || [];
const lastMessage = messages[messages.length - 1];
if (lastMessage?.kwargs?.content) {
console.log('Agent Response:', lastMessage.kwargs.content);
return lastMessage.kwargs.content;
} else {
console.warn('No content in response');
return null;
}
} catch (error) {
if (error instanceof AthenaIntelligenceError) {
console.error(`API Error: ${error.statusCode} - ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
return null;
}
}
// Execute the function
runSimpleAgent().then(result => {
if (result) {
console.log('Success:', result);
}
});
3

Multi-Tool Workflow

Combine multiple tools for complex tasks:

async function runMultiToolWorkflow() {
try {
const request = {
config: {
enabled_tools: ['search', 'browse'],
system_prompt: 'You are a research assistant. Use search and browse tools to gather comprehensive information.',
model: 'gpt-4-turbo-preview',
},
messages: [
{
content: 'Research the latest developments in quantum computing and provide a detailed summary with sources.',
role: 'user',
type: 'user',
},
],
};
console.log('๐Ÿ” Starting multi-tool research...');
const response = await client.agents.general.invoke(request);
// Process the response
const messages = response.messages || [];
messages.forEach((message, index) => {
console.log(`Message ${index + 1}:`);
console.log(` Type: ${message.type}`);
console.log(` Role: ${message.role || 'unknown'}`);
// Handle different content types
const content = message.kwargs?.content || message.content;
if (typeof content === 'string') {
console.log(` Content: ${content.substring(0, 200)}...`);
} else if (Array.isArray(content)) {
console.log(` Content: ${content.length} content parts`);
}
// Check for tool calls
if (message.kwargs?.tool_calls && message.kwargs.tool_calls.length > 0) {
console.log(` Tool Calls: ${message.kwargs.tool_calls.length}`);
}
});
return response;
} catch (error) {
console.error('Multi-tool workflow failed:', error);
return null;
}
}
4

Conversational Interaction

Build interactive conversations with context preservation:

class ConversationManager {
constructor(client) {
this.client = client;
this.messages = [];
this.threadId = null;
}
// Add a system message
addSystemMessage(content) {
this.messages.push({
content,
role: 'system',
type: 'system',
});
}
// Add a user message
addUserMessage(content) {
this.messages.push({
content,
role: 'user',
type: 'user',
});
}
// Send messages and get response
async sendMessage(userInput, config = {}) {
try {
// Add user input to conversation
this.addUserMessage(userInput);
const defaultConfig = {
model: 'gpt-4-turbo-preview',
enabled_tools: ['search'],
};
const request = {
config: { ...defaultConfig, ...config },
messages: [...this.messages],
thread_id: this.threadId,
};
console.log(`๐Ÿ’ฌ Sending message: "${userInput}"`);
const response = await this.client.agents.general.invoke(request);
// Extract assistant response and add to conversation
const responseMessages = response.messages || [];
const lastMessage = responseMessages[responseMessages.length - 1];
if (lastMessage?.kwargs?.content) {
const assistantContent = lastMessage.kwargs.content;
// Add assistant response to conversation history
this.messages.push({
content: assistantContent,
role: 'assistant',
type: 'assistant',
});
console.log('๐Ÿค– Assistant response received');
return {
content: assistantContent,
fullResponse: response,
conversationLength: this.messages.length,
};
} else {
console.warn('No assistant content in response');
return null;
}
} catch (error) {
console.error('Conversation error:', error);
return null;
}
}
// Get conversation history
getHistory() {
return [...this.messages];
}
// Clear conversation
clear() {
this.messages = [];
this.threadId = null;
}
}
// Usage example
async function runConversation() {
const conversation = new ConversationManager(client);
// Set up conversation context
conversation.addSystemMessage('You are a helpful AI assistant specializing in technology and business analysis.');
// First message
const response1 = await conversation.sendMessage(
'What are the key trends in AI for 2024?',
{ enabled_tools: ['search'] }
);
if (response1) {
console.log('Response 1:', response1.content);
}
// Follow-up message with context
const response2 = await conversation.sendMessage(
'Can you provide specific examples of companies implementing these trends?'
);
if (response2) {
console.log('Response 2:', response2.content);
console.log(`Total conversation length: ${response2.conversationLength} messages`);
}
// Show full conversation history
console.log('Full conversation:', conversation.getHistory());
}
5

Understanding AOP Execution

Important: Agent Operating Procedures (AOPs) can take minutes to complete. Always use asynchronous execution to prevent timeouts and enable real-time progress tracking.

How it works:

  1. executeAsync starts execution and returns immediately with a thread_id
  2. The AOP runs in the background on the server
  3. You poll threads.getStatus to monitor progress
  4. When status is completed, extract the final result
6

Basic Async AOP Execution

Execute AOPs asynchronously with proper monitoring:

// Async AOP execution (recommended for production)
async function executeAOP(assetId, userInputs = {}) {
try {
console.log(`๐Ÿš€ Starting async AOP execution: ${assetId}`);
console.log('User inputs:', userInputs);
// Step 1: Start async execution (returns immediately with thread_id)
const asyncResponse = await client.aop.executeAsync({
asset_id: assetId,
user_inputs: userInputs,
});
// executeAsync only STARTS the execution - it does NOT complete it
console.log('โœ… AOP execution initiated (running in background)');
console.log('Thread ID:', asyncResponse.thread_id);
console.log('Status:', asyncResponse.status); // Will be "started" or similar
console.log('AOP Title:', asyncResponse.aop_title);
// Step 2: Monitor execution until it actually completes
const result = await monitorExecution(asyncResponse.thread_id);
return result;
} catch (error) {
console.error('AOP execution failed:', error);
if (error instanceof AthenaIntelligenceError) {
return {
success: false,
error: `API Error: ${error.statusCode} - ${error.message}`,
statusCode: error.statusCode,
};
} else {
return {
success: false,
error: error.message || 'Unknown error',
};
}
}
}
// Progress monitoring function
async function monitorExecution(threadId) {
const maxAttempts = 60; // 5 minutes with 5-second intervals
const pollInterval = 5000;
let consecutiveErrors = 0;
const maxConsecutiveErrors = 3;
console.log(`๐Ÿ“Š Starting progress monitoring for thread: ${threadId}`);
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
// Poll thread status
const status = await client.threads.getStatus(threadId);
// Reset error counter on successful response
consecutiveErrors = 0;
console.log(`[${attempt}/${maxAttempts}] Status: ${status.status} (Updated: ${status.updated_at})`);
// Check if execution completed
if (status.status === 'completed') {
console.log('๐ŸŽ‰ AOP execution completed successfully!');
// Extract final result safely
const conversationAsset = status.conversation_asset;
if (conversationAsset?.last_message?.content) {
const finalContent = conversationAsset.last_message.content;
// Handle string content
if (typeof finalContent === 'string') {
return {
success: true,
status: 'completed',
result: finalContent,
threadId,
conversationAssetId: conversationAsset.conversation_asset_id,
messageCount: conversationAsset.num_messages,
};
}
// Handle multimodal content (array)
if (Array.isArray(finalContent)) {
const textParts = finalContent
.filter(part => part.type === 'text' && part.text)
.map(part => part.text)
.join('\n');
return {
success: true,
status: 'completed',
result: textParts,
threadId,
conversationAssetId: conversationAsset.conversation_asset_id,
messageCount: conversationAsset.num_messages,
isMultimodal: true,
};
}
}
// Completed but no content
return {
success: true,
status: 'completed',
result: 'AOP completed but no final message available',
threadId,
};
} else if (status.status === 'failed') {
console.error('โŒ AOP execution failed');
return {
success: false,
status: 'failed',
error: 'AOP execution failed',
threadId,
};
}
// Still running - wait before next poll
console.log(`โณ Still running... (${status.status})`);
await new Promise(resolve => setTimeout(resolve, pollInterval));
} catch (error) {
consecutiveErrors++;
console.error(`Status check failed (${consecutiveErrors}/${maxConsecutiveErrors}):`, error.message);
// Fail fast if too many consecutive errors
if (consecutiveErrors >= maxConsecutiveErrors) {
return {
success: false,
status: 'error',
error: `Too many consecutive status check failures: ${error.message}`,
threadId,
};
}
// Wait before retrying
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
// Timeout reached
console.warn('โฐ Polling timeout reached');
return {
success: false,
status: 'timeout',
error: 'Monitoring timeout reached - execution may still be running',
threadId,
};
}
// Example usage
const marketAnalysisResult = await executeAOP(
'asset_market_research_aop',
{
company: 'Tesla',
quarter: 'Q3 2024',
analysis_type: 'comprehensive',
}
);
if (marketAnalysisResult.success) {
console.log('โœ… Market analysis result:', marketAnalysisResult.result);
} else {
console.error('โŒ Market analysis failed:', marketAnalysisResult.error);
}
7

Advanced: Custom Progress Callbacks

Add custom progress callbacks for UI updates and analytics:

// Execute AOP with custom progress tracking
async function executeAOPWithProgress(assetId, userInputs = {}, onProgress = null) {
try {
console.log(`๐Ÿš€ Starting async AOP: ${assetId}`);
// Step 1: Start async execution (returns immediately)
const asyncResponse = await client.aop.executeAsync({
asset_id: assetId,
user_inputs: userInputs,
});
console.log('โœ… AOP execution initiated');
console.log('Thread ID:', asyncResponse.thread_id);
console.log('AOP Title:', asyncResponse.aop_title);
// Step 2: Monitor progress with callbacks
const result = await monitorWithCallback(asyncResponse.thread_id, onProgress);
return {
success: result.success,
startResponse: asyncResponse,
finalResult: result,
};
} catch (error) {
console.error('Async AOP execution failed:', error);
return {
success: false,
error: error.message || 'Unknown error',
};
}
}
// Progress monitoring with callback support
async function monitorWithCallback(threadId, onProgress = null) {
const maxAttempts = 120; // 10 minutes for longer workflows
const pollInterval = 5000;
let consecutiveErrors = 0;
const maxConsecutiveErrors = 3;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
const status = await client.threads.getStatus(threadId);
// Reset error counter
consecutiveErrors = 0;
// Call progress callback if provided
if (onProgress) {
onProgress({
attempt,
maxAttempts,
status: status.status,
updatedAt: status.updated_at,
threadId: status.thread_id,
});
}
console.log(`[${attempt}/${maxAttempts}] Status: ${status.status} (${status.updated_at})`);
if (status.status === 'completed') {
console.log('๐ŸŽ‰ AOP execution completed!');
// Extract final result
const conversationAsset = status.conversation_asset;
if (conversationAsset?.last_message?.content) {
const finalContent = conversationAsset.last_message.content;
// Handle string or array content
let resultText;
if (typeof finalContent === 'string') {
resultText = finalContent;
} else if (Array.isArray(finalContent)) {
resultText = finalContent
.filter(part => part.type === 'text' && part.text)
.map(part => part.text)
.join('\n');
} else {
resultText = JSON.stringify(finalContent);
}
return {
success: true,
status: 'completed',
result: resultText,
conversationAssetId: conversationAsset.conversation_asset_id,
messageCount: conversationAsset.num_messages,
threadStatus: status,
};
} else {
return {
success: true,
status: 'completed',
result: 'AOP completed but no final message available',
threadStatus: status,
};
}
} else if (status.status === 'failed') {
console.error('โŒ AOP execution failed');
return {
success: false,
status: 'failed',
error: 'AOP execution failed',
threadStatus: status,
};
}
// Continue polling
await new Promise(resolve => setTimeout(resolve, pollInterval));
} catch (error) {
consecutiveErrors++;
console.error(`Status check failed (${consecutiveErrors}/${maxConsecutiveErrors}):`, error.message);
// Fail fast if too many consecutive errors
if (consecutiveErrors >= maxConsecutiveErrors) {
return {
success: false,
status: 'error',
error: `Too many consecutive failures: ${error.message}`,
};
}
// Wait before retrying
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
console.warn('โฐ Polling timeout reached');
return {
success: false,
status: 'timeout',
error: 'Monitoring timeout reached - execution may still be running',
};
}
// Example usage with progress tracking
const progressCallback = (info) => {
console.log(`๐Ÿ“Š Progress: ${info.attempt}/${info.maxAttempts} - ${info.status}`);
// Update UI or send to analytics
if (typeof window !== 'undefined' && window.updateProgressUI) {
window.updateProgressUI({
percent: (info.attempt / info.maxAttempts) * 100,
status: info.status,
updatedAt: info.updatedAt,
});
}
};
const comprehensiveAnalysis = await executeAOPWithProgress(
'asset_comprehensive_research_aop',
{
company: 'OpenAI',
research_depth: 'comprehensive',
include_financials: 'true',
time_horizon: '2024-2025',
},
progressCallback
);
if (comprehensiveAnalysis.success) {
console.log('โœ… Comprehensive analysis result:', comprehensiveAnalysis.finalResult.result);
} else {
console.error('โŒ Analysis failed:', comprehensiveAnalysis.error);
}
8

Batch Processing with Async Execution

Process multiple AOPs concurrently using async execution:

// Batch AOP execution with async pattern
async function executeBatchAOPs(aopConfigs) {
console.log(`๐Ÿ”„ Starting ${aopConfigs.length} AOPs concurrently...`);
// Step 1: Start all AOPs asynchronously (all return immediately with thread_ids)
const startPromises = aopConfigs.map(async (config, index) => {
try {
console.log(`Starting AOP ${index + 1}: ${config.name || config.assetId}`);
const response = await client.aop.executeAsync({
asset_id: config.assetId,
user_inputs: config.userInputs || {},
});
console.log(`โœ… ${config.name || 'AOP'} started with thread: ${response.thread_id}`);
return {
index,
name: config.name || `AOP ${index + 1}`,
threadId: response.thread_id,
aopTitle: response.aop_title,
success: true,
};
} catch (error) {
console.error(`โŒ Failed to start AOP ${index + 1}:`, error.message);
return {
index,
name: config.name || `AOP ${index + 1}`,
success: false,
error: error.message || 'Unknown error',
};
}
});
const startResults = await Promise.all(startPromises);
// Step 2: Monitor all successful starts until completion
console.log(`๐Ÿ“Š Monitoring ${startResults.filter(r => r.success).length} running AOPs...`);
const monitorPromises = startResults
.filter(result => result.success && result.threadId)
.map(async (result) => {
try {
const finalResult = await monitorExecution(result.threadId);
return {
...result,
...finalResult,
};
} catch (error) {
return {
...result,
success: false,
status: 'error',
error: error.message || 'Monitoring failed',
};
}
});
const finalResults = await Promise.all(monitorPromises);
// Combine failed starts with monitoring results
const allResults = [
...finalResults,
...startResults.filter(r => !r.success),
];
// Calculate summary
const successful = allResults.filter(r => r.success && r.status === 'completed');
const failed = allResults.filter(r => !r.success || r.status !== 'completed');
console.log(`\nโœ… Batch complete: ${successful.length} successful, ${failed.length} failed`);
return {
successful,
failed,
summary: {
total: aopConfigs.length,
successful: successful.length,
failed: failed.length,
},
};
}
// Example batch configuration
const batchConfigs = [
{
name: 'Market Research',
assetId: 'asset_market_research_aop',
userInputs: { company: 'Apple', quarter: 'Q3 2024' },
},
{
name: 'Competitor Analysis',
assetId: 'asset_competitor_analysis_aop',
userInputs: { company: 'Apple', competitors: 'Samsung,Google,Microsoft' },
},
{
name: 'Financial Summary',
assetId: 'asset_financial_analysis_aop',
userInputs: { company: 'Apple', period: 'annual', year: '2024' },
},
];
const batchResults = await executeBatchAOPs(batchConfigs);
console.log('\n=== Batch Results ===');
batchResults.successful.forEach(result => {
console.log(`โœ… ${result.name}: ${result.result?.substring(0, 100)}...`);
});
batchResults.failed.forEach(result => {
console.log(`โŒ ${result.name}: ${result.error}`);
});
console.log(`\nSummary: ${batchResults.summary.successful}/${batchResults.summary.total} completed`);
9

File Upload and Processing

Upload files and process them with AOPs using async execution:

// File upload and processing workflow with async execution
async function uploadAndProcessFile(file, processingAOPId, processingInputs = {}) {
try {
console.log(`๐Ÿ“ Uploading file: ${file.name}`);
// Step 1: Upload the file
const uploadResponse = await client.tools.saveAsset({ file });
if (!uploadResponse.asset_id) {
throw new Error('File upload failed - no asset ID returned');
}
console.log('โœ… File uploaded:', uploadResponse.asset_id);
// Step 2: Start async processing with AOP
console.log('๐Ÿ”„ Starting AOP processing...');
const asyncResponse = await client.aop.executeAsync({
asset_id: processingAOPId,
user_inputs: {
...processingInputs,
file_asset_id: uploadResponse.asset_id,
},
});
console.log('โœ… Processing started with thread:', asyncResponse.thread_id);
// Step 3: Monitor processing until completion
const processingResult = await monitorExecution(asyncResponse.thread_id);
if (processingResult.success) {
return {
success: true,
uploadedAssetId: uploadResponse.asset_id,
processingResult: processingResult.result,
threadId: asyncResponse.thread_id,
conversationAssetId: processingResult.conversationAssetId,
};
} else {
return {
success: false,
uploadedAssetId: uploadResponse.asset_id,
error: processingResult.error || 'Processing failed',
threadId: asyncResponse.thread_id,
};
}
} catch (error) {
console.error('File processing failed:', error);
return {
success: false,
error: error.message || 'Unknown error',
};
}
}
// File input handler
function handleFileUpload(inputElement, processingAOPId) {
inputElement.addEventListener('change', async (event) => {
const file = event.target.files?.[0];
if (!file) {
console.log('No file selected');
return;
}
console.log(`Selected file: ${file.name} (${file.size} bytes)`);
const result = await uploadAndProcessFile(
file,
processingAOPId,
{
analysis_type: 'comprehensive',
extract_insights: 'true',
}
);
if (result.success) {
console.log('File processing completed:', result.processingResult);
} else {
console.error('File processing failed:', result.error);
}
});
}
10

Real-time Data Processing

Process data streams and handle updates:

// Real-time data processor
class RealTimeAOPProcessor {
constructor(client, aopAssetId) {
this.client = client;
this.aopAssetId = aopAssetId;
this.processing = false;
this.queue = [];
this.results = [];
}
// Add data to processing queue
addData(data, metadata = {}) {
this.queue.push({
data,
metadata,
timestamp: new Date().toISOString(),
});
console.log(`๐Ÿ“Š Added data to queue. Queue length: ${this.queue.length}`);
// Auto-process if not currently processing
if (!this.processing) {
this.processQueue();
}
}
// Process queued data
async processQueue() {
if (this.processing || this.queue.length === 0) {
return;
}
this.processing = true;
console.log(`๐Ÿ”„ Processing ${this.queue.length} items...`);
while (this.queue.length > 0) {
const item = this.queue.shift();
try {
const result = await this.processItem(item);
this.results.push(result);
console.log(`โœ… Processed item: ${result.success ? 'success' : 'failed'}`);
} catch (error) {
console.error('Item processing error:', error);
this.results.push({
success: false,
error: error.message,
originalData: item,
});
}
}
this.processing = false;
console.log('๐Ÿ Queue processing complete');
}
// Process individual item with async execution
async processItem(item) {
try {
// Start async execution
const asyncResponse = await this.client.aop.executeAsync({
asset_id: this.aopAssetId,
user_inputs: {
input_data: JSON.stringify(item.data),
metadata: JSON.stringify(item.metadata),
timestamp: item.timestamp,
},
});
console.log(`Processing item with thread: ${asyncResponse.thread_id}`);
// Monitor execution (simplified for real-time processing)
const result = await this.monitorItemExecution(asyncResponse.thread_id);
return {
success: result.success,
result: result.result || 'No result content',
threadId: asyncResponse.thread_id,
originalData: item,
processedAt: new Date().toISOString(),
};
} catch (error) {
return {
success: false,
error: error.message || 'Processing failed',
originalData: item,
processedAt: new Date().toISOString(),
};
}
}
// Simplified monitoring for real-time items (shorter timeout)
async monitorItemExecution(threadId) {
const maxAttempts = 30; // 2.5 minutes for individual items
const pollInterval = 5000;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
const status = await this.client.threads.getStatus(threadId);
if (status.status === 'completed') {
const conversationAsset = status.conversation_asset;
if (conversationAsset?.last_message?.content) {
const content = conversationAsset.last_message.content;
const result = typeof content === 'string'
? content
: Array.isArray(content)
? content.filter(p => p.type === 'text').map(p => p.text).join('\n')
: JSON.stringify(content);
return { success: true, result };
}
return { success: true, result: 'Completed with no content' };
} else if (status.status === 'failed') {
return { success: false, error: 'Execution failed' };
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
} catch (error) {
if (attempt === maxAttempts) {
return { success: false, error: error.message };
}
}
}
return { success: false, error: 'Timeout' };
}
// Get processing results
getResults() {
return [...this.results];
}
// Clear results
clearResults() {
this.results = [];
}
}
// Usage example
const dataProcessor = new RealTimeAOPProcessor(client, 'asset_data_analysis_aop');
// Simulate data stream
const sampleData = [
{ temperature: 23.5, humidity: 45, location: 'NYC' },
{ temperature: 21.2, humidity: 52, location: 'LA' },
{ temperature: 18.7, humidity: 38, location: 'Chicago' },
];
// Add data items with metadata
sampleData.forEach((data, index) => {
dataProcessor.addData(data, {
source: 'sensor_network',
batch_id: 'batch_001',
sequence: index + 1,
});
});
// Wait for processing to complete
setTimeout(() => {
const results = dataProcessor.getResults();
console.log(`๐Ÿ“ˆ Processing complete: ${results.length} results`);
results.forEach((result, index) => {
console.log(`Result ${index + 1}:`, result.success ? result.result : result.error);
});
}, 10000);
11

Error Handling and Debugging

Comprehensive error handling patterns for browser environments:

// Global error handler for SDK operations
class AthenaErrorHandler {
static handleError(error, context = '') {
console.error(`โŒ Error in ${context}:`, error);
if (error instanceof AthenaIntelligenceError) {
const errorInfo = {
type: 'AthenaIntelligenceError',
statusCode: error.statusCode,
message: error.message,
context,
timestamp: new Date().toISOString(),
};
// Log for debugging
console.error('Athena API Error Details:', errorInfo);
// Handle specific error codes
switch (error.statusCode) {
case 401:
console.error('๐Ÿ”‘ Authentication failed - check your API key');
break;
case 404:
console.error('๐Ÿ” Resource not found - check asset IDs');
break;
case 400:
console.error('๐Ÿ“ Bad request - check your input parameters');
break;
case 429:
console.error('๐Ÿšฆ Rate limit exceeded - slow down requests');
break;
case 500:
console.error('๐Ÿฅ Server error - try again later');
break;
default:
console.error(`๐Ÿคท Unknown API error: ${error.statusCode}`);
}
return errorInfo;
} else {
const errorInfo = {
type: 'UnknownError',
message: error.message || 'Unknown error occurred',
context,
timestamp: new Date().toISOString(),
};
console.error('Unknown Error Details:', errorInfo);
return errorInfo;
}
}
// Retry wrapper with exponential backoff
static async withRetry(asyncFn, maxRetries = 3, context = '') {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
console.log(`๐Ÿ”„ Attempt ${attempt}/${maxRetries} for ${context}`);
const result = await asyncFn();
console.log(`โœ… Success on attempt ${attempt} for ${context}`);
return result;
} catch (error) {
lastError = error;
// Don't retry on client errors (4xx)
if (error instanceof AthenaIntelligenceError &&
error.statusCode >= 400 && error.statusCode < 500) {
console.error('โŒ Client error - not retrying');
break;
}
if (attempt < maxRetries) {
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
console.log(`โณ Waiting ${delay}ms before retry...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw this.handleError(lastError, context);
}
}
// Safe execution wrapper with async execution
async function safeExecuteAOP(assetId, userInputs = {}) {
return await AthenaErrorHandler.withRetry(
async () => {
// Start async execution
const asyncResponse = await client.aop.executeAsync({
asset_id: assetId,
user_inputs: userInputs,
});
// Monitor until completion
const result = await monitorExecution(asyncResponse.thread_id);
if (!result.success) {
throw new Error(result.error || 'AOP execution failed');
}
return result;
},
3,
`AOP execution (${assetId})`
);
}
// Usage with comprehensive error handling
try {
const result = await safeExecuteAOP('asset_analysis_aop', {
input: 'market data',
format: 'detailed',
});
console.log('Safe execution result:', result);
} catch (errorInfo) {
console.error('Final error after retries:', errorInfo);
// Handle in UI
if (typeof window !== 'undefined' && window.showErrorMessage) {
window.showErrorMessage(`Failed to execute AOP: ${errorInfo.message}`);
}
}
12

Debug and Development Utilities

Helpful utilities for debugging in browser console:

// Debug utilities for browser development
window.athenaDebug = {
// Test connection
async testConnection() {
try {
const userInfo = await client.me.get();
console.log('โœ… Connection successful:', userInfo);
return true;
} catch (error) {
console.error('โŒ Connection failed:', error);
return false;
}
},
// List available assets
async listAssets(limit = 10) {
try {
const assets = await client.assets.list({ limit });
console.log(`๐Ÿ“ Found ${assets.total} assets (showing first ${limit}):`);
assets.items.forEach((asset, index) => {
console.log(`${index + 1}. ${asset.title} (${asset.athena_original_type})`);
console.log(` ID: ${asset.id}`);
console.log(` Created: ${asset.created_at}`);
});
return assets;
} catch (error) {
console.error('Failed to list assets:', error);
return null;
}
},
// Quick AOP test with async execution
async testAOP(assetId, userInputs = {}) {
console.log(`๐Ÿงช Testing AOP: ${assetId}`);
console.log('User inputs:', userInputs);
try {
// Start async execution
const asyncResponse = await client.aop.executeAsync({
asset_id: assetId,
user_inputs: userInputs,
});
console.log('AOP started:', {
threadId: asyncResponse.thread_id,
aopTitle: asyncResponse.aop_title,
status: asyncResponse.status,
});
// Monitor execution (short timeout for testing)
const maxAttempts = 30; // 2.5 minutes
const pollInterval = 5000;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const status = await client.threads.getStatus(asyncResponse.thread_id);
console.log(`[${attempt}/${maxAttempts}] Status: ${status.status}`);
if (status.status === 'completed') {
console.log('โœ… Test completed successfully');
console.log('Final result:', {
conversationAssetId: status.conversation_asset?.conversation_asset_id,
messageCount: status.conversation_asset?.num_messages,
hasContent: !!status.conversation_asset?.last_message?.content,
});
return status;
} else if (status.status === 'failed') {
console.error('โŒ Test failed');
return status;
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
console.warn('โฐ Test timeout reached');
return null;
} catch (error) {
console.error('AOP test failed:', error);
return null;
}
},
// Monitor thread
async monitorThread(threadId) {
try {
const status = await client.threads.getStatus(threadId);
console.log('Thread status:', {
id: threadId,
status: status.status,
updatedAt: status.updated_at,
hasConversationAsset: !!status.conversation_asset,
conversationState: status.conversation_asset?.state,
messageCount: status.conversation_asset?.num_messages,
});
return status;
} catch (error) {
console.error('Thread monitoring failed:', error);
return null;
}
},
};
// Development helper
console.log('๐Ÿ› ๏ธ Athena Debug utilities available:');
console.log(' athenaDebug.testConnection() - Test API connection');
console.log(' athenaDebug.listAssets(limit) - List workspace assets');
console.log(' athenaDebug.testAOP(assetId, inputs) - Test AOP execution');
console.log(' athenaDebug.monitorThread(threadId) - Check thread status');
13

Complete Browser Example

Hereโ€™s a complete working example that demonstrates all patterns:

// Complete browser implementation
import { AthenaIntelligenceClient, AthenaIntelligenceError } from 'https://esm.run/@athenaintel/sdk';
async function initializeAthenaApp() {
try {
// Initialize client with optional baseUrl override
const client = new AthenaIntelligenceClient({
apiKey: API_KEY,
// Optional: override baseUrl for custom environments
// baseUrl: 'https://your-custom-api.example.com', // Custom API
// baseUrl: 'http://localhost:8000', // Local development
});
console.log('๐Ÿš€ Athena Intelligence SDK loaded');
// Test connection
const userInfo = await client.users.me();
console.log('๐Ÿ‘ค User:', userInfo.email);
console.log('๐Ÿ‘ค Name:', userInfo.first_name, userInfo.last_name);
// Example: Quick agent interaction
const quickResponse = await client.agents.general.invoke({
config: { model: 'gpt-4-turbo-preview' },
messages: [
{
content: 'Hello! Can you help me understand how AOPs work?',
role: 'user',
type: 'user',
},
],
});
const agentResponse = quickResponse.messages?.[quickResponse.messages.length - 1]?.kwargs?.content;
console.log('๐Ÿค– Agent says:', agentResponse);
// Example: Async AOP execution
console.log('๐Ÿš€ Starting async AOP execution...');
const asyncResponse = await client.aop.executeAsync({
asset_id: 'asset_example_aop',
user_inputs: {
topic: 'browser SDK usage',
format: 'comprehensive',
},
});
console.log('โœ… AOP initiated with thread:', asyncResponse.thread_id);
console.log('๐Ÿ“‹ AOP Title:', asyncResponse.aop_title);
// Monitor execution (simplified example)
console.log('๐Ÿ“Š Monitoring execution...');
const maxAttempts = 30;
const pollInterval = 5000;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const status = await client.threads.getStatus(asyncResponse.thread_id);
console.log(`[${attempt}/${maxAttempts}] Status: ${status.status}`);
if (status.status === 'completed') {
console.log('๐ŸŽ‰ AOP execution completed!');
const finalContent = status.conversation_asset?.last_message?.content;
if (finalContent) {
const result = typeof finalContent === 'string'
? finalContent
: Array.isArray(finalContent)
? finalContent.filter(p => p.type === 'text').map(p => p.text).join('\n')
: JSON.stringify(finalContent);
console.log('๐Ÿ“ AOP Output:', result);
} else {
console.log('โš ๏ธ No final output from AOP');
}
break;
} else if (status.status === 'failed') {
console.error('โŒ AOP execution failed');
break;
}
if (attempt < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
// Make client available globally for debugging
window.athenaClient = client;
console.log('๐ŸŒ Client available as window.athenaClient');
return {
client,
userInfo,
ready: true,
};
} catch (error) {
console.error('โŒ Initialization failed:', error);
if (error instanceof AthenaIntelligenceError) {
console.error(`API Error: ${error.statusCode} - ${error.message}`);
}
return {
client: null,
ready: false,
error: error.message,
};
}
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeAthenaApp);
} else {
initializeAthenaApp();
}