AI Chat App Tutorial
Build a complete, AI-powered chat assistant on the Fiberwise platform. Go from zero to a deployed app in under 15 minutes.
๐ค What You'll Build
A production-ready, intelligent chat application that uses Fiberwise agent activations for storing conversations. Think of it as your own personal ChatGPT, powered by the Fiberwise platform.
- Interactive Chat UI: A clean, modern interface for real-time conversations.
- Intelligent AI Agent: Powered by a flexible assistant agent you can customize.
- Conversation History: Automatically saves and retrieves chat sessions.
- One-Click Deploy: Ready to be deployed live on the Fiberwise platform.
๐ Prerequisites: Your Setup Checklist
Before you begin, you need a fully configured Fiberwise environment. This is the foundation for building any app on the platform.
๐ง Required Setup
โ All Set?
Once all boxes are checked, you are ready to start building the chat app. If not, please complete the linked guides first.
Step 1: Get the Code
The Fiberwise platform includes example apps in the local fiber-apps/
directory. Navigate to the activation chat example project to explore its structure.
Navigate to Example Apps
# Navigate to the fiber-apps directory (included with Fiberwise)
cd fiber-apps/activation-chat
Explore the Project Structure
# List the files to see the app structure
ls -la
Open in Your Code Editor
Open the current directory (`activation-chat`) in an editor like VS Code to explore the files.
code .
Step 2: Understanding the App's Blueprint
Before installing, let's look at the key concepts that define the application. This will help you understand what happens in the next step.
The Manifest: `app_manifest.yaml`
This is the most important file. It's the blueprint that tells Fiberwise what resources your app needs. It defines the app itself, the data models it uses, and the AI agent that powers the chat.
๐ก Key Concept: The Manifest
The manifest is a declarative file that defines all the backend resources for your app. When you run `fiber app install`, the CLI reads this file and automatically provisions everything your app needs on the platform.
Project Structure
The app is built from several modern web components that handle different parts of the UI. This separation makes the code clean and easy to maintain.
activation-chat/
โโโ ๐ app_manifest.yaml # โ The app's blueprint
โโโ ๐ฏ index.js # Main entry point, initializes the app
โโโ ๐ฌ chat-app.js # The main component that orchestrates everything
โโโ ๐ญ chat-messages.js # Displays the list of messages for a session
โโโ ... (other UI components & styles)
๐๏ธ App Architecture Flow
Here's the high-level architecture of how Fiberwise applications initialize and prepare for user interaction:
Step 3: Install and Run the App
Now it's time to bring the application to life. This two-step process installs the frontend dependencies and then installs the app onto the Fiberwise platform.
Install Frontend Dependencies
This command reads `package.json` and installs the necessary Node.js packages for the frontend UI.
npm install
Install the App to Fiberwise
This command uses the Fiberwise CLI to read your `app_manifest.yaml` and create all the necessary resources (the app, the agent, the data model) on your instance.
fiber app install ./
โ Expected Output
Installing app: Activation Chat
App installed successfully!
App ID: activation-chat
Status: Active โ
๏ฟฝ Technical App Loading Flow
Now let's see the detailed technical flow when you open your app in the browser:
๐ Key Files in Action
- index.js - Entry point that initializes FIBER SDK and renders the main component
- chat-app.js - Main component that calls
FIBER.listAgents()
and sets up UI state - app_manifest.yaml - Defines the "chatAgent" that gets loaded from the API
๏ฟฝ๐ Provider Selection Flow
Before sending messages, users select their LLM provider. Here's how provider metadata works:
Step 4: Send Your First Message
Your chat app is now live on your Fiberwise instance. Let's send a message to see it in action and understand exactly what happens behind the scenes.
1. Open Your App
Navigate to your app in a browser. By default, the URL will be:
http://localhost:8000/activation-chat
You'll see the clean chat interface with an empty message area and an input box at the bottom.
2. Start a Conversation
Type a message like "Hello, who are you?" into the input box and press Enter.
๏ฟฝ Message Sending Flow
When you type and send a message, here's the complete flow with provider metadata:
Code Reference - chat-input.js:
// When user presses Enter or clicks send
handleSubmit() {
const message = this.input.value.trim();
if (message) {
// Fire custom event that chat-app.js listens for
this.dispatchEvent(new CustomEvent('message-sent', {
detail: { content: message }
}));
this.input.value = ''; // Clear input
}
}
3. See the Magic!
You will see your message appear instantly, followed shortly by a response from the AI. You've just completed a full loop: from UI to AI and back!
๐ค Complete Message Processing Flow
Here's the complete journey of your message through the Fiberwise platform:
Code Reference - chat-app.js sendMessage():
async sendMessage(content) {
// Create the activation with your message
const activation = await FIBER.agents.activate(
this.selectedAgentId, // 'chatAgent' from manifest
{ prompt: content }, // Your message: "Hello, who are you?"
{
chat_id: this.currentChatId, // Links messages to this conversation
system_prompt: this.modelSettings.systemPrompt,
role: 'user'
},
{
provider_id: this.selectedProviderId, // Which LLM to use
temperature: this.modelSettings.temperature
}
);
// Add pending message to UI immediately
this.addMessageToUI({
content: content,
role: 'user',
activationId: activation.id,
status: 'completed'
});
// Add pending AI response placeholder
this.addMessageToUI({
content: '',
role: 'assistant',
activationId: activation.id,
status: 'pending'
});
}
Manifest Reference - app_manifest.yaml:
# The agent that processes your messages
agents:
- name: chatAgent
agent_slug: chat-agent
description: AI chat assistant agent
system_prompt: |
You are a helpful AI assistant. Be friendly and provide
clear, concise responses to user questions.
# This agent will automatically use the connected LLM provider
# with the context and metadata you send via FIBER.agents.activate()
๐ซ What You Just Witnessed
๐ Real-time Updates Explained
One of the most impressive parts is how the UI updates automatically when the AI responds:
Code Reference - Real-time listener in chat-app.js:
// Set up real-time listener for activation updates
connectedCallback() {
// ... other initialization ...
// Listen for activation completion events
FIBER.realtime.on('message', (message) => {
if (message.type === 'activation_completed') {
this.handleActivationCompleted(message);
}
});
}
handleActivationCompleted(message) {
// Find the pending message in the UI
const pendingMessage = this.messages.find(m =>
m.activationId === message.activation_id && m.status === 'pending'
);
if (pendingMessage) {
// Update with the AI's response
pendingMessage.content = message.output;
pendingMessage.status = 'completed';
this.updateMessagesDisplay();
}
}
Step 5: Deep Dive - How Did That Work?
What just happened when you sent that message? Let's trace the data flow from your browser to the Fiberwise platform and back.
1. The UI Captures Your Input (`chat-input.js`)
The `
๐ ๏ธ Router System & App Launch Flow
Behind the scenes, here's how the Fiberwise router system manages app loading and navigation:
Key Router Components:
Router.getInstance()
- Singleton pattern for single router across app_matchRoute()
- Advanced pattern matching with parameters and prioritieslaunchApp()
- Dynamic app loading and manifest processingregisterAppRoutes()
- Add app routes to router registry
2. The App Component Makes the SDK Call (`chat-app.js`)
The main `
๐ก Key Concept: Agent Activation
An **activation** is a record of a single run of an agent. It stores the agent's inputs, outputs, status (e.g., pending, completed), and context. This app uses activations as its message store.
// In chat-app.js -> sendMessage()
const activation = await FIBER.agents.activate(
this.selectedAgentId, // The ID of our chat agent
{ prompt: content }, // The user's message as input
{
chat_id: this.currentChatId, // Context to group messages
system_prompt: this.modelSettings.systemPrompt
},
metadata // Additional settings like temperature
);
3. The Fiberwise Platform Takes Over
When the platform receives the `activate` call:
- It immediately creates a new **activation** with a `pending` status.
- It triggers the "Chat Agent" (defined in your manifest) and passes it the `prompt`.
- The agent calls the connected LLM Provider (e.g., OpenAI).
- When the LLM responds, the agent saves the text as the activation's `output`.
- Finally, the activation's status is updated to `completed`.
4. Real-time Update to the UI
How does the UI know when the response is ready? The app listens for real-time events from the platform using a WebSocket connection.
โก WebSocket Real-time Flow
WebSocket Event Types:
activation_completed
- Agent finished processingactivation_failed
- Agent encountered an erroractivation_progress
- Real-time progress updates
// In chat-app.js -> init()
FIBER.realtime.on('message', (message) => {
// We listen for the specific event that tells us an activation is done
if (message.type === 'activation_completed') {
// We find the 'pending' message in the UI and update it
// with the final output from the activation.
this.handleActivationCompleted(message);
}
});
5. Chat Session & History Management
When you select an existing chat or start a new conversation, here's how message history loads:
๐ Load Message History Flow
Code Reference - How chat history works:
// Loading previous messages for a chat session
async loadChatHistory(chatId) {
const activations = await FIBER.agents.listActivations({
context: { chat_id: chatId }, // Filter by chat session
sort: 'created_at', // Order by time
limit: 50 // Recent messages
});
// Convert activations to chat messages
const messages = activations.map(activation => ({
content: activation.output,
role: activation.context.role || 'assistant',
timestamp: activation.created_at
}));
this.renderMessages(messages);
}
6. Component Lifecycle & State Management
Understanding how web components initialize and manage state in Fiberwise applications:
๐๏ธ Component Lifecycle Flow
Key Lifecycle Methods:
connectedCallback()
- Component mounted to DOMdisconnectedCallback()
- Component removed from DOMattributeChangedCallback()
- Attributes changedrender()
- Custom method to update UI
7. Complete Data Flow Diagram
Here's the complete data flow diagram that shows how all components interact from user input to AI response:
Complete Data Flow
Step 6: Understanding the Technical Implementation
Now that you've built and tested your chat app, let's dive into the technical details of how it works. This section explains the key implementation patterns you can use in your own apps.
๐ Application Manifest Structure
The app_manifest.yaml
file defines your complete application. Here's the activation-chat manifest structure:
app:
name: Activation Chat
app_slug: activation-chat
version: 0.0.21
description: A chat application that uses agent activations and dynamic data as the message store
entryPoint: index.js
icon: fas fa-comments
category: simple
# Minimal model for session tracking only
models:
- name: Chat
model_slug: chats
description: Simple chat session container
fields:
- name: Chat ID
field_column: chat_id
type: uuid
required: true
is_primary_key: true
description: Primary key used as chat_id in agent activation context
- name: Title
field_column: title
type: string
required: true
default: New Chat
routes:
- path: /
component: chat-app
title: Chat
icon: fas fa-comments
agents:
- name: chatAgent
agent_type_id: llm
version: 0.0.2
๐๏ธ App Entry Point Implementation
Every Fiberwise app follows a standard pattern for platform integration. Here's the complete index.js
structure:
// index.js - Standard platform integration pattern
import fiber from 'fiberwise';
// Create FIBER SDK instance using modern constructor pattern
export const FIBER = new FiberWise();
/**
* Standard initialize function for app platform integration
* @param {Object} appBridge - AppBridge instance from platform
* @param {Object} manifest - The application manifest
* @returns {Promise<boolean>} Success status
*/
export async function initialize(appBridge, manifest) {
console.log('[ActivationChat] Initializing app...');
FIBER.initialize(appBridge, manifest);
return true;
}
/**
* Standard render function for app platform integration
* @param {HTMLElement} mountPoint - Where to mount the app
*/
export function render(mountPoint) {
console.log('[ActivationChat] Rendering app...');
const el = document.createElement('chat-app');
mountPoint.appendChild(el);
}
// Register the main Web Component
import './chat-app.js';
๐พ Activation Context Structure
The chat app stores messages as agent activations with special context metadata. Here's how the data structure works:
// User message activation
{
"agent_id": "chatAgent",
"input_data": {
"message": "Hello, how are you?"
},
"context": {
"chat_id": "unique-session-identifier",
"session_title": "Morning Chat",
"role": "user",
"system_prompt": "You are a helpful assistant"
},
"status": "completed"
}
// Assistant response activation
{
"agent_id": "chatAgent",
"input_data": {
"message": "Hello, how are you?"
},
"output_data": {
"text": "Hello! I'm doing well, thank you for asking."
},
"context": {
"chat_id": "unique-session-identifier",
"session_title": "Morning Chat",
"role": "assistant",
"system_prompt": "You are a helpful assistant"
},
"status": "completed"
}
๐ก Data Flow Implementation
Here are the key methods that power the chat functionality:
Message Retrieval
// Query activations by context for chat history
async loadChatHistory(chatId) {
const activations = await FIBER.agents.getActivations(agentId, {
context: { chat_id: chatId },
sort: 'started_at'
});
return activations
.filter(a => a.context?.role)
.map(activation => ({
role: activation.context.role,
content: activation.context.role === 'user'
? activation.input_data?.message
: activation.output_data?.text,
timestamp: activation.started_at,
activationId: activation.activation_id
}));
}
Session Management
// Discover unique chat sessions from activations
async loadSessions() {
const activations = await FIBER.agents.getActivations(agentId);
const sessions = new Map();
activations.forEach(activation => {
if (activation.context?.chat_id && activation.context?.session_title) {
sessions.set(activation.context.chat_id, {
id: activation.context.chat_id,
title: activation.context.session_title,
lastActivity: activation.started_at
});
}
});
return Array.from(sessions.values())
.sort((a, b) => new Date(b.lastActivity) - new Date(a.lastActivity));
}
Message Sending Flow
// Complete message sending implementation
async sendMessage(message, chatId) {
// 1. Create user message activation
const userActivation = await FIBER.agents.activate(agentId, {
message: message
}, {
chat_id: chatId,
session_title: this.currentSession.title,
role: 'user'
});
// 2. Create assistant activation for AI response
const assistantActivation = await FIBER.agents.activate(agentId, {
message: message,
system_prompt: this.systemPrompt
}, {
chat_id: chatId,
session_title: this.currentSession.title,
role: 'assistant'
});
// 3. Refresh chat history to show both messages
await this.loadChatHistory(chatId);
}
๐ Conceptual Database Query
While you interact with activations through the SDK, here's the conceptual SQL that shows how message retrieval works:
-- Conceptual query for message retrieval
SELECT * FROM agent_activations
WHERE context->>'chat_id' = 'session-identifier'
ORDER BY started_at ASC;
๐ก Key Patterns for Your Apps
- Activation-Based Storage: Use activations instead of traditional database tables
- Context Metadata: Store application data in activation context
- Role-Based Organization: Use context.role to categorize data
- Virtual Entities: Derive app entities from activation context patterns
- Standard App Structure: Follow initialize/render pattern for platform integration
๐ Congratulations!
You've successfully installed, run, and understood a production-grade AI application on Fiberwise. You now know the core pattern for building apps on the platform.