Examples

Practical examples of using the Agentuity JavaScript SDK

This section provides practical examples of using the Agentuity JavaScript SDK for common use cases.

Basic Agent Implementation

Here's a complete example of a basic agent that processes JSON requests and returns JSON responses:

import { AgentHandler } from '@agentuity/sdk';
 
// Agent handler function
const handler: AgentHandler = async (request, response, context) => {
  try {
    // Get the request data
    const data = request.data.json;
    const name = data.name || 'Guest';
    
    // Log the request
    context.logger.info(`Received greeting request for ${name}`);
    
    // Return a personalized greeting
    return response.json({
      message: `Hello, ${name}! Welcome to Agentuity.`,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    // Handle errors
    context.logger.error('Error processing request', error);
    return response.json({ 
      error: 'Failed to process request',
      message: error instanceof Error ? error.message : 'Unknown error'
    });
  }
};
 
export default handler;

Key-Value Storage Usage

This example demonstrates how to use the key-value storage API to store and retrieve user preferences:

import { AgentHandler } from '@agentuity/sdk';
 
const handler: AgentHandler = async (request, response, context) => {
  const { action, userId, preferences } = request.data.json;
  
  switch (action) {
    case 'get': {
      // Retrieve user preferences
      const data = await context.kv.get('user-preferences', userId);
      
      if (!data) {
        return response.json({ message: 'No preferences found' });
      }
      
      // Convert ArrayBuffer to string and parse as JSON
      const prefsString = new TextDecoder().decode(data);
      const userPrefs = JSON.parse(prefsString);
      
      return response.json({ preferences: userPrefs });
    }
    
    case 'set': {
      // Store user preferences
      await context.kv.set(
        'user-preferences', 
        userId, 
        JSON.stringify(preferences),
        // Optional TTL (30 days in seconds)
        60 * 60 * 24 * 30
      );
      
      return response.json({ message: 'Preferences saved successfully' });
    }
    
    case 'delete': {
      // Delete user preferences
      await context.kv.delete('user-preferences', userId);
      return response.json({ message: 'Preferences deleted successfully' });
    }
    
    default:
      return response.json({ error: 'Invalid action' });
  }
};
 
export default handler;

Vector Storage Usage

This example demonstrates how to use the vector storage API for semantic search:

import { AgentHandler } from '@agentuity/sdk';
 
const handler: AgentHandler = async (request, response, context) => {
  const { action, query, products } = request.data.json;
  
  switch (action) {
    case 'index': {
      // Index products in vector storage
      if (!Array.isArray(products) || products.length === 0) {
        return response.json({ error: 'No products to index' });
      }
      
      // Prepare documents for vector storage
      const documents = products.map(product => ({
        document: product.description,
        metadata: {
          id: product.id,
          name: product.name,
          price: product.price,
          category: product.category
        }
      }));
      
      // Store in vector database
      const ids = await context.vector.upsert('products', ...documents);
      
      return response.json({ 
        message: `Indexed ${ids.length} products successfully`,
        ids
      });
    }
    
    case 'search': {
      // Search for products
      if (!query) {
        return response.json({ error: 'Query is required' });
      }
      
      // Search vector storage
      const results = await context.vector.search('products', {
        query,
        limit: 5,
        similarity: 0.7
      });
      
      // Format results
      const formattedResults = results.map(result => ({
        ...result.metadata,
        similarity: 1 - result.distance // Convert distance to similarity score
      }));
      
      return response.json({ 
        results: formattedResults,
        count: formattedResults.length
      });
    }
    
    case 'delete': {
      // Delete products from vector storage
      if (!Array.isArray(products) || products.length === 0) {
        return response.json({ error: 'No product IDs to delete' });
      }
      
      const count = await context.vector.delete('products', ...products);
      
      return response.json({ 
        message: `Deleted ${count} products successfully` 
      });
    }
    
    default:
      return response.json({ error: 'Invalid action' });
  }
};
 
export default handler;

Agent Communication Example

This example demonstrates how agents can communicate with each other:

import { AgentHandler } from '@agentuity/sdk';
 
const handler: AgentHandler = async (request, response, context) => {
  const { task, data } = request.data.json;
  
  // Log the incoming request
  context.logger.info(`Received task: ${task}`);
  
  switch (task) {
    case 'process-data': {
      // Get a reference to the data processing agent
      const processingAgent = await context.getAgent({ 
        name: 'data-processor'
      });
      
      // Invoke the data processing agent
      const processingResult = await processingAgent.run(
        { data },
        'application/json'
      );
      
      // Get a reference to the notification agent
      const notificationAgent = await context.getAgent({
        name: 'notification-sender'
      });
      
      // Invoke the notification agent with the processing result
      await notificationAgent.run(
        { 
          message: 'Data processing completed',
          result: processingResult
        },
        'application/json'
      );
      
      return response.json({ 
        message: 'Task orchestrated successfully',
        processingResult
      });
    }
    
    case 'handoff': {
      // Handoff to another agent
      return response.handoff(
        { name: 'data-processor' },
        { data },
        'application/json',
        { source: 'orchestrator' }
      );
    }
    
    default:
      return response.json({ error: 'Unknown task' });
  }
};
 
export default handler;

Error Handling Example

This example demonstrates comprehensive error handling in an agent:

import { AgentHandler } from '@agentuity/sdk';
 
// Custom error classes
class ValidationError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ValidationError';
  }
}
 
