Card 13 of 38· Domain 2 · Generative AI and agents

Function calling — the round trip and the run states

The four-step dispatch loop, the run state machine and its edge cases, and the thing that is always wrong: the model never executes your function.

Function calling — the round trip and the run states
Open the card in a new tab to read it at full size.

This is the most commonly misunderstood mechanic on the whole platform, and the misunderstanding is always the same one. The model never runs your code. It asks you to.

The round trip, in four steps

This arrives regularly as a drag-and-drop sequence question, so learn it in order.

  1. The model returns a tool call. It requests the function. It executes nothing itself.
  2. Your code executes it. Your dispatcher runs the function locally, on your compute.
  3. You append the output. The result goes back into the conversation.
  4. You call the model again. Now it answers, using the result.

Two calls to the model, with your own code doing the actual work in between. Once that shape is clear, most of the questions in this area answer themselves.

The run state machine

The classic run mechanics, in sequence:

  • A tool is needed, so the run status becomes requires_action.
  • You read the requested calls from submit_tool_outputs.tool_calls.
  • You execute them, then send results back through submit_tool_outputs, keyed by tool_call_id.
  • The run returns to in_progress, and you poll until completed.

The tool_call_id matters when more than one function was requested. It is how each result is matched to the request it answers.

The edge cases they test

  • A single conversation can hit requires_action multiple times. Your dispatcher has to loop, not handle one and stop.
  • Runs expire after 10 minutes. A slow function does not just delay the answer; it can kill the run.
  • The terminal states are completed, failed, cancelled and expired.
  • An agent can request one or many functions in a single turn.

Writing a good tool definition

A definition is three things: a name, a description, and descriptions of each parameter.

The part people under-invest in: the descriptions drive tool selection. The model decides which function to call by reading them. A vague description produces a model that reaches for the wrong tool, and that failure looks like model stupidity when it is actually documentation.

Two further habits worth keeping:

  • Return structured JSON.
  • Surface failures as JSON errors rather than throwing exceptions. The model can read an error object and adapt. It cannot read a stack trace that never reaches it.

The trap

Any answer that says the model executed the function is wrong. Always. The model only ever returns a request.

There is a real consequence behind the exam point. In-process function calling runs on your local or client compute — so a long-running job blocks the thing that called it and races the ten-minute run expiry. That is precisely why long-running work belongs in Azure Functions instead, dispatched rather than executed inline.