api
Tool calling and structured output API
Direct answertools let a model propose a structured call; the application must still authorize, validate, execute, and return the result. strict constrains shape, not business truth.
Updated · Reviewed
Beginner: the model proposes; the application executes
Tool calling does not grant a model server authority. The request tools describe allowed functions and arguments. When the model returns a call, the application verifies identity, tenant authorization, tool name, and arguments before performing any operation, then returns a result for the next model turn. Structured output constrains a final answer with JSON Schema for extraction, classification, or form generation. Neither feature replaces business rules.
Create a site API key in token management, then open the model marketplace. Confirm that the selected model explicitly lists /v1/responses or /v1/chat/completions; similar model names do not imply the same endpoint:
export BASE_URL="https://api.tu-zi.com"
export API_KEY="your site API key"
export RESPONSES_MODEL_NAME="exact marketplace model ID that supports /v1/responses"
export CHAT_MODEL_NAME="exact marketplace model ID that supports /v1/chat/completions"
BASE_URL has no trailing /v1. The two structured-output examples below target different endpoints and their outer request shapes must not be mixed.
Minimal tool request
tool_response=$(curl -sS "$BASE_URL/v1/responses" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d @- <<JSON
{
"model": "$RESPONSES_MODEL_NAME",
"input": "Get the delivery status for order A123",
"tools": [{
"type": "function",
"name": "get_order_status",
"description": "Read an order visible to the current user",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
"additionalProperties": false
},
"strict": true
}]
}
JSON
)
response_id=$(printf '%s' "$tool_response" | jq -r '.id')
call_id=$(printf '%s' "$tool_response" | jq -r '.output[] | select(.type == "function_call") | .call_id' | head -n 1)
test -n "$response_id" && test "$response_id" != "null"
test -n "$call_id" && test "$call_id" != "null"
A response can contain a function-call item, call ID, and JSON arguments. Accept only registered tools, validate arguments again, and verify that the order belongs to the caller. The example uses jq to extract the response ID and original call_id. After the application performs the lookup, return its result to the same Responses turn:
curl -sS "$BASE_URL/v1/responses" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d @- <<JSON
{
"model": "$RESPONSES_MODEL_NAME",
"previous_response_id": "$response_id",
"input": [{
"type": "function_call_output",
"call_id": "$call_id",
"output": "Order A123 has shipped"
}]
}
JSON
Only the second response can continue from the tool result toward a final answer, and it may request another tool. Repeat validation, execution, and return until a final answer or the step limit. Treat every model-generated identifier, URL, command, and amount as untrusted input.
Structured output: Responses API
Responses API requires the structured-output definition under text.format. This is a complete minimal request:
curl "$BASE_URL/v1/responses" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d @- <<JSON
{
"model": "$RESPONSES_MODEL_NAME",
"input": "Customer says: I paid, but the balance has not arrived. Turn this into a ticket.",
"text": {
"format": {
"type": "json_schema",
"name": "ticket",
"strict": true,
"schema": {
"type": "object",
"properties": {
"category": {"type": "string", "enum": ["billing", "technical"]},
"summary": {"type": "string"},
"needs_human_review": {"type": "boolean"}
},
"required": ["category", "summary", "needs_human_review"],
"additionalProperties": false
}
}
}
}
JSON
Structured output: Chat Completions
Chat Completions uses response_format.json_schema, which has a different outer wrapper:
curl "$BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d @- <<JSON
{
"model": "$CHAT_MODEL_NAME",
"messages": [{"role": "user", "content": "Customer says: I paid, but the balance has not arrived. Turn this into a ticket."}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "ticket",
"strict": true,
"schema": {
"type": "object",
"properties": {
"category": {"type": "string", "enum": ["billing", "technical"]},
"summary": {"type": "string"},
"needs_human_review": {"type": "boolean"}
},
"required": ["category", "summary", "needs_human_review"],
"additionalProperties": false
}
}
}
}
JSON
Even valid JSON still needs validation for date ranges, numeric precision, entity existence, and authorization. Handle refusal, safety blocking, truncation, protocol failure, and valid JSON as separate outcomes.
Safe execution and idempotency
Give every tool its own permission, timeout, input limit, network egress policy, and rate limit. Use parameterized database queries, an HTTP destination allowlist with SSRF protection, and a least-privilege sandbox for code. Write operations need an application idempotency key and confirmation policy. A repeated call ID must return the existing result instead of charging or ordering again. Tool output can itself contain prompt injection, so structure, truncate, and label it as untrusted before sending it back to the model.
Errors, loops, and observability
Return tool failures as structured {code,message,retryable} data without exposing stacks or secrets. Bound total steps, per-tool calls, tokens, spend, and wall-clock time, and detect repeated arguments. Log trace, response ID, call ID, tool name, argument hash, authorization decision, latency, state, and side-effect ID with sensitive fields redacted. Function arguments can arrive as streamed fragments; execute only after the completion event.
Expert: schema evolution and agent governance
Version tools and output schemas. Adding an optional property can remain compatible, while removing or changing semantics requires a new version and canary. Replay recorded requests, tool results, and final answers against authorization, duplicate execution, partial failure, timeout, refusal, and model-upgrade cases. Put a policy engine and human approval around high-risk writes, separating what the model wants to call from what the system permits. Recover from a persisted state machine, never from the assumption that the model remembers prior side effects.
Use cases
- Let a model call business functions safely
- Produce JSON that conforms to a schema
- Build recoverable and auditable multi-step agents
API protocols
/v1/responses/v1/chat/completions
FAQ
Does a tool call execute automatically?
No. The model emits a tool name and arguments. Your application must authorize, validate, execute, and return the result. Never concatenate arguments into shell, SQL, or URLs.
Does strict=true remove business validation?
No. Schema validates shape, not inventory, ownership, price, date range, or current business state.
Should an agent retry a failed tool forever?
No. Set total steps, per-tool attempts, a deadline, and a budget. Retry only transient failures with a finite backoff.
Related guides
Official sources
- OpenAI Function Calling Guide Official
- OpenAI Structured Outputs Guide Official
- OpenAI Responses API Reference Official
兔子API