class ResourceNotFoundError extends Error {
  constructor(resourceId: string) {
    super(`Resource not found: ${resourceId}`);
    this.name = 'ResourceNotFoundError';
  }
}
 
const handler: AgentHandler = async (request, response, context) => {
  try {
    // Get the request data
    const data = request.data.json;
    
    // Validate the request
    if (!data.resourceId) {
      throw new ValidationError('resourceId is required');
    }
    
    // Log the request
    context.logger.info(`Processing resource: ${data.resourceId}`);
    
    // Simulate resource lookup
    const resource = await lookupResource(data.resourceId, context);
    
    // Process the resource
    const result = await processResource(resource, context);
    
    // Return the result
    return response.json({ 
      message: 'Resource processed successfully',
      result
    });
  } catch (error) {
    // Handle different types of errors
    if (error instanceof ValidationError) {
      context.logger.warn(`Validation error: ${error.message}`);
      return response.json({ 
        error: 'Validation error',
        message: error.message
      });
    }
    
    if (error instanceof ResourceNotFoundError) {
      context.logger.warn(`Resource not found: ${error.message}`);
      return response.json({ 
        error: 'Resource not found',
        message: error.message
      });
    }
    
    // Handle unexpected errors
    context.logger.error('Unexpected error', error);
    return response.json({ 
      error: 'Internal server error',
      message: 'An unexpected error occurred'
    });
  }
};
 
// Helper functions
async function lookupResource(resourceId: string, context: any) {
  // Simulate resource lookup
  const resource = await context.kv.get('resources', resourceId);
  
  if (!resource) {
    throw new ResourceNotFoundError(resourceId);
  }
  
  return JSON.parse(new TextDecoder().decode(resource));
}
 
async function processResource(resource: any, context: any) {
  // Simulate resource processing
  context.logger.debug('Processing resource', resource);
  
  // Add processing logic here
  
  return {
    id: resource.id,
    status: 'processed',
    timestamp: new Date().toISOString()
  };
}
 
export default handler;

Telemetry Example

This example demonstrates how to use OpenTelemetry for tracing and metrics:

import { AgentHandler } from '@agentuity/sdk';
import { SpanStatusCode } from '@opentelemetry/api';
 
const handler: AgentHandler = async (request, response, context) => {
  return context.tracer.startActiveSpan('process-request', async (span) => {
    try {
      // Add attributes to the span
      span.setAttribute('trigger', request.trigger());
      
      // Get the request data
      const data = request.data.json;
      span.setAttribute('data.type', typeof data);
      
      // Create a child span for data processing
      return await context.tracer.startActiveSpan('process-data', async (childSpan) => {
        try {
          // Add event to the span
          childSpan.addEvent('processing-started', {
            timestamp: Date.now()
          });
          
          // Simulate data processing
          const result = await processData(data, context);
          
          // Add event to the span
          childSpan.addEvent('processing-completed', {
            timestamp: Date.now(),
            resultSize: JSON.stringify(result).length
          });
          
          // Set span status
          childSpan.setStatus({ code: SpanStatusCode.OK });
          
          return response.json(result);
        } catch (error) {
          // Record exception in the span
          childSpan.recordException(error as Error);
          childSpan.setStatus({
            code: SpanStatusCode.ERROR,
            message: (error as Error).message
          });
          
          throw error;
        } finally {
          // End the child span
          childSpan.end();
        }
      });
    } catch (error) {
      // Record exception in the parent span
      span.recordException(error as Error);
      span.setStatus({
        code: SpanStatusCode.ERROR,
        message: (error as Error).message
      });
      
      // Log the error
      context.logger.error('Error processing request', error);
      
      // Return error response
      return response.json({
        error: 'Failed to process request',
        message: (error as Error).message
      });
    } finally {
      // End the parent span
      span.end();
    }
  });
};
 
async function processData(data: any, context: any) {
  // Simulate data processing
  await new Promise(resolve => setTimeout(resolve, 100));
  
  return {
    processed: true,
    input: data,
    timestamp: new Date().toISOString()
  };
}
 
export default handler;

On this page