Tools and agents
Function tools (Responses API)
{
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a city. Use it for any weather question. Returns a short text summary.",
"strict": true,
"parameters": {
"type": "object",
"properties": {"city": {"type": "string", "description": "City name"}},
"required": ["city"],
"additionalProperties": false
}
}The description decides whether the tool gets used. strict: true guarantees schema-valid
arguments and needs a strict-clean schema. Arguments arrive as a JSON string: parse and
validate them; they are model output.
The loop
- Send
input+tools. - Append every item of
response.outputto your input (reasoning items included). - For each
function_callitem, run the function and append{"type": "function_call_output", "call_id": <its call_id>, "output": "<string>"}. Several calls can arrive in one turn: answer all of them. Report failures as output text; never drop one. - Call again. Stop when no
function_callitem comes back. Always cap the number of turns.
With previous_response_id you may send only the new function_call_output items instead of the
whole history.
tool_choice: "auto", "required", "none", or {"type": "function", "name": "…"} — all
accepted by every probed model for function tools. "any" is not an OpenAI value.
parallel_tool_calls: false limits the model to one call per turn.
Hosted tools (Responses API only, billed per call)
| Tool | Declaration | Notes |
|---|---|---|
| Web search | {"type": "web_search"} |
Answers carry url_citation annotations; show the sources |
| Code interpreter | {"type": "code_interpreter", "container": {"type": "auto"}} |
Rejected by gpt-5-pro, gpt-5.2-pro |
| File search | {"type": "file_search", "vector_store_ids": ["vs_…"]} |
Needs a vector store |
| Image generation | {"type": "image_generation"} |
Costs far more than text |
| Remote MCP | {"type": "mcp", "server_label": "…", "server_url": "https://…"} |
The server's tools become callable; review what it can do |
o3 and o3-pro accept only tool_choice: "auto" when a hosted tool is present.
Agents SDK
A separate package (@openai/agents, openai-agents) that runs the loop for you and records
traces. TypeScript: tool({name, description, parameters: z.object({…}), execute}),
new Agent({name, instructions, model, tools}), await run(agent, input, {maxTurns}) →
result.finalOutput. Python: @function_tool, Agent(...), Runner.run_sync(agent, input, max_turns=…) → result.final_output. It also provides handoffs between agents, guardrails and
sessions; those were not exercised by this skill's tests.
Which architecture
| Approach | You write | Good for |
|---|---|---|
| Single Responses call | A request | Bounded tasks |
| Function-calling loop | The loop and the tools | Full control, custom flows |
| Agents SDK | Tools and agent definitions | Multi-step agents, handoffs, tracing |
| Hosted tools | A tool declaration | Search, code execution, retrieval without infrastructure |
Before building an agent, check: is the task open-ended, worth the cost, within the model's ability, and are errors recoverable? If not, use a single call or a fixed workflow.