How the Spend Tier System Routes Evaluations Across AI Providers in career-ops

The spend tier system reads your spend_tier setting from config/profile.yml and translates it into a specific Claude model identifier via the spend_tier_to_model helper, automatically routing evaluations to budget-appropriate AI providers while allowing CLI overrides.

The career-ops open-source framework simplifies AI-driven job offer evaluations by abstracting provider complexity into a declarative spend tier setting. Instead of manually selecting model names or managing provider-specific API configurations, you define your budget preference in a single YAML key. The system then automatically routes inference requests to the appropriate model across pipeline, batch, and CLI execution modes.

How Spend Tier Routing Works

The routing mechanism operates through a four-stage pipeline that transforms a user-friendly configuration value into a concrete provider API call. This process is centralized in the batch runner and shared across all execution modes.

Reading the Configuration

At the start of any evaluation run—whether in pipeline, batch, or CLI mode—the system invokes a configuration helper to parse config/profile.yml. According to the shared mode documentation in modes/_shared.md, the helper searches for the spend_tier key. If the key is absent, the system defaults to standard.

In batch/batch-runner.sh (lines 351–409), the read_spend_tier function extracts this value once per run and exports it for downstream use. This ensures consistent model selection across an entire batch job, preventing mixed-tier evaluations within a single execution context.

Validation and Fallback Logic

The system enforces a strict allowlist of tier values. As implemented in batch/batch-runner.sh (line 385), only three strings are accepted:

  • economy
  • standard
  • premium

If the configuration contains an invalid value, the runner emits a warning and falls back to standard. This validation prevents provider errors from typos or unsupported tier names.

Mapping Tiers to Provider Models

Once validated, the tier string passes through the spend_tier_to_model helper function defined in batch/batch-runner.sh (lines 392–408). This function maps abstract budget tiers to concrete model identifiers:

spend_tier Resolved Model
economy claude-haiku-4-5
standard claude-sonnet-5
premium claude-opus-5

This mapping provides a provider-agnostic interface; the user thinks in terms of cost ("economy"), while the system manages the specific Claude model name required by the API.

Applying Models to Evaluation Scripts

The resolved model identifier becomes the --model argument passed to evaluation scripts (e.g., node evaluate.mjs --model $RESOLVED_MODEL). However, explicit CLI flags take precedence over tier-derived values. As verified in test-all.mjs (lines 12948–13037), if you provide --model claude-opus-5 on the command line while your profile specifies economy, the CLI flag wins.

Batch-Specific Pre-Screening

In batch mode, the spend tier gates an additional optimization step. As noted in test-all.mjs (line 12948), the system runs a cheap pre-screen using the tier-appropriate model to discard low-quality offers before spending credits on full evaluations. This ensures high-volume runs remain cost-effective even when processing thousands of job descriptions.

Configuration and Usage Examples

Set your preferred tier in the profile configuration:


# config/profile.yml

spend_tier: economy   # Uses claude-haiku-4-5 for high-volume, low-cost scanning

# spend_tier: standard  # Default: claude-sonnet-5 for balanced performance

# spend_tier: premium   # Uses claude-opus-5 for maximum evaluation depth

Run a standard evaluation—the tier determines the model automatically:

career-ops evaluate --job ./jds/example-job.md

# Verbose output confirms: Model: claude-haiku-4-5 (spend_tier=economy)

Override the tier for a single evaluation using the explicit model flag:

career-ops evaluate --job ./jds/example-job.md --model claude-opus-5

# Output shows: Model: claude-opus-5 (spend_tier=economy)  # CLI flag takes precedence

Execute a batch run where the runner reads the tier once and applies it to every job:

career-ops batch run ./batch/jobs/

# Internally executes: RESOLVED_MODEL=$(spend_tier_to_model $(read_spend_tier))

Summary

  • The spend tier is defined in config/profile.yml and defaults to standard if omitted.
  • Valid tiers are economy, standard, and premium, mapping to claude-haiku-4-5, claude-sonnet-5, and claude-opus-5 respectively.
  • The batch/batch-runner.sh script handles validation, mapping, and application of the model identifier via the spend_tier_to_model helper.
  • Explicit --model CLI arguments override the tier-derived model, as confirmed by the test suite in test-all.mjs.
  • Batch mode uses the tier to gate a pre-screen step that filters low-quality offers before incurring full evaluation costs.

Frequently Asked Questions

What happens if I don't define a spend_tier in my profile?

If the spend_tier key is missing from config/profile.yml, the system defaults to standard, which resolves to the claude-sonnet-5 model. This fallback logic is documented in modes/_shared.md and implemented in batch/batch-runner.sh.

Can I use a different model for a single evaluation without changing my profile?

Yes. You can override the tier-derived model by passing the --model flag directly to the CLI command (e.g., --model claude-opus-5). This explicit flag takes precedence over the spend_tier configuration for that specific execution.

How do the three spend tiers differ in practice?

The economy tier uses claude-haiku-4-5 for fast, low-cost scanning suitable for high-volume batches. The standard tier uses claude-sonnet-5 for balanced speed and reasoning quality. The premium tier uses claude-opus-5 for maximum capability when evaluating complex compensation packages or critical offers.

Does the spend tier affect batch processing costs beyond the model choice?

Yes. In batch mode, the tier also controls a pre-screening step that evaluates offers with a cheaper model pass before committing to full evaluations. This additional gate, referenced in test-all.mjs, prevents wasting premium model credits on obviously low-quality job descriptions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →