Swarm Assessment
Automatically analyze tasks and assign optimal models to agents with SwarmAssessor, TaskAnalyzer, RoleMatcher, and ModelDiscovery.
Overview
The Swarm Assessor analyzes incoming tasks and automatically assigns the best available LLM model to each agent in the swarm. Instead of hardcoding models, let the assessor match agents to models based on task requirements, agent roles, model capabilities, and cost constraints.
Task Input
│
▼
┌──────────────┐ ┌────────────────┐ ┌──────────────┐
│ TaskAnalyzer │────▶│ RoleMatcher │────▶│ ModelScorer │
│ │ │ │ │ │
│ complexity │ │ role needs │ │ score models │
│ domains │ │ expertise │ │ rank & pick │
│ reasoning │ │ custom hints │ │ │
└──────────────┘ └────────────────┘ └──────────────┘
│
┌───────────────────────┘
▼
┌──────────────┐
│ModelDiscovery│
│ │
│ local Ollama │
│ cloud APIs │
└──────────────┘Enabling the Assessor
Use withAssessor() on the swarm builder:
import { Cogitator, Agent } from '@cogitator-ai/core';
import { swarm } from '@cogitator-ai/swarms';
const team = swarm('dev-team')
.strategy('hierarchical')
.supervisor(new Agent({ name: 'lead', model: 'ollama/llama3.2', instructions: 'Coordinate.' }))
.workers([
new Agent({ name: 'coder', model: 'ollama/llama3.2', instructions: 'Write code.' }),
new Agent({ name: 'reviewer', model: 'ollama/llama3.2', instructions: 'Review code quality.' }),
])
.agentMetadata({ coder: { expertise: ['code'] } })
.withAssessor({
preferLocal: true,
minCapabilityMatch: 0.3,
maxCostPerRun: 0.5,
enabledProviders: ['ollama', 'openai', 'anthropic'],
})
.build(cogitator);On the first team.run(...) of the swarm, the assessor runs before execution: it analyzes the task, discovers available models, and reassigns each agent to its optimal model (emitting assessor:complete). Later runs of the same Swarm keep those assignments; team.getLastAssessment() returns the result.
Assessor Configuration
| Option | Default | Description |
|---|---|---|
mode | 'rules' | 'rules': keyword analysis. 'ai': the assessor model analyzes the task. 'hybrid': the model's analysis plus every hard requirement the rules detect. 'ai' / 'hybrid' fall back to the rules (with a warning) when the model cannot run |
assessorModel | the Cogitator's llm.defaultModel | Model for 'ai' and 'hybrid' analysis |
preferLocal | true | Prefer local Ollama models when they score within 80% of the best cloud option |
minCapabilityMatch | 0.3 | Minimum score (0-1) for a model to be considered |
maxCostPerRun | undefined | Budget cap in dollars; triggers cost optimization if set |
ollamaUrl | 'http://localhost:11434' | Ollama API endpoint for model discovery |
enabledProviders | ['ollama', 'openai', 'anthropic', 'google'] | Which providers to include. Inside a Swarm, cloud models whose provider the Cogitator cannot route (no backend / API key configured) are skipped automatically |
cacheAssessments | true | Cache results for identical task/config combinations |
cacheTTL | 300000 | Cache lifetime in milliseconds (5 minutes) |
TaskAnalyzer
The TaskAnalyzer examines the input text and extracts structured requirements:
import { TaskAnalyzer } from '@cogitator-ai/swarms';
const analyzer = new TaskAnalyzer();
const reqs = analyzer.analyze('Analyze this screenshot and write a detailed code review');The analysis returns a TaskRequirements object:
| Field | Type | Detection |
|---|---|---|
needsVision | boolean | Keywords like "image", "screenshot", "diagram" |
needsToolCalling | boolean | Keywords like "search", "execute", "api", "database" |
needsLongContext | boolean | Large input (500+ words) or keywords like "codebase", "repository" |
needsReasoning | 'basic' | 'moderate' | 'advanced' | "analyze", "synthesize" -> advanced; "explain", "summarize" -> moderate |
needsSpeed | 'fast' | 'balanced' | 'slow-ok' | "quick", "urgent" -> fast; "thorough", "detailed" -> slow-ok |
costSensitivity | 'low' | 'medium' | 'high' | "cheap", "budget" -> high; "best", "premium" -> low |
complexity | 'simple' | 'moderate' | 'complex' | Word count, sentence count, multi-step indicators, conditionals |
domains | string[] | Detected from domain patterns: code, math, creative, analysis, legal, medical, finance |
In 'ai' and 'hybrid' mode the same TaskRequirements come from AiTaskAnalyzer, which runs the assessor model with a structured-output schema:
import { AiTaskAnalyzer } from '@cogitator-ai/swarms';
const aiAnalyzer = new AiTaskAnalyzer(cogitator, 'google/gemini-3.5-flash-lite');
const aiReqs = await aiAnalyzer.analyze('Analyze this screenshot and write a detailed code review');RoleMatcher
The RoleMatcher takes each agent's role and metadata and adjusts the task requirements to match what that specific agent needs (agents without a role are assessed as workers):
import { RoleMatcher } from '@cogitator-ai/swarms';
const matcher = new RoleMatcher();
const roleReqs = matcher.analyzeRole(swarmAgent, taskRequirements);Role-based adjustments:
| Role | Adjustments |
|---|---|
supervisor | Upgrades reasoning to advanced, lowers cost sensitivity |
worker | Applies expertise-based requirements (code, vision, etc.), increases cost sensitivity |
critic / advocate | Upgrades reasoning level |
moderator | Sets moderate reasoning, balanced speed |
router | Sets moderate reasoning, fast speed |
For workers, expertise further refines requirements: code / program / develop require tool calling and add the code domain, research / analysis raise the reasoning level, writing / content add creative, math / statistics add math, and image / visual / design require vision.
ModelDiscovery
The ModelDiscovery class discovers all available models across providers:
import { ModelDiscovery } from '@cogitator-ai/swarms';
const discovery = new ModelDiscovery({
ollamaUrl: 'http://localhost:11434',
enabledProviders: ['ollama', 'openai', 'anthropic', 'google'],
});
const models = await discovery.discoverAll();Discovery sources:
- Ollama — queries the
/api/tagsendpoint (5 s timeout; an unreachable server yields no local models) to find locally installed models, and infers capabilities and context windows from known model families (llama3, qwen, mistral, llava, etc.) - Cloud APIs — a built-in catalog with pricing and capabilities: OpenAI
gpt-6-astra,gpt-6.1-sol,gpt-6-luna; Anthropicclaude-opus-5-5,claude-sonnet-5-5,claude-haiku-4-5; Googlegemini-3.1-pro-preview,gemini-3.8-flash,gemini-3.5-flash-lite
Results are cached for cacheTTL. getCloudModels(providers?) returns the catalog alone. An optional second constructor argument, canRunModel(model), filters the cloud catalog (the assessor passes one that checks the Cogitator can route the model).
Each discovered model includes:
interface DiscoveredModel {
id: string;
provider: 'ollama' | 'openai' | 'anthropic' | 'google' | 'azure' | 'mistral';
displayName: string;
capabilities: {
supportsVision?: boolean;
supportsTools?: boolean;
supportsJson?: boolean;
supportsStreaming?: boolean;
};
pricing: { input: number; output: number };
contextWindow: number;
isLocal: boolean;
isAvailable: boolean;
}ModelScorer
The ModelScorer ranks every discovered model against role-specific requirements. Scoring factors include:
- Hard requirements — vision or tool-calling support; models without required capabilities score 0
- Context window — penalty for < 32K tokens when long context is needed
- Cost — local models get a +15 bonus; expensive models are penalized for cost-sensitive tasks
- Reasoning — advanced models (GPT-6 Astra / 6.1 Sol, Claude Opus and Sonnet, Gemini Pro, large local models) are boosted for advanced reasoning tasks
- Speed — fast models (GPT-6 Luna, Claude Haiku, Gemini Flash, small local models) are boosted for speed-sensitive tasks
- Domain match — coding models get a boost for code tasks
- Role fit — supervisors prefer advanced models, workers prefer cost-effective ones
Models below minCapabilityMatch are dropped; if none is left, the agent keeps its model and the assessment carries a warning. With preferLocal, the best local model wins when it scores at least 80% of the best overall. SwarmAssessor / createAssessor(config, cogitator) expose analyze(task, swarmConfig), assignModels(swarmConfig, result) and suggestModels(requirements) for use outside a swarm. Pass the Cogitator to get the same behaviour as inside a Swarm: it runs the 'ai' / 'hybrid' analysis and limits cloud models to the providers it can route. Without it every enabled provider is offered and the task is analyzed with the rules.
Dry Run
Preview assignments without executing the swarm:
const assessment = await team.dryRun({ input: 'Build a REST API with authentication' });
console.log('Task complexity:', assessment.taskAnalysis.complexity);
console.log('Detected domains:', assessment.taskAnalysis.domains);
for (const a of assessment.assignments) {
console.log(`${a.agentName}: ${a.originalModel} -> ${a.assignedModel} (score: ${a.score})`);
console.log(` Reasons: ${a.reasons.join(', ')}`);
console.log(` Fallbacks: ${a.fallbackModels.join(', ')}`);
}
console.log(`Estimated cost: $${assessment.totalEstimatedCost.toFixed(4)}`);
console.log('Warnings:', assessment.warnings);Budget Optimization
When maxCostPerRun is set and the estimated cost of a run is above it, the assessor downgrades agents, most expensive first, to the first cheaper model in their fallback list (the next-best scored models) until the estimate fits the budget. The estimate uses a token count per task complexity (500 / 1500 / 4000 tokens) and the catalog prices; local models cost nothing.
const team = swarm('budget-team')
.strategy('hierarchical')
.supervisor(leadAgent)
.workers([devA, devB, devC])
.withAssessor({
maxCostPerRun: 0.1,
preferLocal: true,
})
.build(cogitator);Locked Models
If an agent should always use a specific model regardless of assessment, set locked: true in its swarm metadata:
const auditor = new Agent({
name: 'auditor',
model: 'openai/gpt-5.5',
instructions: 'Perform security audit.',
});
const team = swarm('audit-team')
.strategy('round-robin')
.agents([auditor, helper])
.agentMetadata({ auditor: { locked: true } })
.withAssessor({ preferLocal: true })
.build(cogitator);Locked agents are skipped during assessment and keep their original model assignment. Unlocked agents are replaced by clones of themselves running the assigned, provider-qualified model (for example ollama/llama3.2:3b) — name, instructions and tools are preserved. Pipeline stages are reassigned as well.