import { z } from "zod";
/**
* Agentic & Synaptic Tools - Higher-order cognitive functions
* Simulates advanced reasoning, association, and autonomous behavior.
*/
// ============================================
// Decision Matrix Tool
// ============================================
export const decisionMatrixSchema = {
name: "decision_matrix",
description:
"Evaluates options using weighted criteria to make data-driven decisions",
inputSchema: z.object({
problem: z.string().describe("The decision to be made"),
options: z.array(z.string()).describe("List of available options"),
criteria: z
.array(
z.object({
name: z.string(),
weight: z
.number()
.min(0)
.max(10)
.describe("Importance weight (1-10)"),
}),
)
.describe("Evaluation criteria"),
evaluations: z
.array(
z.object({
optionIndex: z.number(),
scores: z
.array(z.number().min(0).max(10))
.describe("Score for each criteria (in order)"),
}),
)
.optional()
.describe("Optional pre-filled scores"),
}),
};
export function decisionMatrixHandler(args: {
problem: string;
options: string[];
criteria: Array<{ name: string; weight: number }>;
evaluations?: Array<{ optionIndex: number; scores: number[] }>;
}) {
const { problem, options, criteria, evaluations } = args;
// If no evaluations provided, return the template structure to fill
if (!evaluations) {
return {
content: [
{
type: "text",
text: `# Decision Matrix Setup for: ${problem}\n\nPlease analyze the options and provide scores (0-10) for each criteria.\n\nCritera:\n${criteria.map((c, i) => `${i + 1}. ${c.name} (Weight: ${c.weight})`).join("\n")}\n\nOptions:\n${options.map((o, i) => `${i + 1}. ${o}`).join("\n")}`,
},
],
};
}
// Calculate weighted scores
const results = evaluations.map((evalItem) => {
const option = options[evalItem.optionIndex];
let totalScore = 0;
let weightedScore = 0;
let maxPossibleWeighted = 0;
evalItem.scores.forEach((score, i) => {
const weight = criteria[i].weight;
totalScore += score;
weightedScore += score * weight;
maxPossibleWeighted += 10 * weight;
});
const percent = Math.round((weightedScore / maxPossibleWeighted) * 100);
return {
option,
rawResults: evalItem.scores
.map((s, i) => `${criteria[i].name}: ${s}`)
.join(", "),
totalScore,
weightedScore,
percent,
};
});
results.sort((a, b) => b.weightedScore - a.weightedScore);
const winner = results[0];
const runnerUp = results.length > 1 ? results[1] : null;
// Sensitivity Analysis
let sensitivityNote = "";
if (runnerUp) {
const diff = winner.weightedScore - runnerUp.weightedScore;
const percentDiff = (diff / winner.weightedScore) * 100;
if (percentDiff < 5) {
sensitivityNote = `**Close Call**: The winner is only ${percentDiff.toFixed(1)}% ahead of ${runnerUp.option}. a slight change in weights could flip the result.`;
} else {
sensitivityNote = `**Clear Winner**: The winner is ${percentDiff.toFixed(1)}% ahead, indicating a robust decision.`;
}
}
return {
content: [
{
type: "text",
text: `# Decision Analysis: ${problem}
## 🏆 Winner: **${winner.option}** (${winner.percent}%)
## Sensitivity Analysis
${sensitivityNote}
## Details
${results
.map(
(r, i) => `### ${i + 1}. ${r.option}
- **Score**: ${r.weightedScore} / ${r.percent}%
- Breakdown: ${r.rawResults}`,
)
.join("\n\n")}`,
},
],
};
}
// ============================================
// Consequence Analysis Tool
// ============================================
export const consequenceAnalysisSchema = {
name: "consequence_analysis",
description:
"Analyzes 2nd and 3rd order consequences of a decision or action (Ripple Effect)",
inputSchema: z.object({
action: z.string().describe("The action or change being proposed"),
stakeholders: z
.array(z.string())
.describe("Who/what is affected (Users, DB, specific modules)"),
timeframes: z
.array(z.enum(["immediate", "short_term", "medium_term", "long_term"]))
.describe("Time horizons to analyze"),
}),
};
export function consequenceAnalysisHandler(args: {
action: string;
stakeholders: string[];
timeframes: string[];
}) {
const { action, stakeholders, timeframes } = args;
// In a real agent, this would query a knowledge base.
// Here we provide a structured template for the LLM to fill or for the user to reflect on.
return {
content: [
{
type: "text",
text: `# Consequence Analysis (Ripple Effect)\n**Action**: ${action}\n\n## Impact Matrix\n\n${timeframes
.map((time) => {
return `### ⏱️ ${time.replace("_", " ").toUpperCase()}\n${stakeholders.map((s) => `- **${s}**: [Analyze impact on ${s}]`).join("\n")}`;
})
.join(
"\n\n",
)}\n\n## ⚠️ Risks & Mitigations\n- [Identify major risks]\n- [Propose mitigations]`,
},
],
};
}
// ============================================
// Concept Association (Synaptic) Tool
// ============================================
export const conceptAssociationSchema = {
name: "concept_association",
description:
"Links concepts to build a knowledge graph and identify hidden connections",
inputSchema: z.object({
concept: z.string().describe("The central concept to analyze"),
domains: z
.array(z.string())
.optional()
.describe(
"Domains to look for associations in (e.g. 'security', 'performance', 'business')",
),
depth: z
.enum(["shallow", "deep", "abstract"])
.optional()
.default("shallow"),
}),
};
export function conceptAssociationHandler(args: {
concept: string;
domains?: string[];
depth?: string;
}) {
const { concept, domains = ["general"], depth = "shallow" } = args;
const prompts = {
shallow:
"Direct dependencies, immediate parents/children, explicit references.",
deep: "Indirect dependencies, shared resources, race conditions, architectural patterns.",
abstract:
"Metaphorical similarities, design philosophy, structural parallels, anti-patterns.",
};
return {
content: [
{
type: "text",
text: `# Synaptic Association: ${concept}\n\n**Mode**: ${depth} (${prompts[depth as keyof typeof prompts]})\n**Domains**: ${domains.join(", ")}\n\n## Associations Map\n\n1. **Direct Links**\n - [Link 1]\n - [Link 2]\n\n2. **Conceptual Parallels**\n - [Concept A] is like [Concept B] because...\n\n3. **Hidden Implications**\n - If ${concept} changes, then...\n\n4. **Pattern Recognition**\n - This resembles the [Pattern Name] pattern.`,
},
],
};
}
// ============================================
// Derive Patterns Tool
// ============================================
export const derivePatternsSchema = {
name: "derive_patterns",
description:
"Identifies repeating code or architectural patterns to suggest refactoring or standardization",
inputSchema: z.object({
sourcePaths: z
.array(z.string())
.describe("File paths or components to analyze"),
focus: z
.enum([
"code_duplication",
"architectural_style",
"naming_conventions",
"error_handling",
])
.describe("Aspect to analyze"),
}),
};
export const derivePatternsHandler = async (args: {
sourcePaths: string[];
focus: string;
}) => {
const { sourcePaths, focus } = args;
const fs = require("fs");
const path = require("path");
let findings: string[] = [];
let analyzedCount = 0;
for (const filePath of sourcePaths) {
try {
if (fs.existsSync(filePath)) {
const content = fs.readFileSync(filePath, "utf-8");
analyzedCount++;
const lines = content.split("\n");
if (focus === "code_duplication") {
// Simple heuristic: check for identical blocks of 5+ lines (very naive)
// Better: check for "TODO" or specific anti-patterns
if (content.includes("TODO")) {
findings.push(
`- ${path.basename(filePath)}: Contains TODOs, potential technical debt.`,
);
}
if (lines.length > 300) {
findings.push(
`- ${path.basename(filePath)}: Large file (${lines.length} lines), potential monolith.`,
);
}
} else if (focus === "error_handling") {
const tryCatchCount = (content.match(/try\s*{/g) || []).length;
findings.push(
`- ${path.basename(filePath)}: Found ${tryCatchCount} try-catch blocks.`,
);
} else if (focus === "architectural_style") {
if (content.includes("class ")) {
findings.push(
`- ${path.basename(filePath)}: Uses OOP (Class definitions found).`,
);
} else if (content.includes("function ")) {
findings.push(
`- ${path.basename(filePath)}: Uses Functional patterns.`,
);
}
} else if (focus === "naming_conventions") {
// Basic checks for camelCase vs snake_case
const hasSnake = /const [a-z]+_[a-z]+/.test(content);
const hasCamel = /const [a-z]+[A-Z][a-z]+/.test(content);
if (hasSnake && hasCamel) {
findings.push(
`- ${path.basename(filePath)}: Mixed naming conventions detected (snake_case and camelCase).`,
);
} else if (hasSnake) {
findings.push(
`- ${path.basename(filePath)}: Predominantly snake_case.`,
);
} else {
findings.push(
`- ${path.basename(filePath)}: Predominantly camelCase (or consistent).`,
);
}
}
} else {
findings.push(`- ${path.basename(filePath)}: File not found.`);
}
} catch (error) {
findings.push(`- ${path.basename(filePath)}: Error reading file.`);
}
}
return {
content: [
{
type: "text",
text: `# Pattern Recognition: ${focus}\n\nAnalyzing: ${analyzedCount} sources\n\n## Observed Patterns\n\n${findings.length > 0 ? findings.join("\n") : "No specific patterns detected with current heuristics."}\n\n## Recommendations\n\n- Review larger files for decomposition.\n- Standardize error handling where inconsistent.`,
},
],
};
};
// ============================================
// Research Synthesis Tool
// ============================================
export const researchSynthesisSchema = {
name: "research_synthesis",
description:
"Aggregates and synthesizes information from multiple sources to answer a complex question",
inputSchema: z.object({
topic: z.string().describe("The topic to research"),
sources: z
.array(z.string())
.describe("List of provided information/code snippets"),
goal: z.string().describe("The specific question or output needed"),
}),
};
export function researchSynthesisHandler(args: {
topic: string;
sources: string[];
goal: string;
}) {
const { topic, sources, goal } = args;
// Simple frequency analysis
const allText = sources.join(" ").toLowerCase();
const words = allText.match(/\b\w+\b/g) || [];
const wordCounts: Record<string, number> = {};
const stopWords = new Set([
"the",
"and",
"a",
"to",
"of",
"in",
"is",
"for",
"on",
"with",
"as",
"this",
"that",
"it",
]);
words.forEach((w) => {
if (!stopWords.has(w) && w.length > 3) {
wordCounts[w] = (wordCounts[w] || 0) + 1;
}
});
const topKeywords = Object.entries(wordCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([w, c]) => `${w} (${c})`);
const summaryPoints = sources.map((s, i) => {
const firstSentence = s.split(".")[0];
return `${i + 1}. ${firstSentence}.`;
});
return {
content: [
{
type: "text",
text: `# Research Synthesis: ${topic}\n\n## Goal\n${goal}\n\n## Synthesized Highlights\n\n**Common Keywords**: ${topKeywords.join(", ")}\n\n## Key Findings (Extracted)\n\n${summaryPoints.map((p) => `- ${p}`).join("\n")}\n\n## Conclusion\nBased on the analysis of ${sources.length} sources, the content revolves around ${topKeywords
.slice(0, 3)
.map((k) => k.split(" ")[0])
.join(", ")}.`,
},
],
};
}
// ============================================
// Six Thinking Hats Tool
// ============================================
export const sixThinkingHatsSchema = {
name: "six_thinking_hats",
description:
"Runs a meaningful parallel thinking session using the Six Thinking Hats method to explore a problem from all angles.",
inputSchema: z.object({
problem: z.string().describe("The problem or decision to analyze"),
participants: z
.array(z.string())
.optional()
.describe("Optional stakeholders to assign per hat"),
}),
};
export const sixThinkingHatsHandler = (args: { problem: string }) => {
const { problem } = args;
const context = problem.toLowerCase();
const hats = [
{
color: "⚪ White Hat",
focus: "Facts & Information",
questions: [
"What do we know?",
"What information is missing?",
"What data do we need?",
context.includes("performance")
? "What are the current metrics?"
: "What are the verified facts?",
],
},
{
color: "🔴 Red Hat",
focus: "Feelings & Intuition",
questions: [
"What is my gut reaction?",
"What are the emotional risks?",
"How will users feel?",
context.includes("ui")
? "Is the design frustrating?"
: "Are we excited about this?",
],
},
{
color: "⚫ Black Hat",
focus: "Caution & Risks",
questions: [
"What could go wrong?",
"What are the weaknesses?",
"Why might this fail?",
context.includes("security")
? "Where are the vulnerabilities?"
: "What is the worst case scenario?",
],
},
{
color: "🟡 Yellow Hat",
focus: "Benefits & Value",
questions: [
"What are the positives?",
"What is the value add?",
"Who benefits?",
context.includes("refactor")
? "How does this improve maintainability?"
: "What is the ROI?",
],
},
{
color: "🟢 Green Hat",
focus: "Creativity & Alternatives",
questions: [
"Are there other ways?",
"What if we break the rules?",
"Can we combine ideas?",
context.includes("deadline")
? "Is there a faster shortcut?"
: "What is the radical alternative?",
],
},
{
color: "🔵 Blue Hat",
focus: "Process & Control",
questions: [
"What is the next step?",
"How do we summarize?",
"What hat do we need next?",
],
},
];
const analysis = hats
.map(
(h) => `### ${h.color} (${h.focus})
*Guiding Questions:*
${h.questions.map((q) => `- ${q}`).join("\n")}
**Analysis**:
[Insert thoughts here based on ${h.focus.toLowerCase()}]
`,
)
.join("\n\n---\n\n");
return {
content: [
{
type: "text",
text: `# Six Thinking Hats Session: ${problem}\n\n${analysis}\n\n## Synthesis\n[Summarize the holistic view here]`,
},
],
};
};
// ============================================
// Logical Fallacy Check Tool
// ============================================
export const logicalFallacyCheckSchema = {
name: "logical_fallacy_check",
description: "Analyzes an argument or text for common logical fallacies.",
inputSchema: z.object({
text: z.string().describe("The argument or text to analyze"),
}),
};
export const logicalFallacyCheckHandler = (args: { text: string }) => {
const { text } = args;
const lowerText = text.toLowerCase();
const fallacies = [
{
name: "Ad Hominem",
description: "Attacking the person instead of the argument",
keywords: ["idiot", "stupid", "ignorant", "you are", "personally"],
},
{
name: "Straw Man",
description: "Misrepresenting the argument to make it easier to attack",
keywords: ["so you're saying", "twist", "never said", "misinterpret"],
},
{
name: "Appeal to Authority",
description: "Assuming something is true because an authority said so",
keywords: ["expert says", "doctor says", "because he is", "authority"],
},
{
name: "False Dichotomy",
description: "Presenting only two options when more exist",
keywords: ["either", "or", "only two", "black and white"],
},
{
name: "Confirmation Bias",
description: "Favoring information that confirms existing beliefs",
keywords: ["always", "knew it", "proves my point"],
},
{
name: "Sunk Cost Fallacy",
description: "Continuing because of past investment",
keywords: ["invested", "spent so much", "too late"],
},
{
name: "Circular Reasoning",
description: "The conclusion is included in the premise",
keywords: ["because", "therefore", "is true because"],
},
];
const detected = fallacies.filter((f) =>
f.keywords.some((k) => lowerText.includes(k)),
);
return {
content: [
{
type: "text",
text: `# Logical Fallacy Check\n\n**Input Text**: "${text}"\n\n## Potential Fallacies Detected\n\n${
detected.length > 0
? detected
.map(
(f) =>
`- **${f.name}**: ${f.description} (Trigger: keywords found)`,
)
.join("\n")
: "No specific fallacies detected based on simple heuristics."
}\n\n## Automated Checklist\n\n${fallacies
.map(
(f) =>
`- [${detected.includes(f) ? "x" : " "}] **${f.name}**: ${f.description}`,
)
.join(
"\n",
)}\n\n## Findings\n[Identify potential fallacies found in the text]\n\n## Recommendation\n[How to strengthen the argument]`,
},
],
};
};
// ============================================
// Causal Loop Diagram Tool
// ============================================
export const causalLoopDiagramSchema = {
name: "causal_loop_diagram",
description:
"Visualizes a system using a Causal Loop Diagram (CLD) description to identify feedback loops.",
inputSchema: z.object({
params: z
.array(z.string())
.describe("List of variables/parameters in the system"),
relationships: z
.array(
z.object({
from: z.string(),
to: z.string(),
type: z
.enum(["positive", "negative"])
.describe(
"Positive (+) means same direction, Negative (-) means opposite direction",
),
description: z.string().optional(),
}),
)
.describe("Causal links between parameters"),
}),
};
export const causalLoopDiagramHandler = (args: {
params: string[];
relationships: Array<{
from: string;
to: string;
type: "positive" | "negative";
description?: string;
}>;
}) => {
const { params, relationships } = args;
// Validation
const errors: string[] = [];
const nodes = new Set(params);
// Check for unknown nodes in relationships
relationships.forEach((r) => {
if (!nodes.has(r.from)) errors.push(`Unknown source node: ${r.from}`);
if (!nodes.has(r.to)) errors.push(`Unknown target node: ${r.to}`);
if (r.from === r.to)
errors.push(
`Self-loop detected: ${r.from} -> ${r.to} (CLDs typically involve loops of 2+ variables)`,
);
});
if (errors.length > 0) {
return {
content: [
{
type: "text",
text: `# Causal Loop Diagram Error\n\n## Issues Found\n${errors.map((e) => `- ${e}`).join("\n")}\n\nPlease correct the parameters or relationships.`,
},
],
isError: true,
};
}
const mermaidParams = params
.map((p) => {
// Sanitize for mermaid id (remove spaces, special chars)
const id = p.replace(/[^a-zA-Z0-9]/g, "");
return `${id}["${p}"]`;
})
.join("\n ");
const mermaidEdges = relationships
.map((r) => {
const fromId = r.from.replace(/[^a-zA-Z0-9]/g, "");
const toId = r.to.replace(/[^a-zA-Z0-9]/g, "");
const label = r.type === "positive" ? "+" : "-";
return `${fromId} -->|"${label}"| ${toId}`;
})
.join("\n ");
const diagram = `graph TD\n ${mermaidParams}\n ${mermaidEdges}`;
return {
content: [
{
type: "text",
text: `# Causal Loop Diagram\n\n## Visual\n\`\`\`mermaid\n${diagram}\n\`\`\`\n\n## Loop Analysis\n- **Reinforcing Loops (R)**: Creating exponential growth/collapse?\n- **Balancing Loops (B)**: Creating stability or resistance?\n\n## Insights\n[Analyze the system behavior based on loops]`,
},
],
};
};
// Export all
export const agenticTools = {
decisionMatrixSchema,
decisionMatrixHandler,
consequenceAnalysisSchema,
consequenceAnalysisHandler,
conceptAssociationSchema,
conceptAssociationHandler,
derivePatternsSchema,
derivePatternsHandler,
researchSynthesisSchema,
researchSynthesisHandler,
sixThinkingHatsSchema,
sixThinkingHatsHandler,
logicalFallacyCheckSchema,
logicalFallacyCheckHandler,
causalLoopDiagramSchema,
causalLoopDiagramHandler,
};