Skip to main content

Building Applications

Now let's build something useful. We'll create three types of applications, each building on what you've learned.

Application 1: Smart File Organizer

Let's build an agent that can organize messy directories:

// file-organizer.ts
import 'dotenv/config';
import { loadConfigFile, createSaikiAgent } from '@truffle-ai/saiki';

const config = await loadConfigFile('./agents/saiki.yml');
const agent = await createSaikiAgent(config);

console.log("🗂️ Smart File Organizer");
console.log("I can help organize your files by type, date, or project.\n");

const task = "Look at the current directory and suggest how to organize these files. Create folders if needed.";
const response = await agent.run(task);
console.log(response);

What you're learning: Single-purpose agents with clear objectives work best.

Making it Interactive

Let's add some user input:

// interactive-organizer.ts
import 'dotenv/config';
import { loadConfigFile, createSaikiAgent } from '@truffle-ai/saiki';
import readline from 'readline';

const agent = await createSaikiAgent(
await loadConfigFile('./agents/saiki.yml')
);

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

console.log("🗂️ Smart File Organizer");
console.log("Commands: 'analyze', 'organize by type', 'organize by date', 'exit'\n");

function askQuestion() {
rl.question("What would you like to do? ", async (input) => {
if (input.toLowerCase() === 'exit') {
rl.close();
return;
}

let task;
switch (input.toLowerCase()) {
case 'analyze':
task = "Analyze the current directory and tell me what files are here.";
break;
case 'organize by type':
task = "Organize files by type (documents, images, code, etc.). Create folders and move files.";
break;
case 'organize by date':
task = "Organize files by creation date. Create year/month folders and move files.";
break;
default:
task = input;
}

try {
const response = await agent.run(task);
console.log(`\n🤖 ${response}\n`);
} catch (error) {
console.log(`❌ Error: ${error.message}\n`);
}

askQuestion();
});
}

askQuestion();

Application 2: Interactive Code Helper

Now let's build something interactive for developers:

// code-helper.ts
import 'dotenv/config';
import { loadConfigFile, createSaikiAgent } from '@truffle-ai/saiki';
import readline from 'readline';

const agent = await createSaikiAgent(
await loadConfigFile('./agents/saiki.yml')
);

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

console.log("💻 Your Code Helper is ready!");
console.log("Ask me about code, files, or type 'exit' to quit.\n");

function askQuestion() {
rl.question("You: ", async (input) => {
if (input.toLowerCase() === 'exit') {
rl.close();
return;
}

try {
const response = await agent.run(input);
console.log(`\n🤖 ${response}\n`);
} catch (error) {
console.log(`❌ Error: ${error.message}\n`);
}

askQuestion();
});
}

askQuestion();

What you're learning: Adding interaction is just a few lines of code. The agent handles the complexity.

Specialized Code Helper Configuration

Create a specialized configuration for code assistance:

# agents/code-helper.yml
mcpServers:
filesystem:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]

llm:
provider: anthropic
model: claude-4-sonnet-20250514
apiKey: $ANTHROPIC_API_KEY
systemPrompt: |
You are a senior software engineer and code reviewer.

Your expertise includes:
- Code review and best practices
- Debugging and troubleshooting
- Architecture and design patterns
- Security considerations
- Performance optimization

When helping with code:
1. Read and understand the codebase structure first
2. Provide specific, actionable feedback
3. Explain your reasoning
4. Suggest improvements with examples
5. Consider security and performance implications

Use the filesystem tools to examine code files when needed.

Application 3: Web API Service

Ready for something more advanced? Let's create a web service:

// web-service.ts
import express from 'express';
import { loadConfigFile, createSaikiAgent } from '@truffle-ai/saiki';

const app = express();
app.use(express.json());

// Initialize our agent once
const agent = await createSaikiAgent(
await loadConfigFile('./agents/saiki.yml')
);

// Simple chat endpoint
app.post('/chat', async (req, res) => {
try {
const { message } = req.body;
const response = await agent.run(message);

res.json({
success: true,
response,
timestamp: new Date().toISOString()
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});

// Health check
app.get('/health', (req, res) => {
res.json({ status: 'healthy', agent: 'ready' });
});

// File analysis endpoint
app.post('/analyze', async (req, res) => {
try {
const { path = '.' } = req.body;
const response = await agent.run(`Analyze the files in ${path} and provide a summary.`);

res.json({
success: true,
analysis: response,
path,
timestamp: new Date().toISOString()
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});

app.listen(3000, () => {
console.log('🚀 Saiki web service running on http://localhost:3000');
console.log('Endpoints:');
console.log(' POST /chat - Chat with the agent');
console.log(' POST /analyze - Analyze files');
console.log(' GET /health - Health check');
});

What you're learning: The same agent works everywhere - CLI, web, mobile, anywhere Node.js runs.

Testing Your Web Service

Test it with curl:

# Health check
curl http://localhost:3000/health

# Chat with the agent
curl -X POST http://localhost:3000/chat \
-H "Content-Type: application/json" \
-d '{"message": "What files are in the current directory?"}'

# Analyze files
curl -X POST http://localhost:3000/analyze \
-H "Content-Type: application/json" \
-d '{"path": "."}'

Key Patterns You've Learned

1. Single Purpose Agents

Each application has a clear, focused purpose:

  • File Organizer: Manages file organization
  • Code Helper: Assists with development tasks
  • Web Service: Provides API access to agent capabilities

2. Configuration Over Code

Notice how we didn't write complex AI integration code. Instead:

  • Configure capabilities in YAML
  • Use simple API calls to interact
  • Let Saiki handle the complexity

3. Consistent API

The same agent.run() call works in:

  • Command line tools
  • Interactive applications
  • Web services
  • Any Node.js environment

4. Error Handling

Always wrap agent calls in try-catch blocks:

try {
const response = await agent.run(message);
// Handle success
} catch (error) {
// Handle errors gracefully
}

Customizing for Your Use Case

Environment-Specific Configurations

Development

llm:
provider: openai
model: gpt-4.1-mini # Faster, cheaper for dev
apiKey: $OPENAI_API_KEY

Production

llm:
provider: openai
model: gpt-4.1 # More capable for production
apiKey: $OPENAI_API_KEY
providerOptions:
temperature: 0.3 # More consistent responses

Adding More Capabilities

Add new tools by including more MCP servers:

mcpServers:
filesystem:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]

puppeteer:
type: stdio
command: npx
args: ["-y", "@truffle-ai/puppeteer-server"]

# Add more servers for additional capabilities

What You've Built

You now have three working applications that demonstrate:

  • File management with AI assistance
  • Interactive development tools
  • Web API integration
  • Error handling and user experience
  • Flexible configuration for different environments

Next Steps

Ready to take it to the next level?

  • Learn advanced patterns: Check out Advanced Patterns for production-ready techniques
  • Add more tools: Explore MCP servers for additional capabilities
  • Deploy your service: See the deployment guide for production hosting
  • Join the community: Share your creations in our Discord

You're well on your way to building amazing AI applications! 🎉