All insights

Inference economics

What Should a Request Trace Contain When One Logical Request Fans Out to Multiple Model Calls?

A multi-model request should use one shared distributed trace with an end-to-end root span, a separate child span for each logical model call, nested spans for retries or fallback attempts, and a visible fan-in span for response selection or aggregation. It should preserve timing, routing, usage, outcome, and correlation data across every branch.

A multi-model request should use one shared distributed trace with an end-to-end root span, a separate child span for each logical model call, nested spans for retries or fallback attempts, and a visible fan-in span for response selection or aggregation. It should preserve timing, routing, usage, outcome, and correlation data across every branch.

The Recommended Shape: One Trace, Separate Branch Spans, and a Visible Fan-In

The purpose of the trace is to reconstruct the logical request as the user or calling application experienced it. Operators should be able to determine which branches ran, why they ran, whether they overlapped, what each consumed, which failures occurred, and how the completed branches affected the final response.

This requires more than putting a shared request ID into several log lines. A distributed trace represents the request as related operations on a timeline. Logs can provide detailed event records, while metrics summarize behavior across many requests. Shared identifiers can correlate these signals, but logs, metrics, and traces are not interchangeable.

Use a root or orchestration span for the end-to-end request

Start with one root span representing the complete logical operation. Depending on the architecture, this might be an API request, agent turn, retrieval-and-generation workflow, batch-enrichment item, or other business operation.

The root or orchestration span should establish the identity and timing of the request. Recommended data includes:

  • Trace ID and root span ID
  • Stable request or operation ID
  • Operation name and request type
  • Start timestamp, end timestamp, and wall-clock duration
  • Entry service, environment, and relevant deployment identity
  • Overall status and final outcome
  • Cancellation or deadline information
  • The final response path, where it can be recorded without exposing sensitive content

The root should cover the full period from accepted request to completed response, including orchestration, queueing, model work, retries, and fan-in. If an upstream trace already exists, the orchestration operation may instead appear as a child within that wider transaction.

A useful orchestration span can also record why fan-out occurred. For example, a workflow might call multiple models to compare candidates, assign different subtasks, hedge against latency, apply a specialist model, or provide a fallback path. Recording a structured routing reason is usually more useful than relying on a human-readable message alone.

Create one child span for each concurrent model invocation

Each logical model call should have its own span. That span represents the branch as a unit of work, not necessarily every attempt made to complete it.

A model-call span can record, when available:

  • Serving system or provider and model identifier or version
  • Operation type, destination, endpoint class, or deployment target
  • Branch role, such as primary generation, critique, classification, ranking, or fallback
  • Routing decision and a machine-readable reason code
  • Timeout, deadline, and cancellation status
  • Relevant generation settings, recorded with sensitive values excluded where necessary
  • Start time, duration, and status
  • Whether the branch result contributed to the final response

Separate spans preserve concurrency. If three calls begin together, the trace timeline should show three overlapping branches rather than one opaque model-processing block. This makes slow branches, partial failures, early cancellation, and unnecessary work visible.

Avoid assuming that all branches use the same model, provider, parameters, destination, or execution path. The reason to trace each branch independently is precisely that multi-model orchestration can make different decisions for each one.

Distinguish logical calls from attempts, retries, fallbacks, and hedges

A logical model call answers the question, “What work did the orchestrator want this branch to perform?” An attempt answers, “What execution was made to complete that work?” Mixing the two makes retry rates, latency, and cost difficult to interpret.

A practical pattern is to place attempt spans beneath the logical model-call span. Each attempt can capture:

  • Attempt number and attempt type
  • Selected model and serving destination
  • Start time, duration, and timeout
  • Success, error, or cancellation status
  • Error category without unnecessary sensitive payloads
  • Retry or fallback trigger
  • Token usage and cost inputs when available

A fallback to another model can remain inside the original logical branch if it is trying to fulfill the same role. If the fallback performs a materially different task, representing it as a separate logical model-call branch may be clearer. The important requirement is that the relationship be explicit.

Hedged requests require similar care. If two attempts race to satisfy one logical model call, record both attempts, identify the winning result, and mark whether the other was cancelled or completed without contributing. Otherwise, an apparently successful request can conceal duplicated consumption.

Represent response selection, ranking, or merging as an aggregation span

Fan-out is only half of the workflow. The trace should also show fan-in: the step that waits for, selects, ranks, validates, merges, or otherwise processes branch results.

An aggregation span can capture:

  • The branches expected and the branches actually received
  • The completion rule, such as wait-for-all, first-success, quorum, or deadline
  • Branches excluded because of failure, timeout, policy, or low rank
  • The selected or merged result references
  • Aggregation duration and final status
  • Which model responses contributed to the user-visible result

