Siirry pääsisältöön
OpenAI

22. huhtikuuta 2026

Tekniikka

Agenttien työnkulkujen nopeuttaminen WebSocketien avulla Responses API:ssa

Brian Yu ja Ashwin Nathan, teknisen henkilöstön jäseniä

Ladataan...

Kun pyydät Codexia korjaamaan virheen, se etsii koodikannastasi asiaankuuluvia tiedostoja, lukee ne kontekstin luomiseksi, tekee muutoksia ja suorittaa testejä varmistaakseen, että korjaus toimi. Käytännössä tämä tarkoittaa kymmeniä edestakaisia Responses API -pyyntöjä: määritetään mallin seuraava toiminto, suoritetaan työkalu tietokoneellasi, lähetetään työkalun tuotos takaisin API:lle ja toistetaan.

Kaikki nämä pyynnöt voivat lisätä käyttäjien odotteluaikaa minuuteilla, kun Codex suorittaa monimutkaisia tehtäviä. Viiveen näkökulmasta Codex-agenttisilmukka käyttää suurimman osan ajastaan kolmeen päävaiheeseen: API-palveluissa tehtävään työhön (pyyntöjen validoimiseksi ja käsittelemiseksi), mallin päättelyyn ja asiakaspuolen aikaan (työkalujen suorittamiseen ja mallin kontekstin rakentamiseen). Päättely on vaihe, jossa malli suoritetaan GPU:illa uusien tokenien tuottamiseksi. Aiemmin LLM-päättelyn suorittaminen GPU:illa oli agenttisilmukan hitain osa, joten API-palvelun lisäkuormitus oli helppo piilottaa. Kun päättely nopeutuu, agenttien käyttöönotosta aiheutuva kumulatiivinen API-lisäkuormitus korostuu huomattavasti enemmän.

Tässä kirjoituksessa selitämme, miten teimme API:n avulla toteutetuista agenttisilmukoista kokonaisuudessaan 40 % nopeampia, jolloin käyttäjät voivat kokea päättelynopeuden kasvun 65 tokenista lähes 1 000 tokeniin sekunnissa. Ratkaisimme tämän välimuistin avulla poistamalla tarpeettomia verkkohyppyjä, parantamalla turvallisuuskerrostamme, jotta ongelmat voidaan merkitä nopeasti, ja – mikä tärkeintä – rakentamalla tavan luoda pysyvä yhteys Responses API:in sen sijaan, että olisi tehtävä sarja synkronisia API-kutsuja.

Kaavio nimeltä ”Codex-agenttisilmukka käytännössä” – kaaviossa näkyy Codexin ja Responses API:n välinen iteratiivinen työnkulku työkalukutsuilla (rg, sed, apply_patch, pytest) ja vaihtuvilla tuloksilla, kunnes saavutetaan lopullinen viesti: ”Virhe on korjattu.”

Kun API:sta tuli pullonkaula

Responses API:ssa aiemmat lippulaivamallit, kuten GPT‑5 ja GPT‑5.2, toimivat noin 65 tokenin sekuntinopeudella (TPS). GPT‑5.3‑Codex‑Sparkin, nopean koodausmallin, julkaisua varten tavoitteemme oli päästä kertaluokkaa suurempaan nopeuteen: yli 1,000 TPS:ään, jonka mahdollistaa LLM-päättelyyn optimoitu erityinen Cerebras-laitteisto. Jotta käyttäjät voisivat kokea tämän uuden mallin todellisen nopeuden, meidän oli vähennettävä API-lisäkuormitusta. 

Marraskuun 2025 tienoilla käynnistimme Responses API:a koskevan suorituskykysprintin ja teimme useita optimointeja yksittäisen pyynnön kriittisen polun viiveeseen: 

  • Renderöityjen tokenien ja mallin määritysten tallentaminen välimuistiin kalliin tokenisoinnin ja verkkokutsujen välttämiseksi monivaiheisissa vastauksissa
  • Verkkohyppyviiveen vähentäminen poistamalla kutsut välipalveluihin (esimerkiksi kuvankäsittelyresoluutioon) ja kutsumalla suoraan päättelypalvelua
  • Turvakerroksemme parantaminen, jotta voisimme käyttää tiettyjä luokittelijoita keskustelujen merkitsemiseen nopeammin

