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;