This span separates model execution time from post-processing delay. For example, all model calls may have finished promptly while ranking, validation, or response assembly becomes the critical path. Without a distinct aggregation span, that delay may be incorrectly attributed to inference.

Propagate context across every execution boundary

Trace context should follow the request through gateways, orchestrators, routing services, queues, workers, model-serving components, and aggregation services wherever instrumentation permits. Losing context at a queue or worker boundary creates disconnected traces and prevents end-to-end reconstruction.

Direct synchronous work often fits a parent-child relationship. Asynchronous work can be more complicated. A queued job may outlive the producing span, be consumed by a different worker, or be associated with several upstream operations. In those cases, messaging context or span links may represent causality more accurately than forcing every operation into a strict parent-child tree.

Whatever relationship model is chosen, preserve enough correlation data to answer:

  • Which logical request caused this work?
  • Which branch or attempt does it belong to?
  • Which message, worker, and service handled it?
  • Did it complete before or after the caller’s deadline?
  • Did its result affect the final response?

Use a field model that separates identity, execution, usage, and outcome

The following matrix is design guidance rather than a universally mandatory schema. Exact semantic-convention names can change over time, so teams using OpenTelemetry or another standard should verify the current specification before fixing attribute names in instrumentation contracts.

ScopeRecommended trace dataOperational question answered
Trace-wide identityTrace ID, operation ID, request type, environmentWhich end-to-end request is this?
OrchestrationFan-out reason, workflow stage, deadline, routing policy referenceWhy were multiple branches created?
Logical model callBranch role, model identity, destination, timeout, generation contextWhat was this branch intended to do?
Individual attemptAttempt number, retry or fallback trigger, timing, status, error typeWhat executions were required to complete the branch?
AggregationCompletion rule, accepted and rejected branches, contribution statusHow was the final response assembled?
Usage and costInput, output, and total tokens; cost source and currency when availableWhat did each branch consume?
Serving-layer eventsCache, queue, batch, scheduling, routing, or quantization context when observableWhat serving decisions affected execution?

Usage data should remain attached to the branch or attempt that generated it. Record input tokens, output tokens, and total tokens when the serving system makes them available. If cost is calculated internally, label it as estimated and preserve the price basis or rate-card version used. Keep that separate from provider-reported cost so finance and engineering teams do not compare unlike figures.

Serving-layer events can add important context when they are actually observable. Examples include a cache lookup and hit or miss, queue admission, batch assignment, scheduling decision, selected quantization context, or routing result. These fields should explain execution rather than become an unbounded dump of internal state.

Measure latency using the timeline and critical path

Parallel span durations should not be summed to calculate end-to-end latency. If several model calls overlap, adding their durations measures aggregate model work, not elapsed time experienced by the caller.

Instead, distinguish the components that can affect wall-clock completion:

  • Queue and scheduling delay before execution
  • Network or gateway time
  • Model execution time
  • Retry or fallback delay
  • Aggregation and post-processing time
  • Idle time caused by dependencies or completion rules

The root span provides end-to-end elapsed time. The trace timeline reveals overlap, while the critical path identifies the chain of operations that determined completion. Aggregate model time can still be useful for capacity and cost analysis, but it must be labeled differently from request latency.

Example Trace Tree for Parallel Calls, Retries, and Aggregation

The following fictional example illustrates the relationships. It is an architecture pattern, not a Token Forge Cloud product trace or user-interface representation.

A compact trace-tree example

request: generate_supported_answer
└── orchestration: plan_and_dispatch
    ├── logical_model_call: primary_generation        [parallel]
    │   ├── attempt: model_A / first_attempt           [timeout]
    │   └── attempt: model_A / retry                   [success, selected]
    ├── logical_model_call: specialist_review         [parallel]
    │   └── attempt: model_B / first_attempt           [success, contributed]
    ├── logical_model_call: backup_generation         [parallel hedge]
    │   └── attempt: model_C / first_attempt           [cancelled, not used]
    └── aggregation: rank_validate_and_merge
        ├── input: primary_generation retry
        ├── input: specialist_review
        └── result: final response

The logical branch remains stable even when its first attempt fails. The retry is visible as additional execution rather than being hidden inside a single duration. The hedged backup also remains visible, including the fact that it did not contribute to the final result.

In a real distributed system, some operations may appear as linked spans rather than direct children, particularly when queues or detached workers are involved. The visual hierarchy matters less than preserving causality and correlation accurately.

What the timeline reveals that a flat log cannot

