← All courses ← Course home

Lesson 01 of 05

One call is many hops

A LanguageModelSession looks like one call. The work is a chain. If you only time the call, you cannot say which hop failed.

Agent brief (llms.md)

You send a prompt. You wait. A string comes back. That wait is not one step. The app packed context. The model may have called a tool. The model ran. Your code may have checked the answer before you showed it.

Apprespond or stream
Apprespond or stream
InsideSeveral hops

An Edge FDE debugs with a timeline, not a single duration. If TTFT is high, the hop before the first token is the suspect. If the answer is wrong, the hop that built the prompt or skipped a guardrail is the suspect.

import FoundationModels

// Illustrative. Time hops around the session, not only the whole call.
let session = LanguageModelSession()
let packed = packContext(question)
let reply = try await session.respond(to: packed)
let shown = try applyGuardrail(reply)

Apple's Foundation Models instrument in Xcode 27 already draws sessions, requests, inferences, instructions, and tool calls. Your own hops still need names, because Instruments does not know your context packer or your product guardrail.

Pair this course with Stream tokens and measure speed for the clocks, and with Test AI behavior before you ship when the trace shows a wrong path you want to fail in CI.

Rule. Never file a bug as "the model is slow" until you can name the hop.

Next, give the hops stable names.

Key concepts

  • The app packs context, the model may call tools, the model runs, then a guardrail checks.
  • A single duration hides which hop failed.
  • High TTFT often lives in the hop before the first token.
  • Instruments does not know your context packer or product guardrail.

Takeaways

  • Debug with a timeline, not one opaque duration.
  • Never file 'the model is slow' until you can name the hop.
  • Pair this with streaming metrics for clocks and the eval harness for wrong paths.