Adding Lumnis AI to Lovable
Official guide for integrating Lumnis AI API to Lovable
Integrating Lumnis AI with Lovable
This guide provides step-by-step, copyable prompts to integrate Lumnis AI into your Lovable project. Each prompt is designed to be pasted directly into Lovable for quick implementation.
What You'll Build
By following this guide, you'll create a complete AI agent application with:
- 🔌 App Integrations: Connect to external tools like Google Docs, Google Sheets, Slack, and more
- ✨ Task Creation: A simple interface where users can describe tasks in natural language
- 📊 Task Management: View and track agent tasks with real-time progress updates
- 👤 User Management: Automatic user creation and authentication
- 🤖 Intelligent Agent: An AI agent that can research, create documents, analyze data, and more
The result is a flexible agent platform that users can interact with through natural language prompts, with the agent automatically using the right tools and integrations to complete tasks.
Prerequisites
Before starting, ensure you have:
- A Lovable account with a project created
- Your Lumnis AI API key
- Basic understanding of what you want your AI agent to do
Step 1: Enable Lovable Cloud, Install SDK, and Add API Key
We're building a complete AI agent application that allows users to:
- Connect to external tools (Google Docs, Sheets, Slack, etc.)
- Submit tasks using natural language prompts
- Track agent progress in real-time
- View past tasks and results
To start, enable Lovable Cloud for backend functionality. Install the lumnisai npm package for the project. Then add a secret called LUMNISAI_API_KEY with my API key.
When Lovable asks for the API key value, provide your actual Lumnis AI API key.
Step 2: Set Up Database Schema
Create the following database schema for Lumnis AI integration:
1. profiles table:
- id (UUID, primary key)
- user_id (UUID, unique)
- email (text)
- first_name (text)
- last_name (text)
- created_at, updated_at (timestamps)
2. agent_responses table:
- id (UUID, primary key)
- user_id (UUID)
- response_id (text, unique) - stores Lumnis AI response ID
- status (text) - queued/running/succeeded/failed/cancelled
- progress (JSONB) - array of progress entries
- output_text (text) - final agent output
- error (text)
- created_at, updated_at (timestamps)
Add RLS policies so users can only access their own data. Create update_updated_at_column function and triggers for automatic timestamp updates.
Step 3: Create Edge Functions for Lumnis AI
Create the following Supabase edge functions using this exact code structure:
1. CREATE ensure-user FUNCTION:
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
import { LumnisClient } from 'https://esm.sh/lumnisai@latest';
import { z } from "https://esm.sh/zod@3.22.4";
const userInputSchema = z.object({
email: z.string().email().max(255),
firstName: z.string().max(100).optional(),
lastName: z.string().max(100).optional(),
});
const LUMNISAI_API_KEY = Deno.env.get('LUMNISAI_API_KEY');
const SUPABASE_URL = Deno.env.get('SUPABASE_URL')!;
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const authHeader = req.headers.get('Authorization');
if (!authHeader) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
const token = authHeader.replace('Bearer ', '');
const { data: { user }, error: authError } = await supabase.auth.getUser(token);
if (authError || !user) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
const body = await req.json();
const validation = userInputSchema.safeParse(body);
if (!validation.success) {
return new Response(JSON.stringify({ error: 'Invalid input data' }), {
status: 400,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
const { email, firstName, lastName } = validation.data;
// Ensure user can only manage their own profile
if (user.email !== email) {
return new Response(JSON.stringify({ error: 'Forbidden' }), {
status: 403,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
if (!LUMNISAI_API_KEY) {
throw new Error('LUMNISAI_API_KEY not configured');
}
const client = new LumnisClient({ apiKey: LUMNISAI_API_KEY });
try {
const existing = await client.getUser(email);
console.log('User exists:', email);
return new Response(JSON.stringify(existing), {
status: 200,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
} catch (error: any) {
if (error.message?.includes('not found') || error.response?.status === 404) {
const created = await client.createUser({
email,
firstName: firstName ?? email.split('@')[0],
lastName: lastName ?? 'User',
});
console.log('User created:', email);
return new Response(JSON.stringify(created), {
status: 201,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
throw error;
}
} catch (error) {
console.error('Error in ensure-user:', error);
const message = error instanceof Error ? error.message : 'Unknown error';
return new Response(JSON.stringify({ error: message }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
});
2. CREATE initiate-connection FUNCTION:
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { LumnisClient } from 'https://esm.sh/lumnisai@latest';
const LUMNISAI_API_KEY = Deno.env.get('LUMNISAI_API_KEY');
const SUPABASE_URL = Deno.env.get('SUPABASE_URL')!;
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const authHeader = req.headers.get('Authorization');
if (!authHeader) {
throw new Error('No authorization header');
}
if (!LUMNISAI_API_KEY) {
throw new Error('LUMNISAI_API_KEY not configured');
}
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
const token = authHeader.replace('Bearer ', '');
const { data: { user }, error: authError } = await supabase.auth.getUser(token);
if (authError || !user?.email) {
throw new Error('Unauthorized');
}
const { appName } = await req.json(); // e.g., 'googledocs', 'googlesheets', 'slack', etc.
console.log(`Initiating ${appName} connection for ${user.email}`);
const client = new LumnisClient({ apiKey: LUMNISAI_API_KEY });
// Enable app at tenant level if not enabled
const appEnabled = await client.isAppEnabled(appName);
if (!appEnabled.enabled) {
console.log(`Enabling ${appName} at tenant level...`);
await client.setAppEnabled(appName, true);
}
// Initiate connection
const connection = await client.initiateConnection({
userId: user.email,
appName: appName,
});
console.log(`${appName} connection initiated for ${user.email}:`, connection);
return new Response(JSON.stringify({
redirectUrl: connection.redirectUrl,
status: 'pending'
}), {
status: 200,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
} catch (error) {
console.error('Error connecting:', error);
const message = error instanceof Error ? error.message : 'Unknown error';
return new Response(JSON.stringify({ error: message }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
});
3. CREATE check-connection FUNCTION:
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { LumnisClient } from 'https://esm.sh/lumnisai@latest';
const LUMNISAI_API_KEY = Deno.env.get('LUMNISAI_API_KEY');
const SUPABASE_URL = Deno.env.get('SUPABASE_URL')!;
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const authHeader = req.headers.get('Authorization');
if (!authHeader) {
throw new Error('No authorization header');
}
if (!LUMNISAI_API_KEY) {
throw new Error('LUMNISAI_API_KEY not configured');
}
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
const token = authHeader.replace('Bearer ', '');
const { data: { user }, error: authError } = await supabase.auth.getUser(token);
if (authError || !user?.email) {
throw new Error('Unauthorized');
}
const { appName } = await req.json(); // e.g., 'googledocs', 'googlesheets', 'slack', etc.
console.log(`Checking ${appName} connection status for ${user.email}`);
const client = new LumnisClient({ apiKey: LUMNISAI_API_KEY });
const status = await client.getConnectionStatus(user.email, appName);
console.log(`${appName} status for ${user.email}:`, status);
return new Response(JSON.stringify(status), {
status: 200,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
} catch (error) {
console.error('Error checking status:', error);
const message = error instanceof Error ? error.message : 'Unknown error';
return new Response(JSON.stringify({ error: message }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
});
4. CREATE create-response FUNCTION:
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
import { LumnisClient } from "https://esm.sh/lumnisai@latest";
// Define your agent system prompt
const AGENT_PROMPT = `You are an expert AI agent with access to various tools and integrations. Your role is to help users accomplish their tasks efficiently and accurately.
Key capabilities:
- Research and gather information from the web
- Create and edit documents in Google Docs
- Manage data in Google Sheets
- Integrate with various productivity tools
- Provide comprehensive, well-structured outputs
Guidelines:
- Break down complex tasks into manageable steps
- Use appropriate tools for each subtask
- Verify information when possible
- Provide clear explanations of your actions
- Ask for clarification if the task is ambiguous`;
const LUMNISAI_API_KEY = Deno.env.get("LUMNISAI_API_KEY");
const SUPABASE_URL = Deno.env.get("SUPABASE_URL")!;
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};
serve(async (req) => {
if (req.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders });
}
try {
const authHeader = req.headers.get("Authorization");
if (!authHeader) {
throw new Error("No authorization header");
}
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
const token = authHeader.replace("Bearer ", "");
const { data: { user }, error: authError } = await supabase.auth.getUser(token);
if (authError || !user) {
throw new Error("Unauthorized");
}
const body = await req.json();
const { taskPrompt } = body;
if (!LUMNISAI_API_KEY) {
throw new Error("LUMNISAI_API_KEY not configured");
}
const client = new LumnisClient({ apiKey: LUMNISAI_API_KEY });
// Build the full task message
const taskMessage = `${AGENT_PROMPT}\n\nUSER TASK:\n${taskPrompt}`;
// Create LumnisAI response
const responseData = await client.responses.create({
messages: [{ role: "user", content: taskMessage }],
userId: user.email,
agentConfig: {
coordinatorModelName: "openai:gpt-4.1",
plannerModelName: "openai:gpt-4.1",
orchestratorModelName: "openai:gpt-4.1",
useCognitiveTools: true,
enableTaskValidation: true,
generateComprehensiveOutput: false,
},
});
const responseId = responseData.responseId;
// Store in database
const { error: dbError } = await supabase.from("agent_responses").insert({
user_id: user.id,
response_id: responseId,
status: "queued",
});
if (dbError) {
console.error("Failed to store response in DB:", dbError);
}
console.log("Response created:", responseId);
console.log("User:", user.email);
return new Response(JSON.stringify({ responseId }), {
status: 201,
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
} catch (error) {
console.error("Error in create-response:", error);
const message = error instanceof Error ? error.message : "Unknown error";
return new Response(JSON.stringify({ error: message }), {
status: 500,
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
}
});
5. CREATE poll-response FUNCTION:
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { LumnisClient } from 'https://esm.sh/lumnisai@latest';
const LUMNISAI_API_KEY = Deno.env.get('LUMNISAI_API_KEY');
const SUPABASE_URL = Deno.env.get('SUPABASE_URL')!;
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const { responseId } = await req.json();
if (!responseId) {
throw new Error('Missing responseId');
}
const authHeader = req.headers.get('Authorization');
if (!authHeader) {
throw new Error('No authorization header');
}
if (!LUMNISAI_API_KEY) {
throw new Error('LUMNISAI_API_KEY not configured');
}
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
const token = authHeader.replace('Bearer ', '');
const { data: { user }, error: authError } = await supabase.auth.getUser(token);
if (authError || !user) {
throw new Error('Unauthorized');
}
const client = new LumnisClient({ apiKey: LUMNISAI_API_KEY });
// Poll LumnisAI with 10s wait
const data = await client.responses.get(responseId, { wait: 10 });
// Update database
const { error: dbError } = await supabase
.from('agent_responses')
.update({
status: data.status,
progress: data.progress ?? [],
output_text: data.outputText ?? null,
error: data.error ?? null,
})
.eq('response_id', responseId);
if (dbError) {
console.error('Failed to update response in DB:', dbError);
}
return new Response(JSON.stringify(data), {
status: 200,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
} catch (error) {
console.error('Error in poll-response:', error);
const message = error instanceof Error ? error.message : 'Unknown error';
return new Response(JSON.stringify({ error: message }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
});
Step 4: Create User Authentication Flow
Create a user authentication flow:
1. Sign up/login page with Supabase Auth
2. After successful auth, ensure Lumnis AI user:
const ensureUser = async (email, firstName, lastName) => {
const response = await fetch('/functions/v1/ensure-user', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, firstName, lastName })
})
return response.json()
}
3. User creation logic (handled by edge function):
- Validates input with zod schema
- Ensures user.email matches authenticated user
- Tries getUser(email) first
- If 404 or "not found", creates with createUser()
- Returns status 200 for existing, 201 for new user
4. Redirect to dashboard after successful user creation/verification
Step 5: Build App Integration UI
Create app connection components for integrations:
1. Check connection status:
const checkConnectionStatus = async (appName) => {
const response = await fetch('/functions/v1/check-connection', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ appName }) // e.g., 'googledocs', 'googlesheets', 'slack', etc.
})
return response.json()
}
2. Initiate app connection:
const initiateConnection = async (appName) => {
const response = await fetch('/functions/v1/initiate-connection', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ appName })
})
const data = await response.json()
if (data.redirectUrl) {
window.open(data.redirectUrl, '_blank')
// Poll for status updates
const interval = setInterval(async () => {
const status = await checkConnectionStatus(appName)
if (status.status === 'active') {
clearInterval(interval)
setConnectionStatus(appName, 'active')
}
}, 5000)
}
}
3. Create UI components:
- Display each app integration as a card
- Show connection status for each app
- Display "Connected" (green checkmark) or "Connect" button (primary)
- Examples: Google Docs, Google Sheets, Slack, Gmail, etc.
- Use app icons for better visual recognition
4. Layout integrations in a responsive grid or card layout
Step 6: Create Task Submission Form
If it doesn't exist yet, then create a simple form for users to submit tasks to the AI agent:
1. Main form component:
- Large textarea for task/prompt input
- Character count (optional)
- Examples or placeholder text to guide users
- Submit button with loading state
Example placeholder:
"Describe what you'd like the AI agent to do. For example:
- Research the top 5 CRM tools and create a comparison doc
- Analyze sales data and create a summary report
- Draft a project proposal based on these requirements..."
2. Submission handler:
const handleSubmit = async () => {
// Validate task prompt
if (!taskPrompt.trim()) {
showError('Please enter a task description')
return
}
// Optional: Check if required integrations are connected
const checkConnection = async (appName) => {
const response = await fetch('/functions/v1/check-connection', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ appName })
})
return response.json()
}
// Example: Check if Google Docs is connected (if required for your use case)
const docsStatus = await checkConnection('googledocs')
if (docsStatus.status !== 'active') {
showWarning('Note: Some integrations are not connected. The agent will work with available tools.')
}
// Create agent response
const response = await fetch('/functions/v1/create-response', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
taskPrompt: taskPrompt.trim()
})
})
const { responseId } = await response.json()
// Navigate to progress page
navigate(`/agent/${responseId}`)
}
3. UI Elements:
- Clear, prominent textarea (min 3-4 rows)
- Submit button: "Start Agent" or "Run Task"
- Show loading spinner during submission
- Display connection status badges for integrations (optional)
- Include examples or suggestions to help users get started
Step 7: Build Agent Progress Viewer
Create a real-time progress viewer for agent runs:
1. Polling implementation:
const pollResponse = async (responseId) => {
let done = false
while (!done) {
const response = await fetch('/functions/v1/poll-response', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ responseId })
})
const data = await response.json()
// Update UI with new data
setStatus(data.status)
setProgress(data.progress || [])
setOutputText(data.outputText)
setError(data.error)
// Check if complete
done = ['succeeded', 'failed', 'cancelled'].includes(data.status)
if (!done) {
await new Promise(resolve => setTimeout(resolve, 2000))
}
}
}
2. Progress entry display:
data.progress?.forEach(entry => {
// Display each progress entry with:
// - Timestamp (entry.ts)
// - State (entry.state)
// - Message (entry.message)
// - Tool calls (entry.toolCalls) if present
// Format tool calls with arguments
if (entry.toolCalls) {
entry.toolCalls.forEach(tool => {
// Display tool name: tool.name
// Display tool arguments
if (tool.args) {
Object.entries(tool.args).forEach(([key, value]) => {
let displayValue = value
// Format arrays/lists properly
if (Array.isArray(value)) {
displayValue = `[${value.join(', ')}]`
}
// Format objects as JSON
if (typeof value === 'object' && !Array.isArray(value)) {
displayValue = JSON.stringify(value, null, 2)
}
// Truncate long values (>100 chars)
const stringValue = String(displayValue)
if (stringValue.length > 100) {
displayValue = stringValue.substring(0, 100) + '...'
}
// Display: key: displayValue
})
}
})
}
})
3. Status indicators:
- 'queued': Show "Waiting to start..."
- 'running': Show spinner/progress animation
- 'succeeded': Show success checkmark and render outputText as Markdown
- 'failed': Show error message
- 'cancelled': Show cancelled state
4. Final output handling:
- When status === 'succeeded', render data.outputText as Markdown
- Make all links clickable (Google Docs/Sheets links)
- Format tables and lists properly
- Allow collapsing/expanding progress entries
5. Error recovery:
- If failed, show error message from data.error
- Provide "Try Again" button to create new response
- Include "Back to Form" navigation
Step 8: Polish the User Experience
Improve the UX by:
1. Adding loading states for all async operations
2. Showing success toasts when operations complete
3. Adding proper error handling with user-friendly messages
4. Making the UI responsive and mobile-friendly
5. Adding animations for state transitions
6. Using a modern color scheme with good contrast
7. Remove placeholder or fake data.
8. Use thread title instead of task id in list of past tasks.
Important Notes
- All edge functions use POST method (even for checking status)
- Pass appName in request body for app connections (e.g., 'googledocs', 'googlesheets', 'slack', etc.)
- responseId goes in request body for polling, not query params
- Always include Authorization header with Bearer token
- Handle CORS preflight with OPTIONS check
- Use exact imports from the code examples above
Tips for Success
- Always provide your actual use case - Replace generic examples with your specific needs
- Test incrementally - Verify each step works before moving to the next
- Check logs - Use Lovable's logs to debug edge function issues
- Be specific about UI - Describe exactly how you want the interface to look
- Save response IDs - Always store them in the database for persistence
- Use proper TypeScript types - Import types like
AgentConfig,ApiProviderfrom lumnisai - Handle streaming - For real-time updates, use the streaming API with
displayProgress
Troubleshooting
If agent doesn't start:
Check that:
1. User exists in Lumnis AI (call /api/users/ensure first)
2. API key is correctly set in secrets
3. Task data is properly formatted as JSON
4. AgentConfig includes all required model names
If app connection/OAuth fails:
Ensure:
1. Apps are enabled at tenant level with setAppEnabled()
2. User email matches the authenticated user
3. OAuth redirect URL completes fully
4. Connection status transitions from 'pending' to 'active'
5. appName is correctly formatted (e.g., 'googledocs', 'slack', etc.)
If progress doesn't update:
Verify:
1. responseId is being passed correctly
2. Using { wait: 10 } for long-polling
3. Progress array is being properly parsed
4. Status checks include all terminal states: ['succeeded', 'failed', 'cancelled']
Common Edge Function Issues:
If DNS resolution fails:
- Ensure using 'https://esm.sh/lumnisai' for imports
- Check that process.env.LUMNISAI_API_KEY is available
- Add try-catch blocks with detailed error logging
If types are missing:
- Import types explicitly: import { type AgentConfig } from 'lumnisai'
- Use proper TypeScript configuration in edge functions
Summary
You now have a complete guide to integrate Lumnis AI with Lovable! This integration enables:
- AI Agent Capabilities: Research, document creation, data analysis, and more
- App Integrations: Connect to Google Workspace, Slack, and other productivity tools
- Real-time Progress Tracking: Live updates as the agent works
- User Management: Automatic user creation and profile management
- Flexible Configuration: Customizable models and agent settings
Remember to:
- Install the
lumnisainpm package - Set up your API key properly
- Test each component incrementally
- Use the example code as templates
- Check the logs if you encounter issues
Customizing Your Integration
The examples in this guide provide a general-purpose AI agent. You can customize the integration to match your specific use case:
Customizing the Agent Prompt (Step 3)
In the create-response edge function, modify the AGENT_PROMPT constant to give your agent specific instructions, domain knowledge, or personality:
const AGENT_PROMPT = `You are a marketing specialist AI agent...
- Focus on SEO and content marketing
- Create engaging, conversion-focused content
- Follow brand guidelines for [Your Brand]
...`;Customizing the Input Form (Step 6)
Instead of a simple textarea, you can create structured forms with specific fields:
// Example: Event planning form
const formData = {
eventName: string,
date: date,
budget: number,
requirements: string[]
}
// Pass to agent as JSON
body: JSON.stringify({
taskPrompt: `Plan an event with these details:\n${JSON.stringify(formData, null, 2)}`
})Or keep it simple with a prompt-based approach that lets users describe their needs in natural language.
Tip: Start with the simple prompt-based form, gather user feedback, and add structure only where it provides clear value.
For more details on the Lumnis AI SDK, refer to the JavaScript SDK documentation.