A flat sequence of log messages may show that several calls occurred, but it does not inherently show their overlap, ancestry, or causal role. A trace timeline can reveal that:

  • A specialist branch finished first but could not complete the response alone.
  • The primary branch timed out and succeeded only after a retry.
  • A backup branch consumed resources but was cancelled before aggregation.
  • Aggregation waited on a branch that ultimately did not contribute.
  • Queueing, rather than model execution, dominated one branch’s elapsed time.

Logs remain valuable for detailed diagnostics, and metrics remain valuable for fleet-level trends. Correlating them with trace and span IDs allows an operator to move from an unusual metric, to an affected trace, to the relevant event records.

Record branch outcomes explicitly

Every branch should end with a meaningful outcome, including branches that never provide a response. Useful states include success, error, timeout, cancellation, retry, fallback, and abandonment after the overall deadline.

Also record contribution separately from execution success. A model call can succeed technically but still be rejected during ranking, superseded by a faster hedge, excluded by policy, or completed after the final response was sent. This distinction supports more accurate reliability and cost analysis.

Error information should be structured enough to group recurring problems. Categories such as timeout, rate limit, transport failure, invalid response, capacity rejection, and orchestration cancellation are generally more actionable than raw exception text alone. Detailed diagnostics can remain in linked logs with suitable access and retention controls.

Protect sensitive content by default

A useful model trace does not require unrestricted capture of prompts and outputs. Raw content can contain credentials, personal data, customer records, source code, or other proprietary information. Default instrumentation should favor operational metadata over full payload collection.

Practical controls include:

  • Redacting or excluding sensitive fields before telemetry export
  • Hashing stable values when correlation is needed without retaining content
  • Recording prompt template or policy identifiers instead of prompt text
  • Applying access controls and retention limits to trace data
  • Using controlled opt-in capture for narrowly defined debugging cases

If content capture is enabled, define who can access it, why it is needed, how long it is retained, and how deletion is handled. Do not assume that private deployment alone establishes the appropriate telemetry architecture or data-handling controls.

Choose sampling based on diagnostic value

Capturing every trace indefinitely may create unnecessary storage, privacy, and operating costs. Sampling should reflect workload volume, risk, and diagnostic needs rather than one universal percentage or threshold.

Teams may prioritize retention for failed, slow, retried, fallback-heavy, anomalous, or potentially high-cost requests. Tail-based decisions can be useful because these properties are often known only after a request completes. However, the sampling system must preserve enough connected spans to reconstruct the request; retaining only an isolated failed branch can remove the context needed to understand it.

Sampling policy should also account for workload shape. Latency-sensitive chat, batch enrichment, and agentic workflows have different execution patterns and may require different definitions of unusual behavior.

Connect trace design to serving-layer decisions

Good trace design helps teams evaluate model selection, routing, reliability, and inference economics because it makes the reason and impact of each serving decision inspectable. When observable, cache behavior, batching, queueing, model routing, quantization context, and GPU scheduling can be correlated with branch outcomes instead of evaluated only through fleet-wide averages.

Token Forge Cloud Private LLM Inference supports private deployment and serving-layer optimization across caching, model routing, batching, quantization, and GPU scheduling. Token Forge Cloud also provides Managed Model APIs for teams validating model demand before moving toward private serving capacity. This trace pattern can help teams define the telemetry data they need across either deployment approach. Implementation details depend on the architecture and telemetry stack in use.

Implementation checklist

Before considering a fan-out trace complete, verify that operators can determine:

  • What ran: Every logical model branch and each underlying attempt is identifiable.
  • Why it ran: Routing, fallback, retry, and hedging decisions have structured reasons.
  • Where it ran: The serving system, model identity, destination, service, and worker are distinguishable when available.
  • How long it took: End-to-end, queue, execution, retry, network, and aggregation time can be separated where instrumentation supports it.
  • What it consumed: Token usage is attributed to the correct attempt, with estimated and provider-reported costs kept separate.
  • Whether it succeeded: Status, timeout, error, cancellation, and fallback outcomes are recorded for every branch.
  • How it affected the response: The trace identifies which results were selected, merged, rejected, cancelled, or completed too late.
  • How context was preserved: Correlation survives service, queue, worker, gateway, and model-serving boundaries.
  • Whether sensitive data was controlled: Raw prompts, outputs, credentials, personal data, and proprietary content are excluded by default or handled through explicit controls.
  • Whether the timing is interpreted correctly: Wall-clock latency and critical-path behavior are not confused with the sum of overlapping model-call durations.

Contact Token Forge Cloud to discuss API access, private deployment, and LLM inference cost control.

Contact us