Most agent workloads are a mix of easy tasks (format this JSON, summarize this paragraph, classify this input) and hard tasks (multi-step reasoning, nuanced judgment, complex code generation). Routing every step through your most capable model is like hiring a senior engineer to rename variables — it works, but you're paying far more DA than necessary.
This recipe shows how to build a dispatcher that assigns each sub-task to the cheapest model that can handle it.
Check current pricing in the model catalog. As a rough guide:
| Tier | Example models | Typical use |
|---|
| Free | Various free models | Prototyping, high-volume classification |
| Economy | meta-llama/llama-4-maverick | Summarization, formatting, routing, triage |
| Mid | anthropic/claude-sonnet-5, google/gemini-2.5-pro | Code generation, structured extraction, multi-hop Q&A |
| Premium | anthropic/claude-opus-4.8, openai/gpt-5.4 | Complex reasoning, nuanced judgment, final synthesis |
from dataclasses import dataclass
from enum import Enum
class Tier(Enum):
FREE = "free"
ECONOMY = "economy"
MID = "mid"
PREMIUM = "premium"
@dataclass
class Task:
name: str
prompt: str
tier: Tier
max_tokens: int = 512
TIER_MODELS = {
Tier.FREE: "meta-llama/llama-4-maverick",
Tier.ECONOMY: "meta-llama/llama-4-maverick",
Tier.MID: "anthropic/claude-sonnet-5",
Tier.PREMIUM: "anthropic/claude-opus-4.8",
}
import os
from openai import OpenAI
client = OpenAI(
base_url="https://opendunes.com/api/v1",
api_key=os.environ["OPENDUNES_API_KEY"],
)
def dispatch(task: Task, context: str = "") -> str:
model = TIER_MODELS[task.tier]
messages = []
if context:
messages.append({"role": "user", "content": f"Context:\n{context}"})
messages.append({"role": "user", "content": task.prompt})
resp = client.chat.completions.create(
model=model,
messages=messages,
max_tokens=task.max_tokens,
temperature=0 if task.tier in (Tier.FREE, Tier.ECONOMY) else 0.7,
)
return resp.choices[0].message.content or ""
Imagine a pipeline that processes customer feedback: classify sentiment, extract key themes, and generate a response draft.
def process_feedback(feedback: str) -> dict:
sentiment = dispatch(Task(
name="classify_sentiment",
prompt=f"Classify the sentiment of this feedback as positive, neutral, or negative. Respond with one word only.\n\n{feedback}",
tier=Tier.ECONOMY,
max_tokens=5,
))
themes = dispatch(Task(
name="extract_themes",
prompt=f"List up to 3 key themes in this feedback, one per line, no bullets.\n\n{feedback}",
tier=Tier.ECONOMY,
max_tokens=100,
))
draft = dispatch(Task(
name="draft_response",
prompt=f"Write a polite, helpful one-paragraph response to this customer feedback.\n\nFeedback: {feedback}\nSentiment: {sentiment}\nThemes: {themes}",
tier=Tier.MID,
max_tokens=200,
))
if sentiment.strip().lower() == "negative":
draft = dispatch(Task(
name="refine_negative_response",
prompt=f"Improve this draft response to a negative customer complaint. Be empathetic and concrete.\n\nDraft: {draft}\n\nOriginal feedback: {feedback}",
tier=Tier.PREMIUM,
max_tokens=300,
))
return {"sentiment": sentiment, "themes": themes, "response_draft": draft}
Per feedback item (approximate):
| Step | Tier | Tokens | Cost |
|---|
| Sentiment | Economy | ~100 in / 5 out | < 0.01 DA |
| Themes | Economy | ~150 in / 80 out | < 0.05 DA |
| Draft response | Mid | ~250 in / 200 out | ~0.2 DA |
| Refine (negative only, ~20% of items) | Premium | ~400 in / 300 out | ~0.7 DA × 0.2 = ~0.14 DA avg |
Total per item: ~0.4 DA. Routing everything through the premium tier would cost roughly 3–4× more for the same output quality.
For more flexibility, let the dispatcher infer the tier from a difficulty score instead of hardcoding it:
def infer_tier(prompt: str) -> Tier:
"""Rough heuristic: long prompts and certain keywords signal harder tasks."""
word_count = len(prompt.split())
hard_keywords = {"reason", "analyze", "compare", "design", "debug", "refactor", "evaluate"}
if word_count > 300 or any(k in prompt.lower() for k in hard_keywords):
return Tier.MID
if word_count > 600 or "complex" in prompt.lower():
return Tier.PREMIUM
return Tier.ECONOMY
Combine this with the explicit tier parameter — explicit always wins, inference is the fallback.
Use the analytics API to see how much DA each tier is spending in production. If economy-tier calls are generating a lot of downstream rework, it may be cheaper to promote them to mid tier.