LLM Calls
AI integration is a core feature of Operaide, enabling you to build sophisticated workflows that leverage Large Language Models (LLMs) for text processing, analysis, and generation. This guide covers everything you need to know about integrating AI into your Reaktors and Aktors.
Overview
Operaide provides a comprehensive set of AI-focused Aktors that work seamlessly with multiple AI providers including OpenAI, Azure OpenAI, Anthropic, Google, and many others. The AI integration is designed to be:
- Provider-agnostic: Switch between different AI providers without changing your code
- Type-safe: Full TypeScript support with proper type inference
- Streaming-capable: Support for real-time streaming responses
- Composable: Easily combine with other Aktors in complex workflows
Core AI Aktors
aktorAICall
The primary Aktor for making LLM calls. Supports both standard and streaming responses.
import { aktorAICall, aktorAISettingProviderModel } from '@operaide/ai';
import { aktorConst } from '@operaide/aktor';
const response = aktorAICall({
messages: aktorConst([
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What is the capital of France?' }
]),
providerModel: aktorAISettingProviderModel()
});
aktorCompletePrompt
Template completion for dynamic prompt generation with variable substitution.
import { aktorCompletePrompt } from '@operaide/ai';
const completedPrompt = aktorCompletePrompt({
template: aktorConst('Hello {{name}}, today is {{date}}.'),
name: args.userName,
date: aktorConst(new Date().toLocaleDateString())
});
aktorPatchMessages
Modify existing message arrays by adding system prompts.
import { aktorPatchMessages, aktorUserPromptAsHistory } from '@operaide/ai';
const messages = aktorPatchMessages({
messages: aktorUserPromptAsHistory({
content: args.userMessage
}),
system: aktorConst('You are an expert data analyst.')
});
General Usage Patterns
Simple Q&A Workflow
import {
aktorAICall,
aktorAISettingProviderModel,
aktorMessagesFromSystemAndUser
} from '@operaide/ai';
import { aktorConst, registerReaktorDefinition } from '@operaide/aktor';
import { z } from 'zod';
registerReaktorDefinition({
reaktorDefinitionId: 'simple-qa-assistant',
label: 'AI Assistant',
description: 'Simple AI-powered question answering',
inputSchema: z.object({
question: z.string().describe('The question to ask the AI')
}),
outputSchema: z.string().describe('The AI-generated answer'),
createReaktor({ question }) {
const messages = aktorMessagesFromSystemAndUser({
user: question,
system: aktorConst('You are a helpful and knowledgeable assistant.')
});
const aiResponse = aktorAICall({
messages,
providerModel: aktorAISettingProviderModel()
});
return aiResponse;
}
});
Document Analysis Workflow
import {
aktorAICall,
aktorCompletePrompt,
aktorPatchMessages,
aktorMessagesFromSystemAndUser,
aktorAISettingProviderModel
} from '@operaide/ai';
import { aktorConst } from '@operaide/aktor';
import { dedent, registerReaktorDefinition } from '@operaide/aktor';
import { z } from 'zod';
registerReaktorDefinition({
reaktorDefinitionId: 'simple-qa-assistant',
label: 'AI Assistant',
description: 'Simple AI-powered question answering',
inputSchema: z.object({
document: z.string(),
analysisType: z.enum(['summary', 'detailed']).describe('Type of analysis to perform on the document')
}),
outputSchema: z.string().describe('The AI-generated answer'),
createReaktor({ document, analysisType }) {
const analysisPrompt = aktorCompletePrompt({
template: aktorConst(dedent`
Please analyze the following document and provide a {{analysisType}} analysis:
Document:
{{document}}
Analysis Type: {{analysisType}}
Please provide a detailed analysis including:
1. Key findings
2. Main themes
3. Actionable insights
`),
document,
analysisType
});
const messages = aktorPatchMessages({
messages: aktorMessagesFromSystemAndUser({
user: analysisPrompt
}),
system: aktorConst('You are an expert document analyst with expertise in extracting meaningful insights from text.')
});
return aktorAICall({
messages,
providerModel: aktorAISettingProviderModel()
});
}
});
Best Practices
1. Prompt Engineering
// Good: Structured, clear prompts
const structuredPrompt = dedent`
You are a professional email writer.
Task: Write a follow-up email based on the meeting notes.
Meeting Notes:
{{meetingNotes}}
Requirements:
- Professional tone
- Include action items
- Keep under 200 words
- Include a clear subject line
Format your response as JSON:
{
"subject": "Email subject line",
"body": "Email body content"
}
`;
// Avoid: Vague, unstructured prompts
const vaguePRompt = "Write an email about the meeting: {{notes}}";
2. Input Validation
import { aktorAICall, aktorAISettingProviderModel, aktorMessagesFromSystemAndUser } from '@operaide/ai';
import type { Aktor } from '@operaide/aktor';
import { createAktorFunction } from '@operaide/aktor';
import { z } from 'zod';
const validateInput = createAktorFunction('aktorValidateInput', ({ text }) => {
const schema = z.string().min(1).max(10000);
return schema.parse(text);
});
// Hint: No real reaktor here
const safeAICall = ({ userInput }: { userInput: Aktor<string> }) => {
const validatedInput = validateInput({ text: userInput });
return aktorAICall({
messages: aktorMessagesFromSystemAndUser({ user: validatedInput }),
providerModel: aktorAISettingProviderModel(),
});
};
3. Response Processing
import { aktorAICall, aktorAISettingProviderModel, aktorMessagesFromSystemAndUser } from '@operaide/ai';
import type { Aktor } from '@operaide/aktor';
import { createAktorFunction } from '@operaide/aktor';
const processAIResponse = createAktorFunction('aktorProcessAIResponse', ({ response }: { response: string }) => {
try {
// Try to parse as JSON if expected
const parsed = JSON.parse(response);
return parsed;
} catch {
// Fallback to plain text
return { content: response, type: 'text' };
}
});
// Hint: No real reaktor here
const structuredAIWorkflow = ({ input }: { input: Aktor<string> }) => {
const rawResponse = aktorAICall({
messages: aktorMessagesFromSystemAndUser({ user: input }),
providerModel: aktorAISettingProviderModel(),
});
return processAIResponse({ response: rawResponse });
};
Summary
LLM integration in Operaide provides powerful capabilities for building AI-powered workflows. Key takeaways:
- Use
aktorAICallfor all LLM interactions - Leverage
aktorCompletePromptfor dynamic prompt generation - Structure prompts clearly for better results
- Handle errors gracefully with fallbacks
- Use streaming for real-time applications
- Cache responses when appropriate
- Test AI workflows thoroughly
For more advanced AI patterns and examples, see the Examples section and explore the Prompt Engineering guide.