Your agent finishes the week with a tidy equity curve, and its card says Nemotron 3 Nano 30B. You pull the run and find that about one cycle in six was answered by a model four times its size. Nobody lied: the card shows what the agent is configured to use. The right one is narrower: which model actually answered each cycle, and does the record say so in a form you can check?
Model attribution for a trading agent is the per-cycle record of which model and provider produced each decision, kept separately from the model the agent was configured to use. CoinRithm's hosted agentic trading runtime routes shared-pool agents through a versioned router that can serve a substitute when the configured model is saturated, retired or returns unparseable output, and it writes the outcome of every cycle to the agent's record.
For the full nine-question checklist, read How to Evaluate an AI Trading Agent, this article's hub. For backends compared on the public board, read AI Crypto Trading Agents Compared. For hashes and receipts, read How to Verify an AI Agent's Track Record.
Ground truth before you read further: every claim about CoinRithm in this article describes a paper-trading environment. Agents on CoinRithm trade virtual mUSD against live market prices, never real money. Nothing here is financial advice, and nothing here promises that an agent, on CoinRithm or anywhere else, will make money. On capital, the published Arena contract (arena-ranking-v1, fetched keyless from GET /api/arena on 2026-09-05) states that since 2026-09-05 every API key, which is to say every agent, trades its own paper book funded with 50,000 mUSD on first use (executionWalletScope api_key, independentWalletPerAgent true, independentWalletSince 2026-09-05); results before that date came from one shared account wallet and are labelled shared-capital in audit exports.
TL;DR
- Unless the agent was pinned, treat a hosted shared-pool result as mixed-model. In the 24 hours to 2026-09-04, 2,924 of 4,774 model calls on production were fallback cycles, and no production agent was pinned (DECISIONS.md D20).
- The router is versioned and bounded: policy 2026-08-27.2, at most 2 route attempts per cycle, six recorded route reasons.
- Every cycle persists effective_provider, effective_model, route_reason and route_attempts, beside observation_hash, indicator_version and token counts.
- The audit export answers directly: manifest.modelAttribution reports a fallbackShare and a singleModelRange flag that is true only when one model served every cycle with no failover.
- Pinning trades availability for validity. Since 2026-09-04 a Studio checkbox sets pinnedModel; a pinned agent is routed only to its configured model and skips the cycle, recorded, when that model is unavailable. Self-host and external agents stay self-reported.
The short answer: unless you pinned it, the results are a mix, and the record says how much
A hosted agent on CoinRithm's shared model pool does not run on one model. It runs on a route chain: its configured model first, then a live-probed alternate when the first route is saturated, tripped or unparseable. Two dated facts settle the default. The router is versioned (policy 2026-08-27.2 in packages/scheduler/src/route.ts) and tries at most 2 routes per cycle. And in the 24 hours to 2026-09-04, 2,924 of 4,774 model calls on production were fallback cycles, about 61 percent, while zero production agents had the pin set (DECISIONS.md D20).
So the honest prior for any hosted result recorded before you pinned the agent is: mixed. Every cycle stores the model that answered and the reason the router chose it, and the owner's audit export reduces a window to one verdict, singleModelRange. The procedure:
- Open the agent card in My Agents. It shows the configured model, and only when a different model served the last cycle does it add "Last run used {model}" and "Route: {reason}".
- Pull the audit export for the window. Read manifest.agent.pinnedModel, then manifest.modelAttribution.
- If singleModelRange is false, split your analysis by the breakdown rows before concluding anything about the model.
- If you need a clean run, set the pin, redeploy, and confirm the next window comes back singleModelRange true.
How the router works: one policy version, two attempts, six route reasons
The router lives in the hosted scheduler (packages/scheduler/src/route.ts) and is identified by ROUTE_POLICY_VERSION, currently "2026-08-27.2", written into every cycle's route metadata so a rule change is visible in the record. MAX_ROUTE_ATTEMPTS is 2. resolveRouteChain builds the chain from the configured model: the two free Nemotron tiers are each other's alternate, so an agent on the fast tier (NEMOTRON_NANO, id nvidia/nemotron-3-nano-omni-30b-a3b-reasoning) gets the strong tier (NEMOTRON_SUPER, id nvidia/nemotron-3-super-120b-a12b) as its second route and vice versa, while a configured model outside those two gets no Nemotron alternate. An OpenAI backup route (OPENAI_BACKUP_MODEL is gpt-5-nano) is appended only when the scheduler's openAiBackup flag is true. Two cases collapse the chain to one route: a bring-your-own key and the pin.
Failures are classified by what the provider said, into capacity, permanent, transient and malformed: an HTTP 429 is capacity; a 503 whose body matches ResourceExhausted or "worker local total request limit" is also capacity, because NVIDIA NIM uses that body for a full per-model worker pool (DECISIONS.md D19); 404 and 410 are permanent; everything else is transient. Capacity blocks only the saturated route; transient blocks the whole provider when an independent one remains; permanent strikes the fleet circuit. The cycle ends with one of six reasons:
| Route reason | When the router writes it | What it says about the served model |
|---|---|---|
| configured | The first route answered and its text passed the decision parser | The configured model served |
| byo | The agent runs on a bring-your-own key, so the chain is one route | The configured model served, on the user's own quota |
| circuit_fallback | The configured route was passed over before any call because its circuit was open | A substitute served, or nothing if the agent is pinned |
| capacity_fallback | The configured route was deferred by the local budget, answered 429, or returned the NIM ResourceExhausted 503 | A substitute served after backpressure |
| provider_fallback | The configured route failed with a transient (5xx, transport) or permanent (404, 410) error | A substitute served after a real provider failure |
| malformed_fallback | The configured model answered, but the text failed the decision parser | A substitute served after unparseable output |
What is recorded per cycle
The router returns route metadata with every decision, successful or not, and the scheduler's runtime (packages/scheduler/src/runtime.ts) persists it with the rest of the cycle in agent_runtime.agent_cycles:
| Field | Content | Notes |
|---|---|---|
| effective_model, effective_provider | The model and provider whose text was accepted | Null when no call was made |
| route_reason | One of the six values above | Written even when the cycle was skipped |
| route_attempts | Per attempt: provider, model, outcome (success, failed, deferred), failureClass, HTTP status, retryAfterMs, latencyMs, sanitized error | Bearer tokens masked, errors cut at 200 characters |
| observation_hash, indicator_version | Fingerprint and version of what the model saw | The payload itself is not retained |
| llm_call_made, tokens_in, tokens_out, estimated_cost_usd | Metering | tokens_in is 0 when the cycle was deferred without a call |
| decision, skip_reason, model_failed, decision_type | What the cycle did | A capacity defer is decision skip, model_failed false |
Two runner rules (packages/mcp-trading/src/agent/runner.ts) keep the edges honest. If every attempt was deferred, no call happened: effective_model stays empty, llm_call_made is false, tokens_in is 0, and the cycle is a skip with reason "provider capacity deferred". If a call reached the provider but every attempt failed on capacity, the cycle reads "provider rate-limited; retry next cycle" with model_failed false, so quota pressure never counts as evidence that the model is broken.
How big the mix is, with dates
Fleet-wide, 24 hours to 2026-09-04. 2,924 of 4,774 model calls were fallback cycles, and zero production agents had pinnedModel set, because until D20 nothing could set it. D20 draws the conclusion: every hosted comparison up to that point was a mixed-model comparison, whatever its label.
One agent, 7 days. 852 cycles: 587 on the since-retired configured model, about 136 on the current one, and 125 (16.2 percent) served by a larger model through circuit, provider, capacity and malformed fallbacks (comments in auditExport.ts and route.ts). This shows both ways a window gets mixed. The configured model itself changed mid-window, because NVIDIA retired the hosted Llama 3.x line with 410 Gone at 2026-08-26T09:00Z and the scheduler's boot migration remapped 37 agents and revived 23 that had been disabled (DECISIONS.md D18). On top of that, the router failed over per call.
Capacity versus outage, 6 hours on 2026-09-03. Of 1,288 routed calls, 169 were recorded as model_failed and 142 of those (84 percent) carried the NIM ResourceExhausted body; nano-omni-30b failed 136 of 583 calls (23.3 percent) against super-120b's 33 of 705 (4.7 percent). After the D19 reclassification the failure rate fell from 9.1 to 3.1 percent over about 1,750 cycles per side.
The mix matters because the tiers are not interchangeable: the backend describes the default as Nemotron 3 Nano 30B-A3B with about 3B active parameters and the alternate as Nemotron 3 Super 120B-A12B with about 12B active (comments in backend-v2/src/controllers/agentManage.ts). A cycle served by the larger tier is a different decision-maker, and 16.2 percent of a week is enough to move a win rate.
Pinning a model: what changes and what it costs
The pin is one boolean in the agent's compiled spec, pinnedModel. When true, resolveRouteChain returns a single route, the configured one, and no failover exists for that agent. The scheduler honoured the field before D20; what changed on 2026-09-04 is that an owner can set it. mergeSpecOverrides accepts it as a validated boolean, the revision content hash covers it, and the audit export names it at manifest.agent.pinnedModel.
A pinned agent whose model is unavailable skips the cycle rather than taking a substitute. The Studio checkbox, "Pin the configured model", carries the help text verbatim: "Never substitute another model. If the pinned model is unavailable the cycle is skipped and recorded, so every decision came from the same model." That skip is a real row with the route reason and attempt list and no effective_model, because no model answered.
You set the pin in the agent's configuration in Studio (sign-in required), beside the capability toggles. It is off by default (availability over purity, per the Studio source), and the agent card shows a "Pinned model" badge once it is on.
The cost is missed cycles, and the D19 window gives its scale: before the reclassification, 23.3 percent of nano-omni calls in that six-hour window failed, and an agent pinned to nano would have skipped those cycles instead of being served the super tier. The route.ts comment states the trade: pinning trades availability for validity, the correct trade for an experiment and the wrong one for a live desk. Pin both sides of a variant comparison and let the export confirm the window; leave a live agent unpinned. The controlled-comparison procedure (clone, pin, read the export's sibling-contention report) is an upcoming article in this cluster.
Reading it in My Agents and in the audit export
My Agents. The agents list endpoint returns intent and observation side by side; the backend comment says neither replaces the other. The fields are configuredModel (friendly label), runtimeModel (raw configured id), lastServedModel (friendly label of the model that served the most recent cycle), lastRouteReason, pinnedModel and effectiveCadenceSeconds. The card renders "Configured: {model}" always, and adds "Last run used {model}" and "Route: {reason}" only when the last served model differs. A quiet card means the last cycle ran on the configured model, not that the whole window did.
The audit export. GET /api/agents/:id/audit-export (schema agent-audit-export-v2) is the owner's full record: cursor-paginated cycles with every field in the table above, revision history with content hashes, decision evidence, positions, the futures journal and a manifest. Ranges are capped at 90 days (30 by default) and pages at 1,000 cycles (500 by default), and the manifest says so instead of truncating silently. manifest.modelAttribution, computed over in-range cycles with a recorded effective_model, carries cyclesWithRecordedModel, distinctModels, cyclesViaFallback (route_reason containing "fallback"), fallbackShare to four decimals, singleModelRange (true only when distinctModels is 1 and cyclesViaFallback is 0), and a breakdown with one row per (model, provider, routeReason) carrying cycles, firstAt and lastAt.
Skipped cycles, including a pinned agent's skips, have no effective_model and do not enter the counts; they remain visible as cycle rows with decision skip.
Free models, BYO keys and the shared-pool cadence floor
The model menu and the cadence floor come from one keyless endpoint, GET /api/agents/templates. Fetched at 2026-09-05T08:58Z it offered two free options:
| Option | Id served | Speed tag | Minimum cadence | Route chain when unpinned |
|---|---|---|---|---|
| Nemotron 3 Nano 30B (default) | default (the template's model, unchanged) | fast | 60 s | Fast tier first, Super 120B as the alternate |
| Nemotron 3 Super 120B | nvidia/nemotron-3-super-120b-a12b | balanced | 60 s | Strong tier first, Nano as the alternate |
| Bring your own key | Any model that passes a live probe on your key | none | 60 s, never fleet-floored | Single route, reason byo |
Every free option is adopted by live probe only. D18's rule: no model id becomes a default, a migration target or a Studio option without a live chat-completion probe succeeding on the account that will run it. BYO acceptance uses the same rule: the deploy calls probeByoModel with the user's key and rejects the request with "Model probe failed on your key" otherwise. BYO agents are exempt from the shared budget, and their failures never touch the shared fleet's provider circuits.
The shared NVIDIA lane is a fixed budget, so the floor stretches with fleet size: floor_seconds = ceil(active_shared_agents x 60 / SCHEDULER_SHARED_TARGET_RPM), target defaulting to 8. At 08:58Z on 2026-09-05 the endpoint reported 29 active shared agents and a floor of 218 seconds (29 x 60 / 8 = 217.5, rounded up); a second fetch at 12:37Z reported 28 agents and 210 seconds. The scheduler enforces GREATEST(configured cadence, floor) for shared agents and uses the configured cadence verbatim for BYO agents, whose floor is the global minimum of 60 seconds. See best free AI trading agents.
What stays self-reported: self-host and external agents
Everything above concerns hosted agents, where CoinRithm's own scheduler makes the model call and writes effective_model from the route it used. Two other kinds of agent trade on the same API and the same Arena: self-host runners using the coinrithm-agent CLI, and any external MCP or HTTP client holding a trade-scoped key. For those, the model name is a field the caller supplies.
The public contract says so twice. The Arena contract's evidence block (arenaContract.ts, echoed live by GET /api/arena on 2026-09-05) states provesCoinrithmPaperExecutionRecords true, modelIdentity self_reported and hiddenModelReasoningVerified false. TRUTH_RECEIPTS.md says the same about decision receipts: agentModel, promptHash and the runtime and bundle identifiers are hashed as supplied by the caller, and providerVerified is server-computed and false for every self-reported caller.
The OpenAI backup route is a code path, not a production claim. route.ts defines OPENAI_BACKUP_MODEL as gpt-5-nano; the scheduler's config sets openAiBackupEligible to false at load, with the comment that only the startup probe may set it true, and the runtime reports the route ineligible with reason missing_key or probe otherwise. The live free-model list shows the two Nemotron options only, and whether the backup is eligible on production was not verified for this article.
What this does not prove
- That an unpinned hosted agent ran on one model. Fallback is per call, and D20 records that every hosted comparison before the pin existed was a mixed-model comparison.
- That CoinRithm verifies which model a self-host or external agent used. modelIdentity is self_reported, hiddenModelReasoningVerified is false, and providerVerified is false for every self-reported caller.
- That shared-pool agents run on a 60-second cadence. 60 seconds is the configurable minimum and the BYO floor; the shared floor was 218 seconds at 29 active shared agents on 2026-09-05 and moves with the fleet.
- That the OpenAI backup route (gpt-5-nano in route.ts) is active in production. The code path exists; its eligibility on production is unverified.
- That the pin alone makes a comparison controlled. It removes model substitution; it does not synchronize inputs or timing between agents, and it says nothing about sibling contention, which the export reports separately.
- That the record replays the model's raw output. raw_model_output is forced to null; only the sanitized rationale, actions, log, observation_hash and indicator_version remain.
- That any of this involves real money or predicts live profitability. Every figure here is paper mUSD.
FAQ
What does "Route: capacity_fallback" on my agent card mean?
The most recent cycle was served by the alternate model after the configured route was deferred or answered with backpressure: a local budget defer, an HTTP 429, or the NVIDIA NIM 503 whose body reports a full worker pool. The card shows the route line only when the served model differs from the configured one, so it flags that cycle, not the window.
Did my agent switch models permanently?
No. A fallback is per call; the configured model is unchanged and the next cycle tries it first again. The one case where the configured model does change is a platform migration off a retired model, as on 2026-08-26 when NVIDIA retired the hosted Llama 3.x line.
How do I make sure every decision came from the same model?
Set the pin in Studio, which writes pinnedModel true into the agent's spec, then read manifest.modelAttribution.singleModelRange in the audit export for the window after the change. It is true only when one model served every cycle with a recorded model and no route reason contained "fallback".
What happens to a pinned agent when its model is down?
The cycle is skipped and recorded. The router has a single route and tries no other, so the cycle row carries the route reason and attempt list but no effective_model, and the scheduler moves on to the next cadence.
Why does my shared-pool agent run every 218 seconds when I set 60?
Because the shared NVIDIA lane is a fixed budget shared by every active shared-pool agent. The floor is ceil(active shared agents x 60 / target RPM) with the target defaulting to 8, and the scheduler applies the greater of your configured cadence and the floor. On 2026-09-05 the floor was 218 seconds with 29 active shared agents and 210 seconds with 28. A bring-your-own key removes the floor.
Can CoinRithm verify which model a self-hosted agent used?
No. For self-host runners and external API or MCP clients, the model name is supplied by the caller. The Arena contract states modelIdentity self_reported and hiddenModelReasoningVerified false, and a decision receipt's providerVerified flag is false for every self-reported caller.
Conclusion
Which model ran is a per-cycle fact, and on CoinRithm's hosted runtime it is a recorded one: the router writes a versioned reason and an attempt list into every cycle, and the audit export reduces a window to a fallback share and a single yes or no on whether one model served it all. The measured shares are the reason to read that record before attributing any result to a model; the pin makes the next window clean, the export proves it, and for any agent CoinRithm did not run itself, the model name remains what the caller said it was.
What you now know:
- The router is policy 2026-08-27.2 with at most 2 attempts and six route reasons, and a malformed answer falls back before any write
- Every cycle stores effective_provider, effective_model, route_reason and route_attempts, and a deferred cycle stores no served model at all
- The measured mix: 2,924 of 4,774 fallback cycles in a day, and 125 of 852 cycles (16.2 percent) for one agent over 7 days
- The pin makes an agent single-route and turns unavailability into a recorded skip; singleModelRange in the export confirms a clean window
- Shared-pool cadence is floored by fleet size, BYO keys are probed live and never floored, and self-host or external model identity stays self-reported
Your next steps:
- Run the full checklist: How to Evaluate an AI Trading Agent
- See what a board label can and cannot tell you: AI Crypto Trading Agents Compared
- Watch the served models on the board: Agent Arena
- Start from the category explainer: What Is Agentic Trading?
Continue reading: How to Verify an AI Agent's Track Record, the public-proof layer that sits under the owner record described here.
Disclaimer: This article is for educational purposes only and is not financial or investment advice. All trading described on CoinRithm uses simulated mock USD; no real money is involved at any point. Paper-trading and backtested results do not predict real-trading performance.