Näiden parannusten myötä havaitsimme lähes 45 prosentin parannuksen ensimmäisen tokenin saapumisajassa (TTFT) – mikä kuvastaa API:n responsiivisuutta – mutta nämä parannukset eivät silti olleet vielä riittävän nopeita GPT‑5.3‑Codex‑Sparkille. Näistä parannuksista huolimatta Responses API:n kuormitus oli liian suuri mallin nopeuteen nähden – eli käyttäjien piti odottaa API:amme suorittavia CPU:ita, ennen kuin he pystyivät käyttämään mallia palvelevia GPU:ita.

Syvempi ongelma oli rakenteellinen: käsittelimme jokaista Codex-pyyntöä itsenäisenä, ja jokaisessa seurantapyynnössä käsittelimme keskustelun tilan ja muun uudelleenkäytettävän kontekstin. Vaikka suurin osa keskustelusta ei ollut muuttunut, maksoimme silti työstä, joka oli sidottu koko historiaan. Kun keskustelut pitenivät, toistuva käsittely tuli kalliimmaksi.

Pysyvän yhteyden rakentaminen

Tiivistääksemme suunnittelua arvioimme siirtoprotokollan uudelleen: voisimmeko säilyttää pysyvän yhteyden ja välimuistin tilan sen sijaan, että muodostaisimme uuden yhteyden HTTP:n kautta ja lähettäisimme koko keskusteluhistorian jokaista jatkopyyntöä varten? Ajatuksena oli lähettää vain sellaiset uudet tiedot, jotka vaativat validointia ja käsittelyä, ja säilyttää uudelleenkäytettävä tila muistissa yhteyden elinkaaren ajan. Tämä vähentäisi päällekkäisestä työstä aiheutuvaa kuormitusta.

Harkitsimme muutamia erilaisia lähestymistapoja, mukaan lukien WebSocketeja ja gRPC:n kaksisuuntaista suoratoistoa. Päädyimme WebSocketeihin, koska yksinkertaisena viestinsiirtoprotokollana niiden ansiosta käyttäjien ei tarvitsisi muuttaa Responses API:n syöte- ja tuotosmuotoja. Se oli kehittäjäystävällinen ja sopi olemassa olevaan arkkitehtuuriimme aiheuttamatta juurikaan häiriöitä.

Ensimmäinen WebSocket-prototyyppi muutti käsitystämme siitä, mikä oli mahdollista Responses API:n viiveen suhteen. Codex-tiimin insinööri, jolla oli syvällistä asiantuntemusta koko API-pinosta, kokosi prototyypin ajamalla Codex-agenttia yön yli.

Kyseisessä prototyypissä agenttipohjaiset käyttöönotot mallinnettiin yhtenä pitkäkestoisena vastauksena. asyncio-ominaisuuksia käytettäessä Responses API estäisi asynkronisesti etenemisen näytteenottosilmukassa sen jälkeen, kun työkalukutsu oli valittu, ja Responses API lähettäisi response.done-tapahtuman takaisin asiakkaalle. Työkalukutsun suorittamisen jälkeen asiakkaat lähettäisivät takaisin työkalun tuloksen sisältävän response.append-tapahtuman, mikä avaisi näytteenottosilmukan ja antaisi mallin jatkaa.

Tässä voidaan ajatella, että paikallista työkalukutsua käsitellään isännöitynä työkalukutsuna. Kun malli kutsuu verkkohakua, päättelysilmukka estyy, kutsuu verkkohakupalvelua ja lisää palvelun vastauksen mallin kontekstiin. Suunnittelussamme teimme saman asian, mutta etäpalvelun kutsumisen sijaan lähetimme mallin työkalukutsun takaisin asiakkaalle WebSocketin kautta. Kun asiakas vastasi, lisäsimme asiakkaan työkalukutsuvastauksen kontekstiin ja jatkoimme näytteistystä.

Tämä suunnitelma oli erittäin tehokas, koska se poisti toistuvan API-työn agentin käyttöönoton yhteydessä. Voisimme tehdä esipäättelytyön kerran, pitää taukoa työkalun suorittamisen ajan ja tehdä jälkipäättelytyön kerran lopussa.

Valitettavasti tämän seurauksena API:n rakenne muuttui vieraammaksi ja monimutkaisemmaksi. Halusimme, että kehittäjät voivat lisätä WebSocket-tuen ilman, että heidän tarvitsee muokata API-integraatiotaan uuden vuorovaikutustavan mukaiseksi.

API:n pitäminen tuttuna samalla kun teknologiapinosta tehdään asteittain kehittyvä

