Cheat sheets

Tool Calling and Structured Outputs

Declare tools, read calls, return results, run calls in parallel, stream arguments, and force JSON that validates.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

Function call tasks#

TaskCode
Declare a tool, OpenAI{"type": "function", "function": {...}}
Declare a tool, Anthropic{"name": ..., "input_schema": {...}}
Let the model decidetool_choice="auto"
Require a tool calltool_choice="required"
Force one tooltool_choice={"type":"function", ...}
Read OpenAI callsmessage.tool_calls
Find an Anthropic callb.type == "tool_use"
Return an Anthropic result{"type": "tool_result", "tool_use_id": ...}

From Lesson 11.09

Structured output tasks#

TaskCode
Valid JSON, no schema{ type: "json_object" }
JSON that fits a schema{type: "json_schema", strict: true}
Parse into a Pydantic modelresponse_format=Product
Read the typed resultmessage.parsed
Retry on validation errorsinstructor.from_openai(OpenAI())

From Lesson 11.03, Lesson 13.04

The tool loop#

messagetoolstool callvalid argsresultobserveUsermessageHostregistry, loop boundModeltext, call or refuseTool resulttool message, same idExecutoryour code runs itValidatorJSON Schema 2020-12messagetoolstool callvalid argsresultobserveUsermessageHostregistry, loop boundModeltext, call or refuseTool resulttool message, sameidExecutoryour code runs itValidatorJSON Schema 2020-12

From Lesson 13.01, Lesson 11.09

One tool call#

1Hostdeclares name, description and input schema.2Modelanswers, calls tools, or refuses.3Modeleach call has id, name, arguments.4Hostvalidates the arguments against the schema.5Executorruns the code, returns a serializable result.6Hostappends a tool message with the same id.7Hostrepeats until no calls or MAX_TURNS.

From Lesson 13.01, 13.01 code/main.py, Lesson 11.09

OpenAI round trip#

response = client.chat.completions.create(
model="gpt-4o", messages=messages,
tools=tools, tool_choice="auto",model picks tool or text
)
tool_call = response.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments)arguments are a string
result = get_weather(**args)your code executes
messages += [
response.choices[0].message,keep the assistant turn
{"role": "tool", "tool_call_id": tool_call.id,same id as the call
"content": json.dumps(result)},
]
final = client.chat.completions.create(model="gpt-4o", messages=messages)

From Lesson 11.09

Shapes by provider#

Schema field
parameters, input_schema, Gemini parameters.
Call
tool_calls[], a tool_use block, a functionCall part.
Arguments
OpenAI sends a string. The others send an object.
Result link
tool_call_id, tool_use_id, functionResponse id.
Forbid tools
tool_choice: "none", {type: "none"}, mode: "NONE".
Strict
strict: true, always on, responseSchema.

From Lesson 13.02

Parallel and streaming calls#

Enable
parallel_tool_calls: true is the OpenAI default.
Serial
Turn it off when calls depend on each other.
Correlate
Each result carries its call id. Order is free.
OpenAI stream
Join chunks per index until finish_reason = "tool_calls".
Anthropic stream
input_json_delta chunks until content_block_stop.
Parse late
Partial JSON raises. Parse at the end signal.
Latency
400, 600, 800 ms: 1800 ms serial, 800 ms parallel.

From Lesson 13.03, 13.03 code/main.py

Schema design rules#

Name
snake_case, verb then noun: get_weather. No arguments in the name.
Description
"Use when {condition}. Do not use for {close-but-wrong-cases}."
Enums
Put every closed set in an enum.
Atomic tools
Split a tool when action has more than three values.
Strict mode
Every property in required, additionalProperties: false, no $ref.

From Lesson 13.05, Lesson 13.04

Validate, then repair or refuse#

def process_model_output(raw: str, schema: dict) -> ParsedResult:
if raw.startswith("__REFUSAL__"):model declined: no retry
return ParsedResult("refusal", raw.removeprefix("__REFUSAL__").strip(), [])
try:
parsed = json.loads(raw)
except json.JSONDecodeError as e:failure 1: not JSON
return ParsedResult("parse_error", None, [ValidationError("$", str(e))])
errs = validate(schema, parsed)list of path and message
if errs:
return ParsedResult("violation", parsed, errs)inject errs, retry
return ParsedResult("ok", parsed, [])

From 13.04 code/main.py, Lesson 13.04

Limits and defaults#

SettingDefaultNote
OpenAI tools per request128Hard limit
Anthropic tools per request64Hard limit
OpenAI schema depth5Strict mode
OpenAI argument string8192 bytesMaximum size
Description length1024 charactersLonger text is truncated
MAX_TURNS5Lesson loop bound
Repair retries3xMore means a bad schema
timeout_ms30_000Per tool record

From Lesson 13.02, Lesson 13.05, 13.01 code/main.py, Lesson 13.04, 19.21 code/main.py

Troubleshooting#

SymptomCauseFix
json.loads raises mid-streamArguments are partial JSONParse after the end-of-call signal
400 at request time, strict modeStrict schema rule brokenAll in required, no $ref
Wrong tool pickedTwo descriptions overlapAdd a "Do not use for" line
Value outside the enumPrompt-based outputUse constrained decoding
refusal in the responseInput does not fit the schemaHandle it as a typed outcome
Extra fields in inputAnthropic schema is advisoryValidate on the server
Schema errors retriedErrors are deterministicFix the arguments, no retry
Results on the wrong callMatched by name, not idReturn each result with its id

From Lesson 13.03, Lesson 13.04, Lesson 13.05, Lesson 13.02, Lesson 11.03, Lesson 19.23

Questions and answers#

Structured output or call?
Output is final data. A call asks to act.
Why not prompt for JSON?
It fails 5 to 15 percent of the time.
Why a call id?
Parallel results return out of order.
Can a schema catch a wrong value?
No. Type right, value invented.

From Lesson 11.09, Lesson 13.01, Lesson 13.04, Lesson 11.03

Tips#

  • Return errors as results: {"error": true, "code": "CITY_NOT_FOUND"}.
  • Write errors for the model: "'city' is required."
  • Report errors as JSON pointer paths: /user/email.
  • Make key fields required. The model writes null.
  • Expose only the functions the user needs.

From Lesson 11.09, Lesson 13.05, Lesson 11.03, Lesson 19.21