How Firebase Genkit is integrated into the Argument Analysis Tool
The Argument Analysis Tool uses Firebase Genkit as its AI orchestration framework. Genkit provides structured flows, tools, and prompts with type-safe schemas.
Location: src/ai/genkit.tsThe Genkit instance is configured with Google AI (Gemini) as the model provider:
src/ai/genkit.ts
import {genkit} from 'genkit';import {googleAI} from '@genkit-ai/google-genai';export const ai = genkit({ plugins: [googleAI()], model: 'googleai/gemini-2.5-flash',});
const prompt = ai.definePrompt({ name: 'explainLogicalFallacyPrompt', input: {schema: ExplainLogicalFallacyInputSchema}, output: {schema: ExplainLogicalFallacyOutputSchema}, prompt: `You are an expert in logic and rhetoric. Provide a clear, concise explanation for the following logical fallacy: {{{fallacyName}}}. Explain what the fallacy is and provide a simple example. {{json}}`,});
The {{{{json}}}} template variable instructs Genkit to return structured JSON matching the output schema.
From src/ai/flows/generate-argument-blueprint.ts:72:
const mainAnalysisPrompt = ai.definePrompt({ name: 'mainAnalysisPrompt', input: {schema: z.object({ input: z.string(), searchQuery: z.string() })}, output: {schema: z.object({ blueprint: z.array(ArgumentNodeSchema), summary: z.string(), analysis: z.string(), })}, tools: [webSearch], // AI can call this tool during execution system: `You are an expert AI assistant specializing in rigorous, balanced, and detailed argument deconstruction. Your task is to provide a comprehensive, neutral, and multi-faceted analysis. **Core Principles:** 1. **Objectivity is Paramount**: Act as a neutral synthesizer 2. **Depth and Detail**: Go beyond the surface 3. **Ground Everything in Sources**: Every node must cite sources 4. **Find the Opposition**: Search for credible counter-arguments **Execution Process:** 1. Analyze Input 2. Comprehensive Web Search using webSearch tool with searchQuery 3. Identify Core Thesis 4. Deconstruct Both Sides (claims and counterclaims) 5. Excavate Evidence 6. Build the JSON Blueprint 7. Generate Summary & Analysis You must respond with a valid JSON object enclosed in a \`\`\`json code block.`, prompt: `Initial Input: {{{input}}}`,});
export const webSearch = ai.defineTool( { name: 'webSearch', description: 'Searches the web for a given query and returns a list of search results, including organic results, news, and academic papers to get a comprehensive overview.', inputSchema: WebSearchInputSchema, outputSchema: WebSearchOutputSchema, }, async (input) => { if (!process.env.SERPAPI_API_KEY) { throw new Error('SERPAPI_API_KEY is not configured.'); } const response = await getJson({ api_key: process.env.SERPAPI_API_KEY, q: input.query, engine: 'google', location: 'United States', }); const organicResults = (response.organic_results || []).map(result => ({ title: result.title, link: result.link, snippet: result.snippet, })); return organicResults.slice(0, 7); });
From src/ai/flows/generate-argument-blueprint.ts:24:
const ArgumentNodeSchema = z.object({ id: z.string().describe('Unique identifier for the argument node.'), parentId: z.string().nullable().describe( 'ID of the parent node, or null if it is a root node.' ), type: z.enum(['thesis', 'claim', 'counterclaim', 'evidence']).describe( 'Type of the argument node.' ), side: z.enum(['for', 'against']).describe( 'Side of the argument node.' ), content: z.string().describe('The content of the argument node.'), sourceText: z.string().describe( 'The original text snippet from the source that supports the content.' ), source: z.string().url().describe( 'The URL of the source document.' ), fallacies: z.array(z.string()).describe( 'An array of logical fallacies identified in this specific argument node.' ), logicalRole: z.string().describe( "A concise statement explaining the node's function in the overall argument." ),});const BlueprintSchema = z.object({ blueprint: z.array(ArgumentNodeSchema).describe( 'A structured JSON blueprint of the arguments.' ), summary: z.string().describe( "A concise, neutral summary of the overall state of the debate." ), analysis: z.string().describe( "AI-driven meta-analysis providing novel insights." ),});
The .describe() method adds descriptions that Genkit passes to the AI model, improving output quality and accuracy.
Use those results to construct the argument blueprint
The AI decides when to call tools based on the prompt instructions and tool descriptions. Make sure your prompts clearly instruct the AI to use the tools when needed.
Genkit automatically validates outputs against schemas:
const {output} = await prompt(input);// output is typed and validated against outputSchemaif (!output) { throw new Error('Prompt failed to produce valid output');}return output;
if (!process.env.SERPAPI_API_KEY || process.env.SERPAPI_API_KEY === 'YOUR_API_KEY_HERE') { throw new Error( 'SERPAPI_API_KEY is not configured. Please add it to your .env file.' );}
import { generateArgumentBlueprint } from '@/ai/flows/generate-argument-blueprint';import type { GenerateArgumentBlueprintInput, GenerateArgumentBlueprintOutput} from '@/ai/flows/generate-argument-blueprint';const input: GenerateArgumentBlueprintInput = { input: 'Should AI be regulated?'};const result: GenerateArgumentBlueprintOutput = await generateArgumentBlueprint(input);// Full autocomplete and type checkingconsole.log(result.blueprint); // ArgumentNode[]console.log(result.summary); // stringconsole.log(result.tweets); // Tweet[]