claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
126 lines • 5.12 kB
JavaScript
/**
* GAIA Mode Router — iter 58 (#2156)
*
* Rule-based classifier that maps each GAIA question to the appropriate
* agent mode. Empirical basis from iter 57:
* - ToolCalling (gaia-agent.ts) wins retrieval/attachment questions
* - CodeAgent (gaia-claude-p.ts) wins pure-reasoning questions
* - Naïve combination regressed by -10q, so routing is required
*
* Decision rules (evaluated in priority order):
*
* 1. ATTACHMENT — question has file_name → ToolCalling
* CodeAgent struggles with attachment piping; ToolCalling natively
* handles XLSX/PPTX/images/audio via attachment tools.
*
* 2. WEB_RETRIEVAL — question text matches retrieval keywords →
* ToolCalling (has WebSearch/WebFetch in the tool catalogue)
*
* 3. PURE_REASONING — question text matches computation/logic keywords →
* CodeAgent (executes arbitrary Python, no web round-trip needed)
*
* 4. LONG_QUESTION — question length > 400 chars → ToolCalling
* Long questions typically involve multi-hop retrieval steps.
*
* 5. DEFAULT — ToolCalling (higher baseline per iter 56b)
*
* Each decision is logged with the rule that fired so per-Q audit is trivial.
*
* Refs: iter 57 architectural finding, iter 58, #2156
*/
// ---------------------------------------------------------------------------
// Regex patterns
// ---------------------------------------------------------------------------
/**
* Keywords that indicate the question requires live web retrieval.
* ToolCalling has WebSearch + WebFetch in its catalogue.
*/
const WEB_RETRIEVAL_RE = /website|webpage|visit|browse|wikipedia|article|page about|paper titled|published in|according to|the.*\bsite\b|link|url|online|source|reference|official|org\b|\.com\b|\.gov\b|based on the.*page/i;
/**
* Keywords that indicate the question is a pure computation / logic problem.
* CodeAgent runs Python via `claude -p` Bash tool and handles these well.
*/
const PURE_REASONING_RE = /calculate|compute|math|equation|how many|distance|volume|combinations|permutations|logic puzzle|deduction|deduce|sequence|series|prove|derivat|integral|differential|probability|odds|fraction|percentage of|modulo|prime\b|fibonacci|recursive|recurrence|sorting|algorithm|big-?o|time complexity|bits?|bytes?|binary|hexadecimal|base \d/i;
/** Maximum question length before we treat it as a retrieval question. */
const LONG_QUESTION_THRESHOLD = 400;
// ---------------------------------------------------------------------------
// Core classifier
// ---------------------------------------------------------------------------
/**
* Classify a GAIA question into a mode + rule pair.
*
* Rules are evaluated in strict priority order — the first matching rule wins.
*/
export function routeQuestion(question) {
// Rule 1: attachment present → ToolCalling
if (question.file_name) {
return {
mode: 'ToolCalling',
rule: 'attachment',
reason: `file_name="${question.file_name}" — attachment tools in ToolCalling`,
};
}
const text = question.question;
// Rule 2: web retrieval keywords → ToolCalling
if (WEB_RETRIEVAL_RE.test(text)) {
const match = text.match(WEB_RETRIEVAL_RE);
return {
mode: 'ToolCalling',
rule: 'web_retrieval',
reason: `web-retrieval keyword "${match?.[0]}" detected`,
};
}
// Rule 3: pure reasoning / computation keywords → CodeAgent
if (PURE_REASONING_RE.test(text)) {
const match = text.match(PURE_REASONING_RE);
return {
mode: 'CodeAgent',
rule: 'pure_reasoning',
reason: `reasoning keyword "${match?.[0]}" detected`,
};
}
// Rule 4: long question → ToolCalling
if (text.length > LONG_QUESTION_THRESHOLD) {
return {
mode: 'ToolCalling',
rule: 'long_question',
reason: `question length ${text.length} > ${LONG_QUESTION_THRESHOLD} chars`,
};
}
// Rule 5: default → ToolCalling (higher baseline per iter 56b)
return {
mode: 'ToolCalling',
rule: 'default',
reason: 'no specific signal — defaulting to ToolCalling (iter 56b baseline)',
};
}
/**
* Route an array of questions and return per-Q decisions plus a summary.
* Zero-allocation: decisions array is returned in input order.
*/
export function routeQuestions(questions) {
const decisions = [];
const byRule = {
attachment: 0,
web_retrieval: 0,
pure_reasoning: 0,
long_question: 0,
default: 0,
};
let toolCalling = 0;
let codeAgent = 0;
for (const q of questions) {
const decision = routeQuestion(q);
decisions.push(decision);
byRule[decision.rule]++;
if (decision.mode === 'ToolCalling')
toolCalling++;
else
codeAgent++;
}
return {
decisions,
summary: { total: questions.length, toolCalling, codeAgent, byRule },
};
}
//# sourceMappingURL=gaia-mode-router.js.map