AI Integration
Add AI capabilities to your Appivo applications
AI Integration Example
Learn how to integrate AI agents into your Appivo applications for intelligent automation.
What You'll Build
AI-powered features including:
- Automated code generation
- Intelligent content processing
- Smart search with context-aware responses
- Document analysis and summarization
Prerequisites
- Completed the Rules and Actions example
- Understanding of action scripts and the context object
Understanding AI in Appivo
Appivo provides 23 pre-built AI agents accessible through the AIFunctions API:
| Agent Category | Examples |
|---|---|
| Code Assistance | generate-code, code analyzers |
| Data Processing | generate-data-model, generate-query |
| Content Processing | clean-html, extract-keywords, translate |
| Media Processing | transcribe-audio, transcribe-image |
Example 1: Code Generation
Generate action scripts automatically.
Create the Action
'use strict';
exports.execute = async function(context, params) {
const aiFunctions = context.getAIFunctions();
const result = await aiFunctions.invokeAgent('generate-code', {
arguments: {
instructions: params.instructions,
model: params.modelName,
context: {
operation: params.operation
}
}
});
if (result.success) {
return {
success: true,
code: result.result,
message: 'Code generated successfully'
};
}
return {
success: false,
error: result.error
};
};
Usage
// Call the action
const generated = await context.executeAction('GenerateCode', {
instructions: 'Create a function to validate email addresses',
modelName: 'User',
operation: 'validation'
});
if (generated.success) {
console.log('Generated code:', generated.code);
}
Example 2: Content Translation
Translate user content between languages.
Create the Translation Action
'use strict';
exports.execute = async function(context, params) {
const aiFunctions = context.getAIFunctions();
const result = await aiFunctions.invokeAgent('translate', {
arguments: {
text: params.text,
targetLanguage: params.targetLanguage
}
});
if (result.success) {
return {
success: true,
translated: result.result,
originalLanguage: result.detectedLanguage
};
}
return {
success: false,
error: result.error
};
};
Trigger on Data Save
Create a rule to auto-translate content:
Rule: Auto-Translate Content
Type: DATA
Model: Article
Event: CREATE
Action: SCRIPT
'use strict';
exports.execute = async function(context, params) {
const article = params.record;
const aiFunctions = context.getAIFunctions();
// Translate title to Swedish
const titleSv = await aiFunctions.invokeAgent('translate', {
arguments: {
text: article.title,
targetLanguage: 'sv'
}
});
// Translate content to Swedish
const contentSv = await aiFunctions.invokeAgent('translate', {
arguments: {
text: article.content,
targetLanguage: 'sv'
}
});
if (titleSv.success && contentSv.success) {
await context.updateRecord('Article', article.id, {
title_sv: titleSv.result,
content_sv: contentSv.result
});
}
return { success: true };
};
Example 3: Smart Document Processing
Extract information from uploaded documents.
Process Uploaded Files
'use strict';
exports.execute = async function(context, params) {
const document = params.record;
const aiFunctions = context.getAIFunctions();
// Extract text from image if applicable
if (document.file_type === 'image') {
const extracted = await aiFunctions.invokeAgent('transcribe-image', {
arguments: {
imageFile: document.file_checksum
}
});
if (extracted.success) {
await context.updateRecord('Document', document.id, {
extracted_text: extracted.result
});
}
}
// Extract keywords from content
const content = document.extracted_text || document.content;
if (content) {
const keywords = await aiFunctions.invokeAgent('extract-keywords', {
arguments: {
text: content
}
});
if (keywords.success) {
await context.updateRecord('Document', document.id, {
keywords: keywords.result
});
}
}
return { success: true };
};
Example 4: Audio Transcription
Convert audio messages to text.
'use strict';
exports.execute = async function(context, params) {
const message = params.record;
const aiFunctions = context.getAIFunctions();
// Transcribe audio file
const transcript = await aiFunctions.invokeAgent('transcribe-audio', {
arguments: {
audioFile: message.audio_checksum
}
});
if (transcript.success) {
await context.updateRecord('VoiceMessage', message.id, {
transcript: transcript.result,
transcribed_at: new Date()
});
// Detect language of transcription
const langInfo = aiFunctions.detectLanguage(transcript.result);
await context.updateRecord('VoiceMessage', message.id, {
detected_language: langInfo.language,
language_code: langInfo.code
});
return { success: true, transcript: transcript.result };
}
return { success: false, error: transcript.error };
};
Example 5: Knowledge Base Search
Build a smart Q&A system using SearchIndexes.
Step 1: Create the SearchIndex
- Go to Data → Search Indexes
- Create index "KnowledgeBase"
- Select the Article model
- Include: title, content, category
- Set search type: BOTH (hybrid)
Step 2: Create the Search Action
'use strict';
exports.execute = async function(context, params) {
const userQuestion = params.question;
// Search the knowledge base
const searchResults = await context.searchIndex('KnowledgeBase', {
query: userQuestion,
type: 'BOTH',
limit: 5
});
if (!searchResults.documents || searchResults.documents.length === 0) {
return {
success: true,
answer: 'I could not find relevant information for your question.',
sources: []
};
}
// Generate contextual response
const aiFunctions = context.getAIFunctions();
const response = await aiFunctions.invokeAgent('generate-response', {
arguments: {
question: userQuestion,
context: searchResults.documents.map(d => d.content).join('\n\n'),
instructions: 'Answer the question based only on the provided context. If the context does not contain enough information, say so.'
}
});
return {
success: true,
answer: response.result,
sources: searchResults.documents.map(d => ({
title: d.title,
score: d.score
}))
};
};
Step 3: Create the UI
Panel: Knowledge Assistant
├── TextField: Question
│ Placeholder: "Ask a question..."
│ onKeyPress (Enter): Call search action
│
├── Button: Ask
│ onClick: Call search action, show loading
│
├── Panel: Answer (visible when answer exists)
│ ├── Label: Answer text
│ └── Panel: Sources
│ └── List: Source articles with scores
│
└── Panel: Loading (visible during search)
└── Spinner
Example 6: HTML Content Cleaning
Sanitize user-submitted HTML content.
'use strict';
exports.execute = async function(context, params) {
const submission = params.record;
const aiFunctions = context.getAIFunctions();
// Clean HTML content
const cleaned = await aiFunctions.invokeAgent('clean-html', {
arguments: {
content: submission.html_content
}
});
if (cleaned.success) {
await context.updateRecord('Submission', submission.id, {
cleaned_content: cleaned.result,
processing_status: 'cleaned'
});
return { success: true };
}
await context.updateRecord('Submission', submission.id, {
processing_status: 'error',
processing_error: cleaned.error
});
return { success: false, error: cleaned.error };
};
Example 7: Data Model Generation
Generate models from descriptions.
'use strict';
exports.execute = async function(context, params) {
const aiFunctions = context.getAIFunctions();
const modelDef = await aiFunctions.invokeAgent('generate-data-model', {
arguments: {
instructions: params.description
}
});
if (modelDef.success) {
// Log the generated model definition
await context.createRecord('GeneratedModel', {
description: params.description,
definition: JSON.stringify(modelDef.result),
created_at: new Date(),
status: 'pending_review'
});
return {
success: true,
model: modelDef.result
};
}
return { success: false, error: modelDef.error };
};
Example 8: Document Summarization
Summarize long documents automatically.
'use strict';
exports.execute = async function(context, params) {
const document = params.record;
const aiFunctions = context.getAIFunctions();
// Use the built-in summarization function
const summary = await aiFunctions.summarizeDocument(document.content, {
chunkSize: 4000,
maxOutputTokens: 500,
temperature: 0.2,
model: 'gemini-2.5-flash'
});
await context.updateRecord('Document', document.id, {
summary: summary,
summarized_at: new Date()
});
return { success: true, summary: summary };
};
Using the AiButton Widget
For client-side AI interactions, use the AiButton widget in your views:
<aibutton
:agent="'generate-data-model'"
:onresult="handleModelGenerated"
:onask="showLoading">
</aibutton>
methods: {
handleModelGenerated: function(data) {
this.generatedModel = data;
this.isLoading = false;
this.showPreview = true;
},
showLoading: function() {
this.isLoading = true;
}
}
Error Handling Pattern
Always handle AI responses properly:
'use strict';
exports.execute = async function(context, params) {
const aiFunctions = context.getAIFunctions();
try {
const result = await aiFunctions.invokeAgent('agent-name', {
arguments: params.data
});
if (result.success) {
// Validate the result
if (result.result && typeof result.result === 'object') {
return {
success: true,
data: result.result
};
} else {
return {
success: false,
error: 'Unexpected response format'
};
}
} else {
// Log the error for debugging
context.log.error('AI agent failed', {
agent: 'agent-name',
error: result.error,
params: params.data
});
return {
success: false,
error: result.error
};
}
} catch (error) {
context.log.error('System error calling AI', {
error: error.message
});
return {
success: false,
error: 'System error: ' + error.message
};
}
};
Caching AI Results
For frequently requested operations, implement caching:
'use strict';
exports.execute = async function(context, params) {
const cacheKey = `ai_translate_${params.text}_${params.targetLanguage}`;
// Check cache first
let cached = await context.getCache(cacheKey);
if (cached) {
return {
success: true,
result: cached,
fromCache: true
};
}
// Call AI agent
const aiFunctions = context.getAIFunctions();
const result = await aiFunctions.invokeAgent('translate', {
arguments: {
text: params.text,
targetLanguage: params.targetLanguage
}
});
if (result.success) {
// Cache for 24 hours
await context.setCache(cacheKey, result.result, 86400);
return {
success: true,
result: result.result,
fromCache: false
};
}
return { success: false, error: result.error };
};
Best Practices
Provide Specific Context
// Good: Detailed context
const code = await aiFunctions.invokeAgent('generate-code', {
arguments: {
instructions: 'Create validation for order total',
model: 'Order',
requirements: 'Total must be positive and not exceed $10,000',
relatedFields: ['quantity', 'unit_price', 'discount']
}
});
// Less effective: Vague request
const code = await aiFunctions.invokeAgent('generate-code', {
arguments: {
instructions: 'validate order'
}
});
Choose the Right Model
| Task Complexity | Recommended Model |
|---|---|
| Simple tasks | gemini-2.5-flash |
| Complex analysis | gemini-2.5-pro |
| Code generation | gemini-2.5-pro or gpt-4o |
Monitor Token Usage
const response = await aiFunctions.invokeAgent('agent-name', params);
if (response.tokenUsage) {
console.log('Tokens used:', response.tokenUsage.total);
if (response.tokenUsage.total > 3500) {
console.warn('High token usage - consider optimizing');
}
}
Complete Application: AI-Powered Help Desk
Models
Model: Ticket
- subject (Text)
- description (Long Text)
- category (Text) - auto-classified
- priority (Text) - auto-assigned
- suggested_response (Long Text)
- status (Selection)
Model: KnowledgeArticle
- title (Text)
- content (Long Text)
- category (Text)
- keywords (Text) - auto-extracted
Rule: Process New Ticket
Rule: AI Process Ticket
Type: DATA
Model: Ticket
Event: CREATE
'use strict';
exports.execute = async function(context, params) {
const ticket = params.record;
const aiFunctions = context.getAIFunctions();
// Extract keywords from description
const keywords = await aiFunctions.invokeAgent('extract-keywords', {
arguments: { text: ticket.description }
});
// Search knowledge base
const docs = await context.searchIndex('KnowledgeArticles', {
query: ticket.subject + ' ' + ticket.description,
type: 'BOTH',
limit: 3
});
// Generate suggested response
const suggestion = await aiFunctions.invokeAgent('generate-response', {
arguments: {
question: ticket.description,
context: docs.documents.map(d => d.content).join('\n'),
instructions: 'Generate a helpful response to this support ticket'
}
});
// Update ticket with AI insights
await context.updateRecord('Ticket', ticket.id, {
keywords: keywords.success ? keywords.result : null,
suggested_response: suggestion.success ? suggestion.result : null,
ai_processed: true
});
return { success: true };
};
Next Steps
- AI Agents Guide - Complete AI reference
- Rules and Actions - Automation patterns
- Integrations - External service connections