Tutorial 4: Configuration Deep Dive
⏱️ Time: 30 minutes | 🎯 Goal: Master Space and Agent configuration
In this tutorial, you’ll learn how to configure every aspect of your Viber workspace for production use.
What You’ll Learn
Section titled “What You’ll Learn”- LLM provider configuration
- Storage adapter options
- Environment variable management
- Production deployment patterns
Prerequisites
Section titled “Prerequisites”- Completed previous tutorials
- Understanding of Viber concepts
- An LLM API key
Understanding Configuration
Section titled “Understanding Configuration”Viber is designed to be flexible. Key configuration areas:
- LLM Providers — Which AI model to use
- Storage Adapters — Where to persist data
- Agent Settings — How agents behave
- Environment — Managing secrets and settings
Step 1: LLM Provider Configuration
Section titled “Step 1: LLM Provider Configuration”Viber supports multiple LLM providers through the Vercel AI SDK:
OPENAI_API_KEY=sk-your-keyAnthropic
Section titled “Anthropic”ANTHROPIC_API_KEY=your-keyDeepSeek
Section titled “DeepSeek”DEEPSEEK_API_KEY=your-keyGoogle (Gemini)
Section titled “Google (Gemini)”GOOGLE_GENERATIVE_AI_API_KEY=your-keyThe provider is automatically detected based on which environment variable is set.
Step 2: Storage Configuration
Section titled “Step 2: Storage Configuration”Viber supports two storage backends:
Local Storage (Default)
Section titled “Local Storage (Default)”Uses SQLite for structured data and the filesystem for files. Perfect for:
- Local development
- Desktop applications
- Offline-first apps
import { XAgent } from "viber";import { createLocalAdapter } from "@viber/local";
// Create a local adapter (optional - this is the default)const adapter = createLocalAdapter({ path: "./data", // Where to store data});
const xAgent = await XAgent.start("My project", { adapter,});Supabase (Cloud)
Section titled “Supabase (Cloud)”Uses PostgreSQL for structured data and Supabase Storage for files. Ideal for:
- Cloud-hosted applications
- Multi-user collaboration
- Apps requiring authentication
SUPABASE_URL=https://your-project.supabase.coSUPABASE_SERVICE_KEY=your-service-keyimport { XAgent } from "viber";import { createSupabaseAdapter } from "@viber/supabase";
const adapter = createSupabaseAdapter({ supabaseUrl: process.env.SUPABASE_URL!, supabaseKey: process.env.SUPABASE_SERVICE_KEY!,});
const xAgent = await XAgent.start("My project", { adapter,});Step 3: Environment Management
Section titled “Step 3: Environment Management”Development Setup
Section titled “Development Setup”Create a .env file:
# LLM ProviderOPENAI_API_KEY=sk-your-key
# Optional: Supabase for cloud storageSUPABASE_URL=https://your-project.supabase.coSUPABASE_SERVICE_KEY=your-service-key
# Development settingsNODE_ENV=developmentLOG_LEVEL=debugProduction Setup
Section titled “Production Setup”For production, use secure environment management:
# Production .env (or use your platform's secrets management)OPENAI_API_KEY=sk-production-keySUPABASE_URL=https://your-project.supabase.coSUPABASE_SERVICE_KEY=your-service-keyNODE_ENV=productionLOG_LEVEL=infoLoading Environment Variables
Section titled “Loading Environment Variables”Always load environment variables at the start of your application:
import "dotenv/config";// orimport { config } from "dotenv";config();Step 4: Agent Configuration
Section titled “Step 4: Agent Configuration”Default Agent Configuration
Section titled “Default Agent Configuration”Viber uses sensible defaults from @viber/defaults:
import { XAgent } from "viber";
// Uses default configurationconst xAgent = await XAgent.start("My project");Custom Agent Configuration
Section titled “Custom Agent Configuration”You can customize agent behavior through YAML files in @viber/defaults:
Default agents include:
- X — The orchestrating agent (project manager)
- Researcher — Gathers information
- Writer — Creates content
- Developer — Writes code
- Reviewer — Quality assurance
- Web Designer — HTML/CSS creation
Prompt Templates
Section titled “Prompt Templates”Agent prompts are stored in @viber/defaults/prompts/. You can override them:
import { XAgent } from "viber";
const xAgent = await XAgent.start("My project", { // Custom system prompt for XAgent systemPrompt: `You are a specialized assistant for...`,});Step 5: Production Configuration Example
Section titled “Step 5: Production Configuration Example”Here’s a complete production setup:
import "dotenv/config";import { createSupabaseAdapter } from "@viber/supabase";
// Validate required environment variablesconst requiredEnvVars = [ "OPENAI_API_KEY", "SUPABASE_URL", "SUPABASE_SERVICE_KEY",];
for (const envVar of requiredEnvVars) { if (!process.env[envVar]) { throw new Error(`Missing required environment variable: ${envVar}`); }}
// Create production adapterexport const adapter = createSupabaseAdapter({ supabaseUrl: process.env.SUPABASE_URL!, supabaseKey: process.env.SUPABASE_SERVICE_KEY!,});
// Export configurationexport const config = { isProduction: process.env.NODE_ENV === "production", logLevel: process.env.LOG_LEVEL || "info",};import { XAgent } from "viber";import { adapter, config } from "./config.js";
async function main() { console.log(`Starting in ${config.isProduction ? "production" : "development"} mode`);
const xAgent = await XAgent.start("Production workspace", { adapter, });
// Your application logic...}
main().catch(console.error);Step 6: React Integration Configuration
Section titled “Step 6: React Integration Configuration”For React applications, use @viber/react:
pnpm add @viber/react// app/actions.ts (Next.js Server Actions)"use server";
import { XAgent } from "viber";
export async function createSpace(goal: string) { const xAgent = await XAgent.start(goal); return xAgent.getSpace().spaceId;}
export async function sendMessage(spaceId: string, message: string) { const xAgent = await XAgent.resume(spaceId); const stream = await xAgent.streamText({ messages: [{ role: "user", content: message }], metadata: { mode: "agent", requestedAgent: "X" }, }); return stream;}"use client";
import { useSpace, useChat } from "@viber/react";
export function Chat({ spaceId }: { spaceId: string }) { const { space } = useSpace(spaceId); const { messages, sendMessage, isLoading } = useChat(spaceId);
return ( <div> <h2>{space?.name}</h2> {messages.map((msg, i) => ( <div key={i}>{msg.content}</div> ))} <button onClick={() => sendMessage("Hello!")}>Send</button> </div> );}Best Practices
Section titled “Best Practices”1. Environment Variables
Section titled “1. Environment Variables”# Never commit secretsecho ".env" >> .gitignore
# Use .env.example for documentationcp .env .env.example# Remove actual secrets from .env.example2. Error Handling
Section titled “2. Error Handling”try { const xAgent = await XAgent.start("My project");} catch (error) { if (error.message.includes("API key")) { console.error("Missing or invalid API key"); } else if (error.message.includes("network")) { console.error("Network error - check your connection"); } else { throw error; }}3. Logging
Section titled “3. Logging”// Configure logging levelprocess.env.LOG_LEVEL = "debug"; // debug, info, warn, error
// In productionprocess.env.LOG_LEVEL = "info";4. Resource Management
Section titled “4. Resource Management”// Always save state before exitprocess.on("SIGINT", async () => { console.log("\nSaving workspace..."); await space.persistState(); process.exit(0);});Configuration Reference
Section titled “Configuration Reference”XAgent.start() Options
Section titled “XAgent.start() Options”| Option | Type | Description |
|---|---|---|
adapter | DataAdapter | Storage adapter (local or Supabase) |
systemPrompt | string | Override the default system prompt |
XAgent.resume() Options
Section titled “XAgent.resume() Options”| Option | Type | Description |
|---|---|---|
adapter | DataAdapter | Storage adapter (must match original) |
Environment Variables
Section titled “Environment Variables”| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY | One LLM key required | OpenAI API key |
ANTHROPIC_API_KEY | One LLM key required | Anthropic API key |
DEEPSEEK_API_KEY | One LLM key required | DeepSeek API key |
SUPABASE_URL | For cloud storage | Supabase project URL |
SUPABASE_SERVICE_KEY | For cloud storage | Supabase service key |
NODE_ENV | No | development or production |
LOG_LEVEL | No | debug, info, warn, error |
🎉 Congratulations!
Section titled “🎉 Congratulations!”You now understand how to configure Viber for any environment:
âś… LLM Provider Configuration
âś… Storage Adapter Options
âś… Environment Variable Management
âś… Production Deployment Patterns
âś… React Integration
🚀 What’s Next?
Section titled “🚀 What’s Next?”You’ve completed the core Viber tutorials! Here are some next steps:
- Advanced: Comprehensive Systems — Build a complete production system
- SDK Reference — Explore the complete API
- Examples — See real-world implementations
đź”§ Troubleshooting
Section titled “🔧 Troubleshooting”Configuration not taking effect?
- Ensure environment variables are loaded before using them
- Check for typos in variable names
- Verify the
.envfile is in the correct directory
Storage errors?
- For Supabase, verify your URL and key are correct
- For local storage, ensure the directory is writable
- Check file permissions
Ready for advanced topics? Continue to Comprehensive Systems! đźŹ