The Argument Analysis Tool uses Firebase Genkit flows to orchestrate AI-powered analysis. Each flow is a self-contained AI agent with defined input/output schemas and specific responsibilities.
Architecture Overview
All flows are defined in src/ai/flows/ and registered in src/ai/dev.ts:
'use server';
import { config } from 'dotenv';
config();
import '@/ai/flows/summarize-source-text.ts';
import '@/ai/flows/identify-logical-fallacies.ts';
import '@/ai/flows/generate-argument-blueprint.ts';
import '@/ai/flows/explain-logical-fallacy.ts';
import '@/ai/tools/web-search.ts';
import '@/ai/tools/twitter-search.ts';
import '@/ai/tools/web-scraper.ts';
All flows use the 'use server' directive to ensure they run on the server side only, protecting API keys and sensitive logic.
Generate Argument Blueprint
Location: src/ai/flows/generate-argument-blueprint.ts
The most complex flow in the system. It takes a topic, URL, or document and generates a comprehensive structured argument tree with claims, counterclaims, and evidence.
const GenerateArgumentBlueprintInputSchema = z.object({
input: z.string().describe('A topic query, URL, or document to analyze.'),
});
A topic query (e.g., “climate change”), URL to analyze, or document text
Output Schema
const GenerateArgumentBlueprintOutputSchema = z.object({
blueprint: z.array(ArgumentNodeSchema),
summary: z.string(),
analysis: z.string(),
socialPulse: z.string(),
tweets: z.array(TweetSchema),
});
Structured array of argument nodes forming a logical tree
Concise, neutral summary of the overall debate state
AI-driven meta-analysis with novel insights and logical gaps
Summary of public sentiment from X/Twitter discussions
Top 5 most-liked relevant tweets
ArgumentNode Schema
const ArgumentNodeSchema = z.object({
id: z.string(),
parentId: z.string().nullable(),
type: z.enum(['thesis', 'claim', 'counterclaim', 'evidence']),
side: z.enum(['for', 'against']),
content: z.string(),
sourceText: z.string(),
source: z.string().url(),
fallacies: z.array(z.string()),
logicalRole: z.string(),
});
Flow Execution Process
The flow follows a multi-stage pipeline:
const generateArgumentBlueprintFlow = ai.defineFlow(
{
name: 'generateArgumentBlueprintFlow',
inputSchema: GenerateArgumentBlueprintInputSchema,
outputSchema: GenerateArgumentBlueprintOutputSchema,
},
async (input) => {
// Step 1: Generate search query
const searchQueryResponse = await searchQueryPrompt(input);
const searchQuery = searchQueryResponse.output?.searchQuery;
// Step 2: Main analysis with web search
const mainAnalysisResponse = await mainAnalysisPrompt({
...input,
searchQuery
});
// Step 3: Parse JSON from AI response
const jsonBlockMatch = rawText.match(/```json\n([\s\S]*?)\n```/);
const coreAnalysis = JSON.parse(jsonBlockMatch[1]);
// Step 4: Twitter/X social pulse (with graceful fallback)
const twitterResult = await twitterSearch({ query: searchQuery });
const sortedTweets = twitterResult.sort(
(a, b) => b.public_metrics.like_count - a.public_metrics.like_count
);
const socialPulseResult = await socialPulsePrompt({
tweets: tweets.map(t => t.text)
});
// Step 5: Combine results
return {
...coreAnalysis,
socialPulse: socialPulse,
tweets: tweets.slice(0, 5),
};
}
);
Prompt Engineering Strategy
The main analysis prompt uses sophisticated prompt engineering with three defined prompts:
1. Search Query Prompt
Generates a concise 2-4 word search query from user input:
const searchQueryPrompt = ai.definePrompt({
name: 'searchQueryPrompt',
input: { schema: z.object({ input: z.string() }) },
output: {
schema: z.object({
searchQuery: z.string().describe(
"A concise 2-4 word search query representing the core topic"
)
})
},
prompt: `Based on the following user input, generate a concise 2-4 word
search query that captures the absolute core topic.
User Input: {{{input}}}`,
});
2. Main Analysis Prompt
The core prompt with comprehensive instructions:
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],
system: `You are an expert AI assistant specializing in rigorous,
balanced, and detailed argument deconstruction.
**Core Principles:**
1. **Objectivity is Paramount**: Act as a neutral synthesizer
2. **Depth and Detail**: Multiple distinct lines of reasoning
3. **Ground Everything in Sources**: Every node must cite sources
4. **Find the Opposition**: Comprehensive search for counter-arguments
**Execution Process:**
1. Analyze Input
2. Comprehensive Web Search using webSearch tool
3. Identify Core Thesis
4. Deconstruct Both Sides (claims for, counterclaims against)
5. Excavate Evidence for Every Claim
6. Build the Blueprint with all fields populated
7. Generate Summary & Analysis`,
});
The main prompt instructs the AI to return JSON within a ```json code block. The flow manually extracts and parses this JSON using regex matching.
3. Social Pulse Prompt
Summarizes tweet sentiment:
const socialPulsePrompt = ai.definePrompt({
name: 'socialPulsePrompt',
input: { schema: z.object({ tweets: z.array(z.string()) }) },
output: {
schema: z.object({
socialPulse: z.string().describe(
"A brief, neutral summary of public sentiment and key points"
)
})
},
prompt: `Analyze the following tweets and write a brief, neutral summary
of the public sentiment and key discussion points, similar to
the style of Grok on X/Twitter.`,
});
Error Handling
The flow implements graceful degradation:
try {
const twitterResult = await twitterSearch({ query: searchQuery });
// Process tweets...
} catch (error: any) {
console.error("Twitter search failed, continuing with main analysis.");
// socialPulse and tweets remain empty
}
Twitter/X integration failures don’t break the entire analysis - the flow returns results with empty social pulse data.
Identify Logical Fallacies
Location: src/ai/flows/identify-logical-fallacies.ts
Analyzes argument text to detect logical fallacies and provide explanations.
const IdentifyLogicalFallaciesInputSchema = z.object({
argumentText: z.string().describe(
'The text of the argument to analyze for logical fallacies.'
),
});
Output Schema
const IdentifyLogicalFallaciesOutputSchema = z.object({
fallacies: z.array(z.string()).describe(
'An array of logical fallacies identified in the argument.'
),
explanation: z.string().describe(
'A detailed explanation of each identified logical fallacy.'
),
});
Implementation
const prompt = ai.definePrompt({
name: 'identifyLogicalFallaciesPrompt',
input: {schema: IdentifyLogicalFallaciesInputSchema},
output: {schema: IdentifyLogicalFallaciesOutputSchema},
prompt: `You are an expert in logical fallacies. Identify any logical
fallacies present in the given argument text and provide a
detailed explanation for each.
Argument Text: {{{argumentText}}}
{{json}}`,
});
const identifyLogicalFallaciesFlow = ai.defineFlow(
{
name: 'identifyLogicalFallaciesFlow',
inputSchema: IdentifyLogicalFallaciesInputSchema,
outputSchema: IdentifyLogicalFallaciesOutputSchema,
},
async input => {
const {output} = await prompt(input);
return output!;
}
);
Explain Logical Fallacy
Location: src/ai/flows/explain-logical-fallacy.ts
Provides detailed explanations for specific logical fallacies.
const ExplainLogicalFallacyInputSchema = z.object({
fallacyName: z.string().describe(
'The name of the logical fallacy to explain.'
),
});
Output Schema
const ExplainLogicalFallacyOutputSchema = z.object({
explanation: z.string().describe(
'A detailed explanation of the logical fallacy.'
),
});
Implementation
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}}`,
});
const explainLogicalFallacyFlow = ai.defineFlow(
{
name: 'explainLogicalFallacyFlow',
inputSchema: ExplainLogicalFallacyInputSchema,
outputSchema: ExplainLogicalFallacyOutputSchema,
},
async input => {
const {output} = await prompt(input);
return output!;
}
);
Summarize Source Text
Location: src/ai/flows/summarize-source-text.ts
Generates concise summaries of source documents.
const SummarizeSourceTextInputSchema = z.object({
sourceText: z.string().describe('The source text to summarize.'),
});
Output Schema
const SummarizeSourceTextOutputSchema = z.object({
summary: z.string().describe('A concise summary of the source text.'),
});
Implementation
const summarizeSourceTextPrompt = ai.definePrompt({
name: 'summarizeSourceTextPrompt',
input: {schema: SummarizeSourceTextInputSchema},
output: {schema: SummarizeSourceTextOutputSchema},
prompt: `Summarize the following text in a concise manner:
{{{sourceText}}}`,
});
const summarizeSourceTextFlow = ai.defineFlow(
{
name: 'summarizeSourceTextFlow',
inputSchema: SummarizeSourceTextInputSchema,
outputSchema: SummarizeSourceTextOutputSchema,
},
async input => {
const {output} = await summarizeSourceTextPrompt(input);
return output!;
}
);
Usage Example
import { generateArgumentBlueprint } from '@/ai/flows/generate-argument-blueprint';
import { identifyLogicalFallacies } from '@/ai/flows/identify-logical-fallacies';
// Generate full argument analysis
const result = await generateArgumentBlueprint({
input: 'Should artificial intelligence be regulated?'
});
console.log(result.blueprint); // ArgumentNode[]
console.log(result.summary); // Neutral debate summary
console.log(result.tweets); // Top 5 tweets
// Analyze specific argument for fallacies
const fallacyAnalysis = await identifyLogicalFallacies({
argumentText: 'Everyone agrees AI is dangerous, so it must be true.'
});
console.log(fallacyAnalysis.fallacies); // ['Ad Populum']
console.log(fallacyAnalysis.explanation); // Detailed explanation
See Also