Firebase Genkit
When to use this skill
- AI workflow orchestration: Building multi-step AI pipelines with type-safe inputs/outputs
- Flow-based APIs: Wrapping LLM calls into deployable HTTP endpoints
- Tool calling / agents: Equipping models with custom tools and implementing agentic loops
- RAG pipelines: Retrieval-augmented generation with vector databases (Pinecone, pgvector, Firestore, Chroma, etc.)
- Multi-agent systems: Coordinating multiple specialized AI agents
- Streaming responses: Real-time token-by-token output for chat or long-form content
- Firebase/Cloud Run deployment: Deploying AI functions to Google Cloud
- Prompt management: Managing prompts as versioned
.promptfiles with Dotprompt
Installation & Setup
Step 1: Install the Genkit CLI
# npm (recommended for JavaScript/TypeScript)
npm install -g genkit-cli
# macOS/Linux binary
curl -sL cli.genkit.dev | bash
Step 2: Create a TypeScript project
mkdir my-genkit-app && cd my-genkit-app
npm init -y
npm pkg set type=module
npm install -D typescript tsx
npx tsc --init
mkdir src && touch src/index.ts
Step 3: Install Genkit core and a model plugin
# Core + Google AI (Gemini) — free tier, no credit card required
npm install genkit @genkit-ai/google-genai
# Or: Vertex AI (requires GCP project)
npm install genkit @genkit-ai/vertexai
# Or: OpenAI
npm install genkit genkitx-openai
# Or: Anthropic (Claude)
npm install genkit genkitx-anthropic
# Or: Ollama (local models)
npm install genkit genkitx-ollama
Step 4: Configure API Key
# Google AI (Gemini)
export GEMINI_API_KEY=your_key_here
# OpenAI
export OPENAI_API_KEY=your_key_here
# Anthropic
export ANTHROPIC_API_KEY=your_key_here
Core Concepts
Initializing Genkit
import { googleAI } from '@genkit-ai/google-genai';
import { genkit } from 'genkit';
const ai = genkit({
plugins: [googleAI()],
model: googleAI.model('gemini-2.5-flash'), // default model
});
Defining Flows
Flows are the core primitive: type-safe, observable, deployable AI functions.
import { genkit, z } from 'genkit';
import { googleAI } from '@genkit-ai/google-genai';
const ai = genkit({ plugins: [googleAI()] });
// Input/output schemas with Zod
const SummaryInputSchema = z.object({
text: z.string().describe('Text to summarize'),
maxWords: z.number().optional().default(100),
});
const SummaryOutputSchema = z.object({
summary: z.string(),
keyPoints: z.array(z.string()),
});
export const summarizeFlow = ai.defineFlow(
{
name: 'summarizeFlow',
inputSchema: SummaryInputSchema,
outputSchema: SummaryOutputSchema,
},
async ({ text, maxWords }) => {
const { output } = await ai.generate({
model: googleAI.model('gemini-2.5-flash'),
prompt: `Summarize the following text in at most ${maxWords} words and extract key points:\n\n${text}`,
output: { schema: SummaryOutputSchema },
});
if (!output) throw new Error('No output generated');
return output;
}
);
// Call the flow
const result = await summarizeFlow({
text: 'Long article content here...',
maxWords: 50,
});
console.log(result.summary);
Generating Content
// Simple text generation
const { text } = await ai.generate({
model: googleAI.model('gemini-2.5-flash'),
prompt: 'Explain quantum computing in one sentence.',
});
// Structured output
const { output } = await ai.generate({
prompt: 'List 3 programming languages with their use cases',
output: {
schema: z.object({
languages: z.array(z.object({
name: z.string(),
useCase: z.string(),
})),
}),
},
});
// With system prompt
const { text: response } = await ai.generate({
system: 'You are a senior TypeScript engineer. Be concise.',
prompt: 'What is the difference between interface and type in TypeScript?',
});
// Multimodal (image + text)
const { text: description } = await ai.generate({
prompt: [
{ text: 'What is in this image?' },
{ media: { url: 'https://example.com/image.jpg', contentType: 'image/jpeg' } },
],
});
Streaming Flows
export const streamingFlow = ai.defineFlow(
{
name: 'streamingFlow',
inputSchema: z.object({ topic: z.string() }),
streamSchema: z.string(), // type of each chunk
outputSchema: z.object({ full: z.string() }),
},
async ({ topic }, { sendChunk }) => {
const { stream, response } = ai.generateStream({
prompt: `Write a detailed essay about ${topic}.`,
});
for await (const chunk of stream) {
sendChunk(chunk.text); // stream each token to client
}
const { text } = await response;
return { full: text };
}
);
// Client-side consumption
const stream = streamingFlow.stream({ topic: 'AI ethics' });
for await (const chunk of stream.stream) {
process.stdout.write(chunk);
}
const finalOutput = await stream.output;
Tool Calling (Agents)
import { z } from 'genkit';
// Define tools
const getWeatherTool = ai.defineTool(
{
name: 'getWeather',
description: 'Get current weather for a city',
inputSchema: z.object({ city: z.string() }),
outputSchema: z.object({ temp: z.number(), condition: z.string() }),
},
async ({ city }) => {
// Call real weather API
return { temp: 22, condition: 'sunny' };
}
);
const searchWebTool = ai.defineTool(
{
name: 'searchWeb',
description: 'Search the web for information',
inputSchema: z.object({ query: z.string() }),
outputSchema: z.string(),
},
async ({ query }) => {
// Call search API
return `Search results for: ${query}`;
}
);
// Agent flow with tools
export const agentFlow = ai.defineFlow(
{
name: 'agentFlow',
inputSchema: z.object({ question: z.string() }),
outputSchema: z.string(),
},
async ({ question }) => {
const { text } = await ai.generate({
prompt: question,
tools: [getWeatherTool, searchWebTool],
returnToolRequests: false, // auto-execute tools
});
return text;
}
);
Prompts with Dotprompt
Manage prompts as versioned .prompt files:
# src/prompts/summarize.prompt
---
model: googleai/gemini-2.5-flash
input:
schema:
text: string
style?: string
output:
schema:
summary: string
sentiment: string
---
Summarize the following text in a {{style, default: "professional"}} tone:
{{text}}
Return JSON with summary and sentiment (positive/negative/neutral).
// Load and use dotprompt
const summarizePrompt = ai.prompt('summarize');
const { output } = await summarizePrompt({
text: 'Article content here...',
style: 'casual',
});
RAG — Retrieval-Augmented Generation
import { devLocalVectorstore } from '@genkit-ai/dev-local-vectorstore';
import { textEmbedding004 } from '@genkit-ai/google-genai';
const ai = genkit({
plugins: [
googleAI(),
devLocalVectorstore([{
indexName: 'documents',
embedder: textEmbedding004,
}]),
],
});
// Index documents
await ai.index({
indexer: devLocalVectorstoreIndexer('documents'),
docs: [
{ content: [{ text: 'Document 1 content...' }], metadata: { source: 'doc1' } },
{ content: [{ text: 'Document 2 content...' }], metadata: { source: 'doc2' } },
],
});
// RAG flow
export const ragFlow = ai.defineFlow(
{
name: 'ragFlow',
inputSchema: z.object({ question: z.string() }),
outputSchema: z.string(),
},
async ({ question }) => {
// Retrieve relevant documents
const docs = await ai.retrieve({
retriever: devLocalVectorstoreRetriever('documents'),
query: question,
options: { k: 3 },
});
// Generate answer grounded in retrieved docs
const { text } = await ai.generate({
system: 'Answer questions using only the provided context.',
prompt: question,
docs,
});
return text;