The AI API provides isolated text generation from within tools, aligned with Vercel AI SDK generateText semantics. Requests are proxied to a dedicated generation endpoint — they do not go through the agent chat pipeline.
import { AI } from 'lua-cli';// Quick text generationconst text = await AI.generate('Summarize the latest AI news.');// Full options with rich resultconst result = await AI.generate({ model: 'google/gemini-2.0-flash', system: 'You are concise.', prompt: 'What is the weather in London?',});
Powerful Tool Enhancement: The AI API lets you embed AI generation directly in your tools with custom personas, multi-modal inputs, and rich response metadata.
User message content. Accepts a string or an array of multimodal parts (TextPart, ImagePart, FilePart) from the AI SDK.
Returns:Promise<string>
// Single argument: prompt is the user messageconst text = await AI.generate('Summarize the latest AI news.');// Two arguments: system instruction + user contentconst text2 = await AI.generate( 'You are a helpful assistant.', [{ type: 'text', text: 'What products do you recommend?' }]);// Multi-modal contentconst analysis = await AI.generate( 'You are an image analysis expert.', [ { type: 'text', text: 'What do you see?' }, { type: 'image', url: 'https://example.com/photo.jpg' } ]);
Constrain the model response to a JSON Schema. The parsed object lands on
result.output. Mirrors AI SDK Output.object({ schema }). Object-mode
only — array / choice modes are future extensions.When set on a Google model, the auto-injected google_search tool is
suppressed (Vertex does not allow mixing function-calling tools with
google_search in one request).
Returns:Promise<AiGenerateOutput>
const result = await AI.generate({ model: 'google/gemini-2.0-flash', system: 'You are concise.', prompt: 'What is the weather in London?', temperature: 0.7,});result.text // Generated textresult.finishReason // 'stop', 'length', etc.result.usage // { promptTokens, completionTokens, totalTokens }result.sources // Google Search grounding URLs
import { LuaTool, AI } from 'lua-cli/skill';import { z } from 'zod';export default class WeatherSearchTool implements LuaTool { name = 'search_weather'; description = 'Search current weather using AI with Google Search grounding'; inputSchema = z.object({ location: z.string().describe('City or location') }); async execute(input: z.infer<typeof this.inputSchema>) { const result = await AI.generate({ model: 'google/gemini-2.0-flash', system: 'You report current weather conditions concisely.', prompt: `What is the current weather in ${input.location}?`, }); return { weather: result.text, sources: result.sources?.map(s => ({ title: s.title, url: s.url })) ?? [], usage: result.usage, }; }}
Use structuredOutput to make the model return an object that conforms to a
JSON Schema. The parsed result lands on result.output — no more
JSON.parse(...) and no more “the model wrapped it in markdown again” bugs.
import { LuaTool, AI } from 'lua-cli/skill';import { z } from 'zod';import { zodToJsonSchema } from 'zod-to-json-schema';const SentimentSchema = z.object({ sentiment: z.enum(['positive', 'negative', 'neutral']), score: z.number().min(0).max(1), summary: z.string(),});export default class SentimentAnalysisTool implements LuaTool { name = 'analyze_sentiment'; description = 'Analyze the sentiment of text'; inputSchema = z.object({ text: z.string() }); async execute(input: z.infer<typeof this.inputSchema>) { const result = await AI.generate({ system: 'You are a sentiment analysis expert.', prompt: `Analyze:\n\n"${input.text}"`, temperature: 0, structuredOutput: { schema: zodToJsonSchema(SentimentSchema) as Record<string, unknown>, }, }); const parsed = SentimentSchema.safeParse(result.output); if (!parsed.success) { return { success: false, error: 'Schema mismatch', rawResponse: result.text }; } return { success: true, ...parsed.data, originalText: input.text }; }}
// Good — specific and clearconst context = `You are a product reviewer.Rate products on Quality (1-10), Value (1-10), Features (1-10).Return ONLY a JSON object with these ratings.`;// Bad — vagueconst context = `Review this product`;
Choose the right overload
Use simplified for quick text, full options when you need metadata
// Simplified — just need the textconst summary = await AI.generate('Summarize this article.', content);// Full options — need usage stats, sources, finish reasonconst result = await AI.generate({ model: 'google/gemini-2.0-flash', prompt: 'What is happening in tech today?',});console.log(result.sources); // Google Search grounding URLs