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 = await 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 } = await request.data.json();
switch (action) {
case 'get': {
// Retrieve user preferences
const result = await context.kv.get('user-preferences', userId);
if (!result.exists) {
return response.json({ message: 'No preferences found' });
}
// Access data using the Data interface
const userPrefs = await result.data.json();
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 } = await 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 (!products || !Array.isArray(products) || products.length === 0) {
return response.json({ error: 'No product IDs to delete' });
}
// Support both single and bulk deletion
const productIds = products.map(p => p.id || p);
const count = await context.vector.delete('products', ...productIds);
return response.json({
message: `Deleted ${count} product(s) successfully`,
deletedCount: count
});
}
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 } = await 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 = await 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 result = await context.kv.get('resources', resourceId);
if (!result.exists) {
throw new ResourceNotFoundError(resourceId);
}
return await result.data.json();
}
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 = await 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;
Welcome Function Example
This example demonstrates how to customize the initial appearance of DevMode when it starts interacting with your agents:
// agent.ts
import type { AgentHandler, AgentWelcomeResult } from '@agentuity/sdk';
export const welcome = (): AgentWelcomeResult => {
return {
welcome: "Welcome to my Agent! How can I help you today?",
prompts: [
{
data: "What can you do?",
contentType: "text/plain",
},
{
data: "Tell me about yourself",
contentType: "text/plain",
}
],
};
};
const handler: AgentHandler = async (request, response, context) => {
// Agent logic
return response.text('Hello, World!');
};
export default handler;
Real-World Example
Here's a more comprehensive example from the React Miami 2025 Concierge template:
// ConciergeHost/index.ts
import type { AgentWelcomeResult } from "@agentuity/sdk";
export const welcome = (): AgentWelcomeResult => {
return {
welcome: "Welcome to the React Miami 2025 Concierge! How can I help you today?",
prompts: [
{
data: "Where should I go for dinner in Miami, tonight?",
contentType: "text/plain",
},
{
data: "What sessions about React hooks are happening today?",
contentType: "text/plain",
},
{
data: "Tell me more about [Speaker Name]'s background",
contentType: "text/plain",
},
{
data: "I'm hungry and looking for Cuban food near the conference",
contentType: "text/plain",
},
{
data: "What is Agentuity all about?",
contentType: "text/plain",
},
{
data: "What can I do?",
contentType: "text/plain",
},
],
};
};
Note that in this example, some prompts use plain text directly while others use base64 encoding. Both approaches work, but using base64 encoding is recommended for consistency.
OpenAI Streaming Example
This example demonstrates how to stream responses from OpenAI models in your Agentuity agent. Streaming allows for a more responsive user experience by displaying the AI's response as it's being generated, rather than waiting for the entire response to complete.
import type { AgentRequest, AgentResponse, AgentContext } from "@agentuity/sdk";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
export default async function Agent(
req: AgentRequest,
resp: AgentResponse,
ctx: AgentContext,
) {
const { textStream } = streamText({
model: openai("gpt-4o"),
prompt: "Invent a new holiday and describe its traditions.",
});
return resp.stream(textStream);
}
How It Works
- We import the necessary types from
@agentuity/sdk
and utilities from the Vercel AI SDK (ai
and@ai-sdk/openai
). - The
streamText
function from the Vercel AI SDK creates a streaming text response from OpenAI. - We configure the stream with the
gpt-4o
model and a prompt. - The
textStream
object contains the streaming response from OpenAI. - We return the stream using
resp.stream()
, which handles the streaming response in the Agentuity platform.
Dependencies
To use this example, you'll need to install the following dependencies:
npm install ai @ai-sdk/openai
Agent-to-Agent Streaming Example
This example demonstrates how to call another agent and stream its response back to the client. This is useful for creating agent workflows where one agent processes a request and streams the response through another agent.
import type { AgentRequest, AgentResponse, AgentContext } from "@agentuity/sdk";
export default async function Agent(
req: AgentRequest,
resp: AgentResponse,
ctx: AgentContext,
) {
// Setup to talk to another agent
const agent = await ctx.getAgent({
name: 'HistoryExpert',
});
// Invoke the agent
const agentResponse = await agent.run({
data: 'What engine did a P-51D Mustang use?',
});
// Get the stream from the agent
const stream = await agentResponse.data.stream();
// Return the stream to the client
return resp.stream(stream);
}
How It Works
- We use
ctx.getAgent()
to get a reference to another agent named 'HistoryExpert'. - We invoke the agent with
agent.run()
, passing the data we want to process. - We retrieve the stream from the agent's response using
agentResponse.data.stream()
. - Finally, we return the stream to the client using
resp.stream()
, which passes the streaming response through our agent.
This pattern allows you to:
- Chain multiple agents together in a workflow
- Maintain a streaming experience end-to-end
- Process or transform streaming data between agents
Learn More About Streaming
For more information about agent streaming, check out these resources:
- Agents just want to have streams - Blog post explaining the importance and implementation of streaming in agents
- Streams for agents! - YouTube video demonstration of agent streaming capabilities
Need Help?
Join our Community for assistance or just to hang with other humans building agents.
Send us an email at hi@agentuity.com if you'd like to get in touch.
Please Follow us on
If you haven't already, please Signup for your free account now and start building your first agent!