Function Calling: Responses API и Chat Completions
Сравнение определений функций, Call ID, результатов, streaming arguments, авторизации, идемпотентности и совместимости маршрутов.
Responses и Chat Completions могут попросить приложение выполнить функцию, но представляют Tool Loop по-разному. Chat Completions определяет функции в tools[].function, возвращает message.tool_calls и принимает результаты как сообщения role: "tool". Responses использует плоские определения, типизированные function_call Output Items и function_call_output, связанные через call_id.
Модель не выполняет функцию. Код приложения должен проверить аргументы, авторизовать операцию, безопасно выполнить её, вернуть результат и предотвратить повторные Side Effects при Retry.
Четыре шага Tool Loop
1. Объявить разрешённую функцию и Schema аргументов
2. Получить один или несколько Function Calls от модели
3. Проверить, авторизовать и выполнить каждый Call в приложении
4. Вернуть каждый результат с Correlation ID вызова
Только после шага четыре модель может сформировать ответ на основе результата. Следующий Tool запускает новую итерацию с новой Call ID. OpenAI Function Calling Guide также описывает многошаговый обмен.
Сравнить Wire Contracts
| Аспект | Responses API | Chat Completions |
|---|---|---|
| Определение | Плоский элемент tools[] |
Поля в tools[].function |
| Предложенный Call | function_call Output Item |
Assistant tool_calls[] |
| Корреляция | call_id |
id, результат как tool_call_id |
| Имя | function_call.name |
tool_calls[].function.name |
| Аргументы | JSON-строка function_call.arguments |
JSON-строка tool_calls[].function.arguments |
| Результат | function_call_output |
Сообщение role: "tool" |
| Streaming | Типизированные Argument Events | Фрагменты delta.tool_calls[] |
| Финальный текст | Output Items / Helper | choices[0].message.content |
Нельзя связывать Calls по позиции в Array. Параллельные вызовы и chunks могут завершиться в другом порядке. Явная Call ID — стабильный Join Key.
Определить строгую Function Schema
{
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^ORDER-[0-9]{4}$" }
},
"required": ["order_id"],
"additionalProperties": false
}
strict: true просит модель соблюдать Schema, но приложение всё равно парсит и валидирует аргументы. Поддержка pattern различается, поэтому применяется тот же compatibility gate, что и для Structured Outputs.
Реализовать Loop через Responses API
const tools = [{
type: "function",
name: "get_delivery_status",
description: "Return the current delivery status for one order.",
parameters: {
type: "object",
properties: { order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" } },
required: ["order_id"], additionalProperties: false,
},
strict: true,
}];
const first = await client.responses.create({
model, input: "Where is ORDER-1001?", tools, parallel_tool_calls: false,
});
const calls = first.output.filter(item => item.type === "function_call");
const outputs = calls.map(call => ({
type: "function_call_output",
call_id: call.call_id,
output: JSON.stringify(executeTool(call.name, call.arguments)),
}));
const final = await client.responses.create({
model, input: [...first.output, ...outputs], tools, parallel_tool_calls: false,
});
call.call_id и call_id результата должны совпадать. В stateless-варианте предыдущие Output Items возвращаются вместе с результатами. Нельзя предполагать, что любой OpenAI-compatible маршрут хранит Response State.
Реализовать Loop через Chat Completions
const tools = [{
type: "function",
function: {
name: "get_delivery_status",
description: "Return the current delivery status for one order.",
parameters: {
type: "object",
properties: { order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" } },
required: ["order_id"], additionalProperties: false,
},
strict: true,
},
}];
const first = await client.chat.completions.create({ model, messages, tools });
const assistant = first.choices[0].message;
messages.push(assistant);
for (const call of assistant.tool_calls ?? []) {
messages.push({
role: "tool",
tool_call_id: call.id,
content: JSON.stringify(executeTool(call.function.name, call.function.arguments)),
});
}
Assistant Message с Calls добавляется в messages до результатов. Его отсутствие или неправильный tool_call_id создаёт некорректную историю.
Считать Streaming Arguments фрагментами
{"order — неполный, а не невалидный JSON. Для каждой Call ID нужен отдельный Buffer: добавлять Delta, дождаться Arguments Done или Completed, один раз распарсить полный String и выполнить после валидации. Responses использует Typed Events, Chat Completions — choices[].delta.tool_calls[]. Нельзя запускать функцию на первом фрагменте. См. AI API Streaming Guide.
Сделать выполнение безопасным и идемпотентным
- разрешать только зарегистрированные Function Names;
- ограничивать размер и проверять полную Schema;
- авторизовать User или Workload для ресурса;
- разделять Read-only Tools и Side Effects;
- удалять Secrets из результата;
- использовать Deadline и ограниченные Downstream Retries;
- сохранять безопасную Operation Reference.
Для Side Effect создаётся Idempotency Key из стабильного Application Request и Call ID. Результат сохраняется до ответа модели. Replay возвращает сохранённый результат вместо второго refund, сообщения, deployment или изменения БД.
Function Name и Arguments модели — untrusted input. Валидная Schema не выдаёт прав и не заменяет транзакцию.
Определить правила для нескольких Calls
parallel_tool_calls: false упрощает State Machine. При параллельном режиме связывайте результаты по Call ID, ограничивайте Calls и Concurrency, определяйте влияние ошибки, возвращайте результат для каждого принятого вызова и сериализуйте зависимые Side Effects. Параллельность ускоряет независимое чтение, но усложняет authorization, retry и partial failure.
Понимать границу совместимости Modelflare
Modelflare сохраняет Strict Function Definitions и преобразует поддерживаемые формы между Responses и Chat Completions на допустимых OpenAI/Codex-маршрутах. Mapping намеренно уже полной Responses Tool Surface.
Application-defined Functions представлены в обоих форматах. Hosted Tools поставщика — Search, Code Execution и другие — не эквивалентны и не должны считаться автоматически конвертируемыми. Другие семейства OpenAI-compatible остаются Raw Chat Completions Pass-through до проверки; upstream определяет поддержку tools, strict, Parallel Calls, Streaming Arguments и tool_choice.
| Тест | Необходимая информация |
|---|---|
| Read-only Call | Имя, аргументы, Call ID, связь результата, финальный текст |
| Невалидные аргументы | Явная ошибка без выполнения |
| Неизвестная функция | Отказ по Allowlist |
| Tool не нужен | Обычный текст без выдуманного Call |
| Streaming | Полные аргументы и корректная ID |
| Повторный Request | Один Side Effect или сохранённый результат |
| Несколько Calls | Корреляция независимо от порядка |
| Route Fallback | Те же модель, протокол, Schema и контракт |
Reliable AI API Routing помогает сделать смену маршрута явной, AI API Key Security — разделить Workloads и права.
Выбрать формат по контракту приложения
Responses подходит для Typed Output Items, Responses Event Model, State Continuation и проверенных Responses-функций. Chat Completions подходит при стабильном Message Transcript и проверенном Tool Contract поставщика. См. Responses API и Chat Completions.
Стандарт одинаков: явный Tool Allowlist, Strict Argument Schema, валидация в приложении, authorization до выполнения, корреляция по Call ID, идемпотентность Side Effects и полный результат для модели. Надёжность дают эти контроли, а не название endpoint.