Skip to content

The per-agent model is never persisted, so both cost accounting and the transparency capsule report the default model #173

Description

@lfnothias

Observation

When the orchestrator picks a model per agent, that choice is never written anywhere. workflow_factory.py:322 resolves a single default_model and stores it as WorkflowState.model_id, which is the only model recorded in state_result.json. The SmolAgent memory files do not record the per-agent model either.

Everything downstream therefore reads the default. pricing.py:275-282 reads model_id back from state_result.json and prices every agent's tokens against it; the comment there states plainly that "Cost is attributed to a single model … the default every agent falls back to." That assumption was true before per-agent selection existed and is no longer true now that orchestrator_choose_model defaults to True.

Why it matters

Two separate consumers are wrong for the same reason, and it is one missing write:

  • Cost. An agent run on an expensive model is billed at the default model's rate, so the reported cost of a run is wrong in an unbounded direction. This is the metric the cost work has been optimising against.
  • Provenance. Any consumer asking "which model produced this agent's output" gets the default. That includes the ASTRA transparency capsule, whose purpose is to record what actually happened. A capsule that names the wrong model is a reproducibility problem, not only an accounting one.

Pathway

  1. Persist the resolved per-agent model at the point the agent is constructed (smolagent_factory), alongside the existing agent memory — one field per agent, written where save_memories already writes.
  2. Have pricing.py price each agent's tokens against that agent's recorded model, falling back to state_result.json's model_id when the field is absent, so older runs keep working.
  3. Carry the same field into the ASTRA export so the capsule reports the model each agent actually used.

Step 1 is the only change that must land first; steps 2 and 3 are independent readers of it. Keeping the fallback in step 2 means no historical run breaks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions