Изградете слой за съвместимост на Responses API в AI API Gateway
Шлюзът на API за отговори не е просто прокси за завършване на чат с нов маршрут. Запазете елементите на отговора, състоянието, извикванията на инструменти, потоците, непрекъснатостта на разсъжденията, приписването на използването и поведението на понижаване с първокласен слой за съвместимост.
Не прилагайте /v1/responses, като превеждате всяка заявка в /v1/chat/completions и се надявате, че формата е достатъчно близка. Този адаптер може да върне текст, но може тихо да загуби частите, за които се интересуват разработчиците: елементи за отговор, състояние от страна на сървъра, извиквания на инструменти, непрекъснатост на разсъжденията, събития от жизнения цикъл на потока, семантика на анулиране и приписване на използване на ниво елемент.
Практическата цел е слой за съвместимост, който третира Responses API като по-богат протокол. Запазете поддръжката на Chat Completions за съществуващи клиенти, но изградете Responses като собствена повърхност на шлюз със собствен модел на състояние, нормализатор на потока, книга за извикване на инструменти, матрица на възможностите и резервни правила.
Какво е фактология, какво е политика и какво е прогноза?
Факти: OpenAI описва Responses API като обединяващи възможности, които преди са били разделени между завършвания на чат и асистенти, включително поддръжка за инструменти като търсене в мрежата, търсене на файлове и използване на компютър. API разкрива полета като previous_response_id, поточно предаване, избор на инструменти и вградени инструменти. Документацията на SDK показва, че previous_response_id може да осигури непрекъснатост на разговора, докато предишните инструкции не се пренасят автоматично и трябва да бъдат изпратени отново, когато все още трябва да са в сила. Справката за поточно предаване на OpenAI включва различен жизнен цикъл на отговора и изходни събития, а не само делта токени.
Препоръки: Шлюзът трябва да запази тази семантика, вместо да я изравни по подразбиране. Той трябва да отхвърли или изрично да понижи заявките, когато целевият доставчик не може да поддържа необходимото поведение.
Прогноза: Повече работни натоварвания на агенти ще зависят от структурата на отговорния елемент, следите за изпълнение на инструмента и контекста на разсъжденията със състояние. Шлюзове, които моделират тези концепции сега, ще бъдат по-лесни за разширяване от шлюзове, които третират Отговорите като козметична крайна точка.
Дефинирайте отделен договор за съвместимост за Отговори
Първата грешка при внедряването е приемането, че OpenAI-съвместим означава една универсална схема за заявка и отговор. На практика /v1/chat/completions и /v1/responses трябва да бъдат отделни договори за съвместимост.
Запазете споделен слой за удостоверяване, таксуване, квота и маршрутизиране, но отделете слоя на протокола:
- Показване на завършвания на чат: съобщения, избори, делта, извиквания на инструменти във формат на чат, наследено клиентско поведение.
- Отговори: входни елементи, изходни елементи, идентификатори на отговор, препратки към предишни отговори, по-богати събития с инструменти, събития от жизнения цикъл на потока, полета, свързани с разсъждение, и крайно състояние на отговор.
Това разделяне има значение за тестовете за съответствие. Адаптер на доставчик, който преминава тестове за чат, все още може да се провали при тестовете за отговори, тъй като не може да запази previous_response_id, подреждането на елементите, структурата на отказите, хостваните метаданни на инструмента или имена на поточни събития.
Договорът за минимална съвместимост трябва да отговаря на:
- Кои полета на заявка се приемат, отхвърлят, трансформират или игнорират?
- Кои типове елементи за отговор са запазени?
- Кои типове инструменти се поддържат за всеки доставчик и модел?
- Може ли доставчикът да поддържа състоянието на разговора или шлюзът трябва да го поддържа?
- Какво се случва, когато се поиска
store=false? - Какви поточни събития са гарантирани?
- Как се записват анулирането, времето за изчакване и частичното използване?
Ако вече имате шлюз на AI API, третирайте поддръжката на Responses като разширение на протокол, а не като псевдоним на маршрут.
Използване на каноничен модел на отговор
API за отговори връща повече от едно помощно съобщение. Може да представлява различни изходни елементи и събития. Вашият шлюз се нуждае от вътрешен каноничен модел, преди да се свърже с който и да е доставчик.
Една практична вътрешна схема на артикул може да започне така:
<предварителен код>{ "gateway_response_id": "gw_resp_...", "provider_response_id": "отговор_...", "tenant_id": "ten_123", "key_id": "ключ_456", "model_alias": "агент по подразбиране", "доставчик": "отворен", "елементи": [ { "item_id": "артикул_1", "тип": "текст", "роля": "асистент", "съдържание": [{ "тип": "изходен_текст", "текст": "..." }], "статус": "завършен" }, { "item_id": "артикул_2", "тип": "извикване_на функция", "call_id": "call_abc", "име": "поръчка_на_търсене", "arguments_json": "{\"order_id\":\"123\"}", "статус": "завършен" } ], "използване": { "input_tokens": 0, "изходни_токени": 0, "reasoning_tokens": нула, "единици_инструменти": [] }, "статус": "завършен" }Включете типовете артикули дори преди всеки доставчик да може да ги произведе. Полезните категории включват:
- Текстов изход
- Откази
- Извиквания на функции
- Изходи на функцията, изпратени от приложението
- Обобщения на разсъжденията или метаданни, свързани с разсъжденията, когато има такива
- Препратки към файлове
- Търсене в мрежата, търсене на файлове, използване на компютър или други събития с хоствани инструменти
- Окончателни метаданни за използване и фактуриране
Въпросът не е да се излага собствена схема на потребителите. Целта е шлюзът да не изхвърля информация, преди да може да я одитира, таксува, предава поточно, възпроизвежда или трансформира.
Изградете държавна книга, притежавана от портал
previous_response_id е полето, което в най-голяма степен разкрива разликата между проксито за чат без състояние и съвместимостта на отговорите. Ако клиент се позовава на предишен отговор, шлюзът трябва да знае какво означава този идентификатор, дали наемателят има право да го използва и дали доставчикът може да продължи от него.
Създайте държавна книга с ключ от наемател и ID на отговора:
<предварителен код>{ "gateway_response_id": "gw_resp_789", "provider_response_id": "resp_provider_789", "previous_gateway_response_id": "gw_resp_456", "tenant_id": "ten_123", "user_id": "user_999", "key_id": "ключ_456", "модел": "gpt-...", "доставчик": "отворен", "store_mode": "доставчик|шлюз|няма", "retention_policy": "стандартно|нулево_задържане|персонализирани_30d", "instructions_hash": "sha256:...", "tool_policy_id": "tools_readonly_v3", "created_at": "...", "expires_at": "...", "deleted_at": нула }Важно правило: не емулирайте автоматично previous_response_id чрез възпроизвеждане на пълната история на чата, освен ако наемателят изрично не е разрешил това поведение на задържане и разходи. Повторното възпроизвеждане може да увеличи цената на токена, да промени позицията на поверителност и да промени поведението на модела. По-безопасно е да върнете грешка при ясна способност, отколкото безшумно да изпратите съхранено съдържание на разговор, което приложението не е очаквало да запазите или използвате повторно.
Режими за обработка на състоянието
- Състояние на доставчика: Доставчикът нагоре по веригата съхранява достатъчно контекст и шлюзът съпоставя идентификаторите на отговорите на шлюза с идентификаторите на отговорите на доставчика.
- Състояние на шлюза: Шлюзът съхранява необходимите предишни елементи и възстановява контекста, когато е разрешено.
- Няма състояние: Заявката използва
store=falseили политиката на клиента забранява запазването.previous_response_idтрябва да бъде отхвърлен, освен ако доставчикът не може да уважи заявката без задържане на шлюза и правилата го позволяват.
Също така не забравяйте, че предишните инструкции може да се наложи да бъдат изпратени повторно от клиента, когато трябва да продължат да се прилагат. Шлюзът не трябва да измисля скрити инструкции, за да компенсира, освен ако това поведение не е част от изрична политика на клиента.
Потвърдете инструментите преди изпращане
Отговорите правят използването на инструмента по-централно. Слоят за съвместимост трябва да обработва две широки категории:
- Приложни инструменти: Дефиниции на функции, предоставени от клиента, изпълнени извън доставчика на модела, с изходни данни, изпратени обратно към API.
- Инструменти на хостван доставчик: Търсене в мрежата, търсене на файлове, използване на компютър, изпълнение на код, заземяване или подобни инструменти, изпълнявани от доставчика или инфраструктура, контролирана от шлюз.
При влизане проверете схемите на инструментите преди маршрутизиране:
- Отхвърлете рано невалидната JSON схема.
- Налагане на максимален размер на схемата и дълбочина на влагане.
- Проверете имената на инструментите за съвместимост с доставчика.
- Прилагане на обхвати на клиент, ключ, потребител и среда.
- Изисквайте пропуски за одобрение за инструменти, които записват данни, харчат пари, имат достъп до чувствителни системи или извикват външни конектори.
За извикване на функция на приложението изисквайте стабилен идентификатор на повикване. Моделът излъчва извикване на функция с call_id; приложението изпраща изхода на инструмента, позовавайки се на този идентификатор; шлюзът записва и двете в една и съща следа. Без този ключ за присъединяване журналите за проверка и повторните опити стават двусмислени.
За хоствани инструменти резервирайте бюджет преди изпращане и уредете разходите след това. Хостваните инструменти може да добавят такси извън обикновеното счетоводно отчитане на токени, така че свържете регистъра на инструментите към унифицирано таксуване на AI API, вместо да скривате тези разходи в обща сума за извикване на модел.
Нормализиране на поточно предаване като събития, а не текст на токен
Проксито за чат често може да се измъкне с препращане на делта токени. Шлюзът за отговори не може. Потокът има значение на жизнения цикъл: отговорът може да започне, изходните елементи могат да стартират и завършат, текстът може да пристигне в делта, извикванията на инструменти могат да бъдат асемблирани постепенно, използването може да пристигне в края или по време на потока и отговорът може да се провали или да бъде отменен.
Дефинирайте схема на събитие на шлюз, след което нанесете всеки поток на доставчик в нея:
събитие: response_started
данни: { "response_id": "gw_resp_123", "status": "in_progress" }
събитие: output_item_startedданни: { "item_id": "item_1", "type": "text" }
събитие: text_delta
данни: { "item_id": "item_1", "delta": "Здравей" }
събитие: tool_call_delta
данни: { "item_id": "item_2", "call_id": "call_abc", "arguments_delta": "{\"order" }
събитие: usage_delta
данни: { "изходни_токени": 12 }
събитие: завършено
данни: { "response_id": "gw_resp_123", "използване": { ... } }
Препоръчани нормализирани събития:
response_startedoutput_item_startedoutput_item_completedtext_deltaотказ_делтаtool_call_deltatool_result_receivedusage_deltaзавършеноотмененонеуспешно
Когато клиентът прекъсне връзката, разпространете анулирането нагоре по веригата, ако доставчикът го поддържа. Запишете състоянието на частичен отговор така или иначе. Ако по-късно доставчикът върне окончателното използване чрез забавено обратно извикване или последна част, съгласувайте счетоводната книга. Съвместимостта с поточно предаване е толкова свързана с отчитането и жизнения цикъл, колкото и със закъснението.
Създайте матрица за възможности на доставчик
Многомоделното маршрутизиране е полезно само когато шлюзът разбира какво може безопасно да бъде маршрутизирано. Добавете специфични за Responses възможности към вашия каталог с модели:
<предварителен код>{ "model_alias": "агент по подразбиране", "маршрути": [ { "доставчик": "отворен", "модел": "...", "supports_responses": вярно, "supports_previous_response_id": вярно, "supports_store_false": вярно, "supports_builtin_web_search": вярно, "supports_function_calling": вярно, "supports_stream_lifecycle_events": вярно, "supports_reasoning_context_continuity": вярно, "max_tool_schema_bytes": 65536 }, { "доставчик": "доставчик_b", "модел": "...", "supports_responses": невярно, "chat_adapter_available": вярно, "loss_profile": ["no_previous_response_id", "no_hosted_tools", "flattened_stream"] } ] }Резервният вариант трябва да е наясно с загубите. Ако заявката изисква вградено уеб търсене и резервният доставчик не може да я изпълни, не отговаряйте тихо без търсене. Ако заявката зависи от запазения контекст на разсъждение и резервният маршрут не може да го запази, върнете грешка във възможността или отговор за понижаване, който клиентът изрично е избрал.
Полезна опция за заявка е:
<предварителен код>{ "модел": "агент по подразбиране", "вход": "...", "резервна_политика": { "allow_lossy": невярно, "позволени_загуби": [] } }За по-малко чувствителни случаи на употреба наемателите могат да разрешат специфични понижавания със загуба:
<предварителен код>{ "резервна_политика": { "allow_lossy": вярно, "allowed_losses": ["flattened_stream", "no_reasoning_summary"] } }Шлюзът трябва да регистрира резервното решение и в двата случая. Това прави възможно по-късно отстраняване на грешки, когато даден агент се държи различно след прекъсване на доставчика или пренасочване на модела.
Използване на атрибут на ниво отговор и елемент
Обажданията с отговори могат да струват повече от еквивалентните завършвания на чат, защото могат да включват изпълнение на инструмент, по-дълъг контекст, токени за разсъждение, търсене на файл, търсене в мрежата или повтарящи се инструкции. Един общ сборен брой токени не е достатъчен за табло за анализ на използването на AI API.
Записвайте използването на две нива:
- Ниво на отговор: наемател, ключ, потребител, модел, доставчик, латентност, крайно състояние, входни токени, изходни токени, логически токени, когато са отчетени, обща цена и резервен маршрут.
- Ниво на артикул/инструмент: име на инструмента, идентификатор на повикване, хоствани инструментални единици, идентификатори на файлове, брой заявки за търсене, ако има такива, забавяне на инструмента, цена на инструмента и резултат от правилата за одобрение.
Това позволява на разработчиците да отговарят на конкретни въпроси:
- Увеличиха ли се разходите поради по-дълго състояние, усилие за разсъждение, извиквания на инструменти или резервен вариант?
- Кой клиент или API ключ генерира такси за хостван инструмент?
- Кой отговор е неуспешен след извикване на инструмент, но преди окончателния текст?
- Кои отменени потоци все още водят до използване нагоре?
Бравете с нулево задържане и изтриване като първокласно поведение
Състоянието от страна на сървъра е полезно, но променя задълженията на шлюза за задържане. Вградете политика в протоколния слой, вместо да я третира като настройка за регистриране.
За всяка заявка за отговори, разреши:
- Правила за задържане на наематели
- Предпочитание за
магазинна ниво заявка - Съвместимост при задържане на доставчик
- Дали повторението на шлюза е разрешено
- Дали входовете и изходите на инструмента могат да се съхраняват
- Поведение при изтичане и изтриване за състояние на отговор
Ако запазването е деактивирано, шлюзът все още може да пази минимални оперативни метаданни: времеви клейма, идентификатори, състояние, брой токени, разходи и решения за правилата. Избягвайте да съхранявате необработени подкани, пълни резултати от инструменти или реконструирана история, освен ако правилата не го позволяват.
Приспособления за съответствие, които да добавите преди стартиране
Не разчитайте на ръчни тестове за щастлив път. Добавете приспособления, които проверяват поведението на протокола през директни OpenAI маршрути, адаптирани към доставчика маршрути и резервни сценарии.
Минимален тестов набор
- Основен отговор: текстовият елемент се връща със стабилен ID на отговора и употреба.
- Многократно състояние: втората заявка препраща към
previous_response_id; шлюзът валидира собствеността на наемателя и режима на състояние. - Повтарящи се инструкции: проверете дали пропуснатите инструкции не са измислени тихо от шлюза.
- Обиколно пътуване на повикване на функция: моделът излъчва идентификатор на повикване; приложението изпраща изход; окончателният отговор обединява двата записа.
- Правила за хостван инструмент: неоторизиран вграден инструмент се блокира преди изпращане.
- Ред на поточно предаване: начало на отговора, начало на елемент, делти, завършване на елемент, използване и завършване се излъчват във валиден ред.
- Анулиране на поток: прекъсването на връзката с клиента задейства анулиране нагоре, където се поддържа, и записва частично използване.
- Резервно отхвърляне: доставчикът без семантика на необходимите отговори връща грешка във възможността.
- Резервно включване при загуба: заявка с разрешени загуби получава явен маркер за понижаване.
- Режим на нулево задържане: повторното възпроизвеждане на състоянието и задържането на подкана от страна на шлюза са блокирани.
Препоръчителна последователност на внедряване
- Изложете бета маршрут. Добавете
/v1/responses, без да променяте съществуващото поведение в чата. - Първо внедряване на преминаване за доставчиците с поддръжка на естествени отговори. Запазване на идентификатори, елементи, потоци, използване и грешки.
- Добавете държавната книга. Съпоставете идентификаторите на шлюза с идентификаторите на доставчика и наложете собствеността на наемателя.
- Добавете канонични елементи. Съхранявайте метаданни за елементи, необходими за проверка, таксуване и реконструкция на поток.
- Добавете управление на инструмента. Валидирайте схеми, наложете обхвати и записвайте съединявания на извикване на инструмент.
- Добавете нормализиране на стрийминг. Конвертирайте специфични за доставчика потоци в събития от жизнения цикъл на шлюза.
- Добавяне на маршрутизиране, съобразено с възможностите. Разрешаване само на безопасни резервни варианти по подразбиране.
- Добавяне на анализи и разплащане за таксуване. Приписване на токен, мотивиране и използване на инструмента отделно.
- Публикувайте бележки за съвместимост. Кажете на разработчиците кои полета са оригинални, емулирани, неподдържани или със загуба.
Изпълнимо заключение
Слоят за съвместимост на API за отговори трябва да запазва значението на протокола, а не просто да връща правдоподобен текст. Изградете го около пет трайни обекта: каноничен модел на отговор на елемента, книга за състояние на разговор, книга за извикване на инструменти, нормализатор на поточно събитие и матрица на възможностите на доставчика.
Най-безопасният стандарт по подразбиране е стриктната съвместимост: ако даден маршрут не може да запази изискваното състояние, инструменти, контекст на разсъждение, събития на потока или поведение на задържане, връща ясна грешка на възможностите. Добавете резервен вариант със загуба на включване само когато разработчиците разберат какво ще бъде премахнато. Този подход може да изглежда по-малко удобен от автоматичното изравняване, но предотвратява най-лошия режим на повреда: приложение, което изглежда съвместимо, като същевременно тихо губи семантиката, която го е накарала да използва Responses API на първо място.