Julkaisemassamme versiossa palasimme tuttuun tapaan: käytämme edelleen response.create-tapahtumaa samalla sisällöllä ja käytämme previous_response_id-tapahtumaa jatkaaksemme keskustelun kontekstia edellisen vastauksen tilasta.

WebSocket-yhteydessä palvelin ylläpitää yhteyskohtaista muistissa olevaa välimuistia aiempien vastausten tilasta. Kun response.create-jatkotapahtuma sisältää previous_response_id-tapahtuman, haemme kyseisen tilan välimuistista sen sijaan, että rakentaisimme koko keskustelun uudelleen alusta alkaen.

Tähän välimuistissa olevaan tilaan sisältyy:

  • Edellinen response-objekti
  • Aiemmat syötteet ja tuotokset
  • Työkalumääritelmät ja nimiavaruudet
  • Uudelleenkäytettävät näytteenottoartefaktit, kuten aiemmin renderöidyt tokenit
Kaavio otsikolla ”Peräkkäisistä pyynnöistä päällekkäiseen suoritukseen” – kaaviossa verrataan peräkkäistä pyyntöputkea WebSocket-pohjaiseen lähestymistapaan, jossa useat pyynnöt menevät päällekkäin validointi-, esipäättely-, näytteenotto- ja jälkipäättelyvaiheiden aikana.

Hyödyntämällä uudelleen muistissa olevaa edellisen vastauksen tilaa pystyimme tekemään useita merkittäviä optimointeja:

  • Saamme osan turvallisuusluokittelijoistamme ja pyyntöjen validoijistamme käsittelemään vain uutta syötettä sen sijaan, että ne käsittelisivät koko historian joka kerta
  • Pidämme muistissa olevaa välimuistia renderöidyistä tokeneista, joihin lisäämme tietoja, jotta voimme ohittaa tarpeettoman tokenisoinnin
  • Käytämme uudelleen onnistunutta mallinnusratkaisun/reitityksen logiikkaamme eri pyyntöjen välillä 
  • Yhdistämme ei-estävän jälkipäättelytyön, kuten laskutuksen, seuraaviin pyyntöihin

Tavoitteena oli päästä mahdollisimman lähelle mahdollisimman kevyttä prototyyppiä, mutta säilyttää API:n muoto, jonka kehittäjät jo tunsivat ja jonka pohjalta he olivat rakentaneet.

Uuden standardin asettaminen nopeudelle

Kahden kuukauden WebSocket-tilan kehitysspurtin jälkeen julkaisimme alfaversion keskeisten koodausagentteja kehittävien startup-yritysten kanssa, jotta ne voisivat integroida sen infrastruktuuriinsa ja lisätä liikennettä turvallisesti. Alfakäyttäjät pitivät siitä kovasti ja ilmoittivat jopa 40 %:n parannuksista(avautuu uudessa ikkunassa) agenttipohjaisissa työnkuluissaan. Positiivisen alfapalautteen ansiosta olimme valmiita julkaisuun.

Julkaisun tulokset näkyivät välittömästi. Codex siirsi nopeasti suurimman osan Responses API -liikenteestään WebSocket-tilaan, ja viive parani merkittävästi. GPT‑5.3‑Codex‑Sparkin osalta saavutimme 1 000 TPS:n tavoitteemme ja havaitsimme hetkellisiä piikkejä aina 4 000 TPS:ään asti, mikä osoitti, että Responses API pystyi käsittelemään huomattavasti nopeampaa päättelyä aidossa tuotantoliikenteessä. Vaikutus näkyi nopeasti myös kehittäjäyhteisössä:

WebSocket-tila on yksi Responses API:n merkittävimmistä uusista ominaisuuksista sen jälkeen, kun se julkaistiin maaliskuussa 2025. Siirryimme ideasta tuotantokäyttöön vain muutamassa viikossa OpenAI:n API- ja Codex-tiimien tiiviin yhteistyön ansiosta. Se ei ainoastaan vähennä merkittävästi agentin käyttöönoton viivettä, vaan tukee myös kehittäjien kasvavaa tarvetta: kun mallin päättely nopeutuu, myös päättelyä ympäröivien palveluiden ja järjestelmien on nopeuduttava, jotta nämä hyödyt välittyvät käyttäjille. 

Tekijät

Brian Yu ja Ashwin Nathan

Kiitokset

Erityiskiitokset Responses API- ja Codex-tiimeille, jotka työskentelivät WebSocket-tilan kehittämiseksi.