Custom function tools in the Responses API use a top-level name field (unlike Chat Completions which nests it under function). The multi-turn tool loop uses function_call output items.
The shape you see in production
A custom function tool is JSON Schema for the parameters plus three fields: type: "function", name, and description. On Responses, all three sit at the top level of each tool object. On Chat Completions, they sit under a nested function wrapper. The schema body is identical — only the wrapping differs.
Treat the description as part of the prompt. The model reads it; vague descriptions ('get the weather') route badly; explicit descriptions with negative examples ('do not call for forecasts beyond 24h') route well. Per-parameter descriptions inside parameters.properties[i].description matter too.