diff --git a/src/app/api/economics/route.ts b/src/app/api/economics/route.ts
new file mode 100644
index 00000000..b3273a67
--- /dev/null
+++ b/src/app/api/economics/route.ts
@@ -0,0 +1,9 @@
+import { modelEconomics } from "@/lib/economics";
+
+export function GET() {
+ return Response.json({
+ generatedAt: new Date().toISOString(),
+ count: modelEconomics.length,
+ models: modelEconomics,
+ });
+}
diff --git a/src/app/economics/compare/page.tsx b/src/app/economics/compare/page.tsx
new file mode 100644
index 00000000..ac46ea20
--- /dev/null
+++ b/src/app/economics/compare/page.tsx
@@ -0,0 +1,132 @@
+/* eslint-disable react/no-unescaped-entities */
+import { Badge } from "@/components/ui/badge";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Separator } from "@/components/ui/separator";
+import { costEfficiencyScore, modelEconomics, type ModelEconomics } from "@/lib/economics";
+
+const formatCurrency = (value: number) =>
+ new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ minimumFractionDigits: value < 1 ? 3 : 2,
+ maximumFractionDigits: value < 1 ? 3 : 2,
+ }).format(value);
+
+const scoreByUseCase = (model: ModelEconomics, useCase: string) => {
+ const qualityWeight = useCase === "feature-build" ? 0.6 : 0.45;
+ const speedWeight = useCase === "testing" ? 0.35 : 0.2;
+ const efficiencyWeight = 0.2;
+ const affinityWeight = 0.15;
+
+ const affinity = model.recommendedFor.includes(useCase) ? 10 : 5;
+
+ return (
+ model.qualityRating * qualityWeight +
+ model.speedRating * speedWeight +
+ Math.min(costEfficiencyScore(model), 10) * efficiencyWeight +
+ affinity * affinityWeight
+ );
+};
+
+const useCases = [
+ { id: "feature-build", label: "Feature builds" },
+ { id: "bug-fix", label: "Bug fixing" },
+ { id: "code-review", label: "Code review" },
+ { id: "testing", label: "Testing pipelines" },
+ { id: "docs", label: "Documentation" },
+];
+
+export default function EconomicsComparePage() {
+ const ranked = [...modelEconomics].sort((a, b) => costEfficiencyScore(b) - costEfficiencyScore(a));
+
+ return (
+
+
+
+ Model Cost Comparison
+
+ Compare model economics side-by-side
+
+ Compare price, context window, speed, and quality. Cost-efficiency score highlights how much quality you get per dollar.
+
+
+
+
+
+
+
+ {ranked.map((model, index) => {
+ const score = costEfficiencyScore(model);
+
+ return (
+
+
+
+
+
{model.name}
+
{model.provider}
+
+ {index === 0 &&
Best value}
+
+
+
+
+ Input / 1M
+ {formatCurrency(model.inputPricePer1M)}
+
+
+ Output / 1M
+ {formatCurrency(model.outputPricePer1M)}
+
+
+ Context window
+ {model.contextWindow.toLocaleString()}
+
+
+ Speed rating
+ {model.speedRating.toFixed(1)} / 10
+
+
+ Quality rating
+ {model.qualityRating.toFixed(1)} / 10
+
+
+ Cost-efficiency score
+ {score.toFixed(2)}
+
+
+
+ );
+ })}
+
+
+
+
+
+
+ Best model recommendations by use case
+
+ {useCases.map((useCase) => {
+ const best = [...modelEconomics].sort(
+ (a, b) => scoreByUseCase(b, useCase.id) - scoreByUseCase(a, useCase.id)
+ )[0];
+
+ return (
+
+
+ {useCase.label}
+
+
+ {best.name}
+
+ Quality {best.qualityRating.toFixed(1)} · Speed {best.speedRating.toFixed(1)} · Efficiency {costEfficiencyScore(best).toFixed(2)}
+
+
+
+ );
+ })}
+
+
+
+ );
+}
diff --git a/src/app/economics/page.tsx b/src/app/economics/page.tsx
new file mode 100644
index 00000000..3c55943d
--- /dev/null
+++ b/src/app/economics/page.tsx
@@ -0,0 +1,350 @@
+/* eslint-disable react/no-unescaped-entities */
+"use client";
+
+import Link from "next/link";
+import { useMemo, useState } from "react";
+import { Badge } from "@/components/ui/badge";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Separator } from "@/components/ui/separator";
+import {
+ calculateTokenCostUSD,
+ complexityMultipliers,
+ modelEconomics,
+ taskProfiles,
+ type ComplexityKey,
+ type TaskType,
+} from "@/lib/economics";
+
+const featuredModelIds = [
+ "gpt-5.3",
+ "gpt-5.3-codex",
+ "claude-opus-4.1",
+ "claude-sonnet-4.5",
+ "gemini-2.5-pro",
+ "llama-4-maverick",
+];
+
+const complexityLabels: Record = {
+ low: "Low",
+ medium: "Medium",
+ high: "High",
+ extreme: "Extreme",
+};
+
+const formatCurrency = (value: number) =>
+ new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ minimumFractionDigits: value < 1 ? 4 : 2,
+ maximumFractionDigits: value < 1 ? 4 : 2,
+ }).format(value);
+
+export default function EconomicsHubPage() {
+ const [taskType, setTaskType] = useState("bug-fix");
+ const [complexity, setComplexity] = useState("medium");
+ const [selectedModelId, setSelectedModelId] = useState("gpt-5.3-codex");
+
+ const [tasksPerDay, setTasksPerDay] = useState(120);
+ const [avgInputTokens, setAvgInputTokens] = useState(3200);
+ const [avgOutputTokens, setAvgOutputTokens] = useState(1400);
+ const [mixPrimary, setMixPrimary] = useState("gpt-5.3-codex");
+ const [mixSecondary, setMixSecondary] = useState("claude-sonnet-4.5");
+ const [mixTertiary, setMixTertiary] = useState("gemini-2.5-flash");
+ const [mixPrimaryShare, setMixPrimaryShare] = useState(40);
+ const [mixSecondaryShare, setMixSecondaryShare] = useState(35);
+
+ const tertiaryShare = Math.max(0, 100 - mixPrimaryShare - mixSecondaryShare);
+
+ const featuredModels = useMemo(
+ () => modelEconomics.filter((model) => featuredModelIds.includes(model.id)),
+ []
+ );
+
+ const selectedModel =
+ modelEconomics.find((model) => model.id === selectedModelId) ?? modelEconomics[0];
+
+ const taskEstimate = useMemo(() => {
+ const profile = taskProfiles[taskType];
+ const multiplier = complexityMultipliers[complexity];
+ const input = Math.round(profile.inputTokens * multiplier);
+ const output = Math.round(profile.outputTokens * multiplier);
+ const cost = calculateTokenCostUSD(selectedModel, input, output);
+
+ return {
+ input,
+ output,
+ cost,
+ };
+ }, [complexity, selectedModel, taskType]);
+
+ const monthlyProjection = useMemo(() => {
+ const primaryModel = modelEconomics.find((model) => model.id === mixPrimary) ?? modelEconomics[0];
+ const secondaryModel =
+ modelEconomics.find((model) => model.id === mixSecondary) ?? modelEconomics[1] ?? modelEconomics[0];
+ const tertiaryModel =
+ modelEconomics.find((model) => model.id === mixTertiary) ?? modelEconomics[2] ?? modelEconomics[0];
+
+ const costFor = (modelId: string) => {
+ const model = modelEconomics.find((candidate) => candidate.id === modelId) ?? modelEconomics[0];
+ return calculateTokenCostUSD(model, avgInputTokens, avgOutputTokens);
+ };
+
+ const weightedTaskCost =
+ costFor(primaryModel.id) * (mixPrimaryShare / 100) +
+ costFor(secondaryModel.id) * (mixSecondaryShare / 100) +
+ costFor(tertiaryModel.id) * (tertiaryShare / 100);
+
+ const monthlyTasks = tasksPerDay * 30;
+
+ return {
+ weightedTaskCost,
+ monthlyTasks,
+ monthlyCost: weightedTaskCost * monthlyTasks,
+ annualCost: weightedTaskCost * monthlyTasks * 12,
+ models: [primaryModel, secondaryModel, tertiaryModel],
+ };
+ }, [
+ avgInputTokens,
+ avgOutputTokens,
+ mixPrimary,
+ mixPrimaryShare,
+ mixSecondary,
+ mixSecondaryShare,
+ mixTertiary,
+ tasksPerDay,
+ tertiaryShare,
+ ]);
+
+ return (
+
+
+
+ Agent Economics Hub
+
+ Agent Economics & Cost Calculator
+
+ Understand true operating cost per task, compare model pricing, and project monthly agent spend before your workload scales.
+
+
+
+
+
+
+
+
Model cost comparison
+
+ Open deep comparison →
+
+
+
+
+
+
+
+ | Model |
+ Provider |
+ Input / 1M |
+ Output / 1M |
+
+
+
+ {featuredModels.map((model, index) => (
+
+ | {model.name} |
+ {model.provider} |
+ {formatCurrency(model.inputPricePer1M)} |
+ {formatCurrency(model.outputPricePer1M)} |
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ Cost per task estimator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Projected cost for this task
+
{formatCurrency(taskEstimate.cost)}
+
+ {taskEstimate.input.toLocaleString()} input + {taskEstimate.output.toLocaleString()} output tokens
+
+
+
+
+
+
+
+ Monthly cost projection
+
+
+
+
+ setTasksPerDay(Number(event.target.value))}
+ className="w-full mt-1"
+ />
+
+
+
+
+ setAvgInputTokens(Number(event.target.value))}
+ className="w-full mt-1"
+ />
+
+
+
+
+ setAvgOutputTokens(Number(event.target.value))}
+ className="w-full mt-1"
+ />
+
+
+
+
+
+
+
+ setMixPrimaryShare(Number(event.target.value))} className="w-full" />
+
+
+
+
+
+
+
+ setMixSecondaryShare(Number(event.target.value))} className="w-full" />
+
+
+
+
+
+
Tertiary mix auto-balances: {tertiaryShare}%
+
+
+
+
+
Weighted cost per task
+
{formatCurrency(monthlyProjection.weightedTaskCost)}
+
Monthly: {formatCurrency(monthlyProjection.monthlyCost)}
+
Annual run-rate: {formatCurrency(monthlyProjection.annualCost)}
+
+
+
+
+
+
+
+
+ How to reduce agent costs
+
+
+
+ Caching strategy
+
+
+ Cache stable system prompts, docs retrieval blocks, and repeated context so agents spend fewer input tokens each run.
+
+
+
+
+
+ Model routing
+
+
+ Route simple tests and docs work to lower-cost models. Escalate only complex feature and architecture tasks to premium models.
+
+
+
+
+
+ Prompt optimization
+
+
+ Keep prompts short, structured, and explicit. Better instructions reduce retries, output bloat, and wasted token cycles.
+
+
+
+
+
+ );
+}
diff --git a/src/data/model-economics.json b/src/data/model-economics.json
new file mode 100644
index 00000000..0953b94b
--- /dev/null
+++ b/src/data/model-economics.json
@@ -0,0 +1,110 @@
+[
+ {
+ "id": "gpt-5.3",
+ "name": "GPT-5.3",
+ "provider": "OpenAI",
+ "family": "GPT",
+ "inputPricePer1M": 10,
+ "outputPricePer1M": 30,
+ "contextWindow": 256000,
+ "speedRating": 7.2,
+ "qualityRating": 9.8,
+ "recommendedFor": ["feature-build", "research", "architecture"]
+ },
+ {
+ "id": "gpt-5.3-codex",
+ "name": "GPT-5.3-Codex",
+ "provider": "OpenAI",
+ "family": "GPT",
+ "inputPricePer1M": 8,
+ "outputPricePer1M": 24,
+ "contextWindow": 256000,
+ "speedRating": 8,
+ "qualityRating": 9.6,
+ "recommendedFor": ["bug-fix", "feature-build", "testing", "code-review"]
+ },
+ {
+ "id": "claude-opus-4.1",
+ "name": "Claude Opus 4.1",
+ "provider": "Anthropic",
+ "family": "Claude Opus",
+ "inputPricePer1M": 15,
+ "outputPricePer1M": 75,
+ "contextWindow": 200000,
+ "speedRating": 6.5,
+ "qualityRating": 9.9,
+ "recommendedFor": ["feature-build", "research", "docs"]
+ },
+ {
+ "id": "claude-sonnet-4.5",
+ "name": "Claude Sonnet 4.5",
+ "provider": "Anthropic",
+ "family": "Claude Sonnet",
+ "inputPricePer1M": 3,
+ "outputPricePer1M": 15,
+ "contextWindow": 200000,
+ "speedRating": 8.2,
+ "qualityRating": 9,
+ "recommendedFor": ["code-review", "docs", "testing", "bug-fix"]
+ },
+ {
+ "id": "gemini-2.5-pro",
+ "name": "Gemini 2.5 Pro",
+ "provider": "Google",
+ "family": "Gemini",
+ "inputPricePer1M": 2.5,
+ "outputPricePer1M": 10,
+ "contextWindow": 1000000,
+ "speedRating": 7.8,
+ "qualityRating": 8.9,
+ "recommendedFor": ["research", "feature-build", "docs"]
+ },
+ {
+ "id": "gemini-2.5-flash",
+ "name": "Gemini 2.5 Flash",
+ "provider": "Google",
+ "family": "Gemini",
+ "inputPricePer1M": 0.3,
+ "outputPricePer1M": 1.5,
+ "contextWindow": 1000000,
+ "speedRating": 9.5,
+ "qualityRating": 7.8,
+ "recommendedFor": ["testing", "docs", "support"]
+ },
+ {
+ "id": "llama-4-maverick",
+ "name": "Llama 4 Maverick",
+ "provider": "Meta",
+ "family": "Llama",
+ "inputPricePer1M": 0.6,
+ "outputPricePer1M": 2,
+ "contextWindow": 128000,
+ "speedRating": 8.6,
+ "qualityRating": 7.6,
+ "recommendedFor": ["testing", "classification", "docs"]
+ },
+ {
+ "id": "llama-3.3-70b",
+ "name": "Llama 3.3 70B",
+ "provider": "Meta",
+ "family": "Llama",
+ "inputPricePer1M": 0.8,
+ "outputPricePer1M": 2.4,
+ "contextWindow": 128000,
+ "speedRating": 8.1,
+ "qualityRating": 7.9,
+ "recommendedFor": ["code-review", "testing", "docs"]
+ },
+ {
+ "id": "mistral-large-2",
+ "name": "Mistral Large 2",
+ "provider": "Mistral",
+ "family": "Mistral",
+ "inputPricePer1M": 2,
+ "outputPricePer1M": 6,
+ "contextWindow": 128000,
+ "speedRating": 8.4,
+ "qualityRating": 8.3,
+ "recommendedFor": ["code-review", "agent-routing", "docs"]
+ }
+]
diff --git a/src/lib/economics.ts b/src/lib/economics.ts
new file mode 100644
index 00000000..b3c9b566
--- /dev/null
+++ b/src/lib/economics.ts
@@ -0,0 +1,55 @@
+import modelEconomicsData from "@/data/model-economics.json";
+
+export interface ModelEconomics {
+ id: string;
+ name: string;
+ provider: string;
+ family: string;
+ inputPricePer1M: number;
+ outputPricePer1M: number;
+ contextWindow: number;
+ speedRating: number;
+ qualityRating: number;
+ recommendedFor: string[];
+}
+
+export type TaskType =
+ | "code-review"
+ | "bug-fix"
+ | "feature-build"
+ | "docs"
+ | "testing";
+
+export const modelEconomics = modelEconomicsData as ModelEconomics[];
+
+export const taskProfiles: Record = {
+ "code-review": { label: "Code review", inputTokens: 4200, outputTokens: 1100 },
+ "bug-fix": { label: "Bug fix", inputTokens: 6200, outputTokens: 1800 },
+ "feature-build": { label: "Feature build", inputTokens: 12000, outputTokens: 4200 },
+ docs: { label: "Documentation", inputTokens: 3500, outputTokens: 1700 },
+ testing: { label: "Testing", inputTokens: 7000, outputTokens: 2300 },
+};
+
+export const complexityMultipliers = {
+ low: 0.7,
+ medium: 1,
+ high: 1.5,
+ extreme: 2.2,
+} as const;
+
+export type ComplexityKey = keyof typeof complexityMultipliers;
+
+export function calculateTokenCostUSD(model: ModelEconomics, inputTokens: number, outputTokens: number) {
+ const inputCost = (inputTokens / 1_000_000) * model.inputPricePer1M;
+ const outputCost = (outputTokens / 1_000_000) * model.outputPricePer1M;
+ return inputCost + outputCost;
+}
+
+export function blendedPricePer1M(model: ModelEconomics) {
+ return (model.inputPricePer1M + model.outputPricePer1M) / 2;
+}
+
+export function costEfficiencyScore(model: ModelEconomics) {
+ const efficiencyBase = model.qualityRating / Math.max(blendedPricePer1M(model), 0.1);
+ return efficiencyBase * 10;
+}