Preskočite na glavno vsebino
OpenAI

23. januar 2026

Tehnologija

Razvijanje zanke agenta Codex

Michael Bolin, član tehničnega osebja

Nalaganje …

Codex CLI(odpre se v novem oknu) je naš večplatformni lokalni programski agent, zasnovan za ustvarjanje visokokakovostnih in zanesljivih sprememb programske opreme, pri čemer na vaši napravi deluje varno in učinkovito. Od prvega lansiranja CLI-ja aprila smo pridobili izjemno veliko znanja o tem, kako zasnovati programski agent najvišje ravni. Da bi te vpoglede razčlenili, je ta prispevek prvi v tekoči seriji, v kateri bomo raziskovali različne vidike delovanja Codexa ter predstavljali izkušnje, pridobljene skozi prakso. (Za še bolj podroben vpogled v zasnovo Codex CLI si lahko ogledate naš odprtokodni repozitorij na naslovu https://github.com/openai/codex(odpre se v novem oknu). Številne podrobnosti naših oblikovalskih odločitev so zabeležene v GitHub zahtevkih in zahtevkih za združitev sprememb, če želite izvedeti več.)

Za začetek se bomo osredotočili na zanko agenta, ki predstavlja osrednjo logiko v Codex CLI in je odgovorna za orkestracijo interakcije med uporabnikom, modelom in orodji, ki jih model prikliče za izvajanje smiselnega dela na programski opremi. Upamo, da vam bo ta prispevek ponudil jasen vpogled v vlogo, ki jo ima naš agent (»ogrodje«), pri učinkoviti uporabi velikega jezikovnega modela (LLM).

Preden se poglobimo, še kratka opomba o terminologiji. Pri OpenAI izraz »Codex« označuje nabor ponudb programskih agentov, med katerimi so Codex CLI, Codex Cloud in razširitev Codex za VS Code. Ta prispevek se osredotoča na ogrodje Codex, ki zagotavlja osnovno zanko agenta in izvršilno logiko, na kateri temeljijo vse izkušnje s Codexom in ki so uporabnikom dostopne prek Codex CLI. Zaradi preglednosti bomo izraza »Codex« in »Codex CLI« uporabljali izmenično. Za lažjo uporabo bomo tukaj izraza “Codex” in “Codex CLI” uporabljali izmenično.

Zanka agenta

V središču vsakega agenta, ki ga poganja umetna inteligenca, je tako imenovana 'zanka agenta'. Poenostavljen prikaz zanke agenta je naslednji:

Diagram z naslovom »Agent loop« ponazarja, kako sistem UI obdeluje uporabnikovo zahtevo, prikliče orodja, opazuje rezultate, posodobi načrt in vrne izhode. Puščice povezujejo korake, kot so uporabnikov vnos, sklepanje modela, dejanja orodij in končni odgovor.

Najprej agent prejme uporabnikov vnosin ga vključi v nabor besedilnih navodil, ki jih pripravi za model. Ta nabor navodil imenujemo poziv.

Naslednji korak je poizvedba modela, pri kateri mu agent posreduje navodila in zahteva generiranje odziva. Ta postopek imenujemo inferenca. Med inferenco se besedilni poziv najprej pretvori v zaporedje vhodnih žetonov(odpre se v novem oknu), to so cela števila, ki se nanašajo na vnose v besedišču modela. Ti žetoni se nato uporabijo za vzorčenje modela, kar povzroči nastanek novega zaporedja izhodnih žetonov.

Izhodni žetoni se pretvorijo nazaj v besedilo, ki predstavlja odziv modela. Ker se žetoni ustvarjajo postopoma, se lahko ta pretvorba izvaja sproti med delovanjem modela, zato številne aplikacije, ki temeljijo na velikih jezikovnih modelih, prikazujejo pretočni izhod. V praksi je inference običajno skrita za aplikacijskim programskim vmesnikom (API), ki deluje na ravni besedila in s tem abstrahira podrobnosti tokenizacije.

Kot rezultat koraka sklepanja model bodisi (1) pripravi končni odgovor na uporabnikov izvirni vnos ali (2) zahteva priklic orodja, ki ga naj bi agent izvedel (npr. »zaženi ls in poročaj o izhodu«). V primeru (2) agent izvede priklic orodja in njegov izhod doda k izvirnemu pozivu. Ta izhod se uporabi za oblikovanje novega vhoda, s katerim se model ponovno poizve, pri čemer agent nove informacije upošteva in postopek ponovi.

Ta postopek se ponavlja, dokler model ne preneha izdajati klicev orodij in namesto tega pripravi sporočilo za uporabnika (v modelih OpenAI imenovano sporočilo asistenta). V številnih primerih to sporočilo neposredno odgovori na uporabnikovo izvirno zahtevo, lahko pa predstavlja tudi dodatno vprašanje za uporabnika.

Ker agent lahko izvaja priklice orodij, ki spreminjajo lokalno okolje, njegov »izhod« ni omejen zgolj na sporočilo asistenta. Pogosto je glavni izhod programskega agenta koda, ki jo zapiše ali uredi na vaši napravi. Kljub temu se vsak korak vedno konča s sporočilom asistenta—na primer »Dodal sem architecture.md, ki ste ga zahtevali«—kar signalizira stanje zaključka v zanki agenta. Z vidika agenta je delo opravljeno in nadzor se vrne uporabniku.

Pot od uporabniškega vnosa do odziva agenta, prikazana v diagramu, se imenuje en korak (ang. turn) pogovora (pogovorni niz (ang. thread) v Codexu). Čeprav lahko ta pogovorni korak vključuje veliko iteracij med modelom in priklici orodij. Vsakič, ko v obstoječem pogovoru pošljete novo sporočilo, se celotna zgodovina pogovora vključi v poziv za novi korak, ki vključuje sporočila in priklice orodij iz prejšnjih korakov:

Diagram z naslovom »Multi-turn agent loop« prikazuje, kako agent UI iterativno prejema uporabnikov vnos, ustvarja dejanja, uporablja orodja, posodablja stanje in vrača rezultate. Vključuje označene korake, puščice in primere izhodov orodij, ki ponazarjajo cikel sklepanja agenta.

To pomeni, da se z rastjo pogovora povečuje tudi dolžina poziva, ki se uporablja za vzorčenje modela. Ta dolžina je pomembna, ker ima vsak model kontekstno okno, kar je največje število žetonov, ki jih lahko uporabi za en klic sklepanja. Upoštevajte, da to okno vključuje tako vhodne kot izhodne žetone. Kot si lahko predstavljate, se lahko agent v enem samem koraku odloči za več sto priklicev orodij, kar lahko privede do izčrpanja kontekstnega okna. Zaradi tega je upravljanje kontekstnega okna ena izmed številnih odgovornosti agenta. Zdaj si oglejmo, kako Codex izvaja zanko agenta.

Inferenca modela

Codex CLI pošilja HTTP zahteve na Responses API(odpre se v novem oknu) za izvajanje sklepanja modela. V nadaljevanju bomo prikazali, kako informacije tečejo skozi Codex, ki za poganjanje zanke agenta uporablja Responses API.

Končna točka Responses API, ki jo uporablja Codex CLI, je nastavljiva(odpre se v novem oknu), zato jo je mogoče uporabiti s katero koli končno točko, ki implementira Responses API(odpre se v novem oknu):

Raziščimo, kako Codex ustvari poziv za prvi sklepni klic v pogovoru.

Ustvarjanje začetnega poziva

Kot končni uporabnik ne določite poziva, uporabljenega za dobesedno vzorčenje modela, ko poizvedujete po API-ju Responses. Namesto tega določite različne vrste vnosa kot del svoje poizvedbe, strežnik API za odgovore pa se odloči, kako te informacije strukturirati v poziv, ki ga je model zasnovan za uporabo. Na poziv lahko gledate kot na »seznam elementov«; ta razdelek bo pojasnil, kako se vaša poizvedba pretvori v ta seznam.

V začetnem pozivu je vsaka postavka na seznamu povezana z določeno vlogo. Vloga označuje, koliko teže naj bi imela povezana vsebina, in je ena od naslednjih vrednosti (v padajočem vrstnem redu prioritete): system, developer, user, assistant.

Responses API(odpre se v novem oknu) sprejme JSON obremenitev z mnogimi parametri. Osredotočili se bomo na te tri:

V Codexu se polje instructions prebere iz model_instructions_file(odpre se v novem oknu) v ~/.codex/config.toml, če je določeno; sicer se uporabijo base_instructions, povezane z modelom(odpre se v novem oknu). Navodila, specifična za model, se nahajajo v repozitoriju Codex in so vključena v CLI (npr. gpt-5.2-codex_prompt.md(odpre se v novem oknu)).

Polje tools je seznam definicij orodij, ki ustrezajo shemi, ki jo določa Responses API. Za Codex to vključuje orodja, ki jih zagotavlja Codex CLI, orodja, ki jih zagotavlja Responses API, ki bi morala biti na voljo za Codex, ter orodja, ki jih zagotovi uporabnik, običajno prek strežnikov MCP:

JavaScript

1
[
2
// Codex's default shell tool for spawning new processes locally.
3
{
4
"type": "function",
5
"name": "shell",
6
"description": "Runs a shell command and returns its output...",
7
"strict": false,
8
"parameters": {
9
"type": "object",
10
"properties": {
11
"command": {"type": "array", "description": "The command to execute", ...},
12
"workdir": {"description": "The working directory...", ...},
13
"timeout_ms": {"description": "The timeout for the command...", ...},
14
...
15
},
16
"required": ["command"],
17
}
18
}
19

20
// Codex's built-in plan tool.
21
{
22
"type": "function",
23
"name": "update_plan",
24
"description": "Updates the task plan...",
25
"strict": false,
26
"parameters": {
27
"type": "object",
28
"properties": {"plan":..., "explanation":...},
29
"required": ["plan"]
30
}
31
},
32

33
// Web search tool provided by the Responses API.
34
{
35
"type": "web_search",
36
"external_web_access": false
37
},
38

39
// MCP server for getting weather as configured in the
40
// user's ~/.codex/config.toml.
41
{
42
"type": "function",
43
"name": "mcp__weather__get-forecast",
44
"description": "Get weather alerts for a US state",
45
"strict": false,
46
"parameters": {
47
"type": "object",
48
"properties": {"latitude": {...}, "longitude": {...}},
49
"required": ["latitude", "longitude"]
50
}
51
}
52
]

Nazadnje je polje input v JSON tovoru seznam elementov. Codex vstavi naslednje elemente(odpre se v novem oknu) v input pred dodajanjem uporabniškega sporočila:

1. Sporočilo z role=developer, ki opisuje peskovnik, ki velja samo za Codex-om zagotovljeno shell orodje, opredeljeno v razdelku tools. To pomeni, da druga orodja, kot so tista, ki jih zagotavljajo strežniki MCP, niso v peskovniku Codex in so odgovorna za uveljavljanje svojih lastnih varovalk.

Sporočilo je zgrajeno iz predloge, kjer ključni deli vsebine izvirajo iz izrezkov Markdowna, vključenih v Codex CLI, kot sta workspace_write.md(odpre se v novem oknu) in on_request.md(odpre se v novem oknu):

Navadno besedilo

1
<permissions instructions>
2
- description of the sandbox explaining file permissions and network access
3
- instructions for when to ask the user for permissions to run a shell command
4
- list of folders writable by Codex, if any
5
</permissions instructions>

2. (Neobvezno) Sporočilo z role=developer, katerega vsebina je vrednost developer_instructions, prebrana iz uporabnikove datoteke config.toml.

3. (Neobvezno) Sporočilo z role=user, katerega vsebina so »uporabniška navodila«, ki ne izvirajo iz ene same datoteke, temveč so zbrana iz več virov(odpre se v novem oknu). Na splošno se podrobnejša navodila pojavijo pozneje:

4. Sporočilo z role=user, ki opisuje lokalno okolje, v katerem agent trenutno deluje. To določa trenutni delovni imenik in uporabnikovo lupino(odpre se v novem oknu):

Navadno besedilo

1
<environment_context>
2
<cwd>/Users/mbolin/code/codex5</cwd>
3
<shell>zsh</shell>
4
</environment_context>

Ko Codex opravi vse zgornje izračune za inicializacijo input, doda uporabniško sporočilo za začetek pogovora.

Prejšnji primeri so se osredotočali na vsebino vsakega sporočila, vendar upoštevajte, da je vsak element input JSON objekt s type, role(odpre se v novem oknu) in content, kot sledi:

JSON

1
{
2
"type": "message",
3
"role": "user",
4
"content": [
5
{
6
"type": "input_text",
7
"text": "Add an architecture diagram to the README.md"
8
}
9
]
10
}

Ko Codex sestavi celoten JSON tovor za pošiljanje v Responses API, nato izvede HTTP POST zahtevo z glavo Authorization, odvisno od tega, kako je končna točka Responses API konfigurirana v ~/.codex/config.toml (dodatne HTTP glave in parametri poizvedbe se dodajo, če so navedeni).

Ko strežnik OpenAI Responses API prejme zahtevo, uporabi JSON za izpeljavo poziva za model, kot sledi (za vsak primer, implementacija Responses API po meri bi se lahko odločila drugače):

Posnetek diagrama, ki prikazuje en sam korak v zanki agenta AI. Zahteva uporabnika vstopi v model, ki ustvari misel, dejanje z imenom orodja in vnos za orodje. Diagram poudarja ta vmesni korak sklepanja, preden se orodje prikliče.

Kot lahko vidite, vrstni red prvih treh elementov v pozivu določa strežnik, ne odjemalec. Kljub temu je od teh treh elementov samo vsebina sistemskega sporočila tudi pod nadzorom strežnika, saj orodja in navodila določa odjemalec. Temu sledi input iz JSON obremenitve za dokončanje poziva.

Zdaj, ko imamo naš poziv, smo pripravljeni vzorčiti model.

Prvi zavoj

Ta zahteva HTTP za Responses API sproži prvi “korak” pogovora v Codexu. Strežnik odgovori s tokom dogodkov, poslanih s strežnika (SSE(odpre se v novem oknu)). data vsakega dogodka je JSON-podatkovni tovor z "type", ki se začne z "response", kar bi lahko bilo na primer takole (celoten seznam dogodkov je na voljo v naši API dokumentaciji(odpre se v novem oknu)):

Navadno besedilo

1
data: {"type":"response.reasoning_summary_text.delta","delta":"ah ", ...}
2
data: {"type":"response.reasoning_summary_text.delta","delta":"ha!", ...}
3
data: {"type":"response.reasoning_summary_text.done", "item_id":...}
4
data: {"type":"response.output_item.added", "item":{...}}
5
data: {"type":"response.output_text.delta", "delta":"forty-", ...}
6
data: {"type":"response.output_text.delta", "delta":"two!", ...}
7
data: {"type":"response.completed","response":{...}}

Codex porablja tok dogodkov(odpre se v novem oknu) in jih ponovno objavi kot interne objekte dogodkov, ki jih lahko uporabi naročnik. Dogodki, kot je response.output_text.delta, se uporabljajo za podporo pretakanju v uporabniškem vmesniku, medtem ko se drugi dogodki, kot je response.output_item.added, pretvorijo v objekte, ki se dodajo v input za nadaljnje klice API-ja Responses.

Predpostavimo, da prva zahteva za Responses API vključuje dva dogodka response.output_item.done: enega z type=reasoning in enega z type=function_call. Ti dogodki morajo biti predstavljeni v polju input v JSON-u, ko model ponovno poizvedujemo z odzivom na klic orodja: 

JavaScript

1
[
2
/* ... original 5 items from the input array ... */
3
{
4
"type": "reasoning",
5
"summary": [
6
"type": "summary_text",
7
"text": "**Adding an architecture diagram for README.md**\n\nI need to..."
8
],
9
"encrypted_content": "gAAAAABpaDWNMxMeLw..."
10
},
11
{
12
"type": "function_call",
13
"name": "shell",
14
"arguments": "{\"command\":\"cat README.md\",\"workdir\":\"/Users/mbolin/code/codex5\"}",
15
"call_id": "call_8675309..."
16
},
17
{
18
"type": "function_call_output",
19
"call_id": "call_8675309...",
20
"output": "<p align=\"center\"><code>npm i -g @openai/codex</code>..."
21
}
22
]

Rezultirajoči poziv, uporabljen za vzorčenje modela kot del nadaljnje poizvedbe, bi izgledal takole:

Diagram z oznako »Snapshot 2« prikazuje agenta UI po priklicu orodja. Model prejme opažanje orodja ter ustvari nov premislek in novo dejanje. Puščice povezujejo vhode, opažanja in izhode ter ponazarjajo, kako agent iterira svojo zanko sklepanja.

Zlasti bodite pozorni na to, kako je stari poziv natančna predpona novega poziva. To je namerno, saj to naredi nadaljnje zahteve veliko učinkovitejše, ker nam omogoča, da izkoristimo predpomnjenje pozivov (o čemer bomo razpravljali v naslednjem razdelku o zmogljivosti).

Ko se ozremo nazaj na naš prvi diagram zanke agenta, opazimo, da bi lahko bilo veliko iteracij med sklepanjem in klicanjem orodij. Poziv se lahko še naprej povečuje, dokler končno ne prejmemo sporočila asistenta, ki označuje konec izmenjave:

Navadno besedilo

1
data: {"type":"response.output_text.done","text": "I added a diagram to explain...", ...}
2
data: {"type":"response.completed","response":{...}}

V Codex CLI uporabniku prikažemo sporočilo asistenta in usmerimo urejevalnik sporočil tako, da uporabniku nakaže, da je zdaj na vrsti za nadaljevanje pogovora. Če se uporabnik odzove, je treba tako sporočilo asistenta iz prejšnje izmenjave kot tudi uporabnikovo novo sporočilo dodati v input (vhod) v zahtevi API za odgovore, da se začne nova izmenjava:

JavaScript

1
[
2
/* ... all items from the last Responses API request ... */
3
{
4
"type": "message",
5
"role": "assistant",
6
"content": [
7
{
8
"type": "output_text",
9
"text": "I added a diagram to explain the client/server architecture."
10
}
11
]
12
},
13
{
14
"type": "message",
15
"role": "user",
16
"content": [
17
{
18
"type": "input_text",
19
"text": "That's not bad, but the diagram is missing the bike shed."
20
}
21
]
22
}
23
]

Še enkrat, ker nadaljujemo pogovor, se dolžina za input, ki ga pošljemo v API za odgovore, še naprej povečuje:

Diagram z oznako »Snapshot 3« prikazuje končno fazo zanke agenta UI. Po prejemu rezultatov orodij model ustvari zaključni premislek in končni odgovor, ki se vrne uporabniku. Puščice ponazarjajo prehod od izhoda orodja do zaključenega odziva.

Poglejmo, kaj ta vedno večji poziv pomeni za zmogljivost.

Vidiki delovanja

Morda se sprašujete: »Ali ni zanka agenta kvadratna glede na količino podatkov JSON, ki se med pogovorom pošiljajo v Responses API?« Odgovor bi bil pritrdilen. Čeprav API Responses podpira izbirni parameter previous_response_id(odpre se v novem oknu) za ublažitev te težave, ga Codex danes ne uporablja, predvsem zato, da ohrani zahteve popolnoma brez stanja in da podpira konfiguracije ničelne hrambe podatkov (ZDR).

Izogibanje previous_response_id poenostavi stvari za ponudnika Responses API, ker zagotavlja, da je vsaka zahteva brez stanja. To tudi olajša podporo strankam, ki so se odločile za ničelno hrambo podatkov (ZDR)(odpre se v novem oknu), saj bi bilo shranjevanje podatkov, potrebnih za podporo previous_response_id, v nasprotju z ZDR. Upoštevajte, da stranke ZDR ne žrtvujejo zmožnosti, da bi imele koristi od lastniških sporočil o sklepanju iz prejšnjih potez, saj je povezano encrypted_content mogoče dešifrirati na strežniku. (OpenAI hrani dešifrirni ključ stranke ZDR, vendar ne njenih podatkov.) Oglejte si zahtevke pridružitve sprememb #642(odpre se v novem oknu) in #1641(odpre se v novem oknu) za povezane spremembe v Codexu za podporo ZDR.

Na splošno strošek vzorčenja modela prevlada nad stroškom omrežnega prometa, zato je prav vzorčenje glavni cilj naših prizadevanj za učinkovitost. Zato je predpomnjenje pozivov tako pomembno, saj nam omogoča ponovno uporabo izračunov iz prejšnjega klica inference. Ko dobimo zadetke predpomnilnika, je vzorčenje modela linearno namesto kvadratnega. Naša dokumentacija o predpomnjenju pozivov (odpre se v novem oknu)to podrobneje pojasnjuje:

Zadetki v predpomnilniku so mogoči le pri natančnih ujemanjih predpone v pozivu. Da bi dosegli koristi predpomnjenja, je treba statično vsebino, kot so navodila in primeri, postaviti na začetek poziva, spremenljivo vsebino, kot so uporabniško specifične informacije, pa na konec. To velja tudi za slike in orodja, ki morajo biti med zahtevami enaki.

S tem v mislih razmislimo, katere vrste operacij bi lahko povzročile »zgrešitev predpomnilnika« v Codexu:

  • Spreminjanje orodij, ki so na voljo modelu, med pogovorom.
  • Spreminjanje modela, ki je cilj zahteve Responses API (v praksi to spremeni tretji element v izvirnem pozivu, saj vsebuje navodila, specifična za model).
  • Spreminjanje konfiguracije peskovnika, načina odobritve ali trenutnega delovnega imenika.

Ekipa Codex mora biti pri uvajanju novih funkcionalnosti v Codex CLI zelo previdna, saj lahko te ogrozijo predpomnjenje pozivov. Kot primer je naša začetna podpora za orodja MCP uvedla napako, pri kateri nismo uspeli našteti orodij v doslednem vrstnem redu(odpre se v novem oknu), kar je povzročalo zgrešene zadetke predpomnilnika. Upoštevajte, da so orodja MCP lahko še posebej zahtevna, ker lahko strežniki MCP sproti spreminjajo seznam orodij, ki jih zagotavljajo, prek obvestila notifications/tools/list_changed(odpre se v novem oknu). Upoštevanje takega obvestila sredi dolgega pogovora lahko povzroči drago zgrešitev predpomnilnika.

Kadar je mogoče, spremembe konfiguracije, ki se zgodijo sredi pogovora, obravnavamo tako, da novo sporočilo dodamo k input, da odraža spremembo, namesto da bi spreminjali prejšnje sporočilo:

  • Če se konfiguracija peskovnika ali način odobritve spremeni, vstavimo(odpre se v novem oknu) novo sporočilo role=developer v enaki obliki kot izvirni element <permissions instructions>.
  • Če se trenutni delovni imenik spremeni, vstavimo(odpre se v novem oknu) novo sporočilo role=user z enakim formatom kot izvirni <environment_context>.

Zelo se trudimo, da zagotovimo zadetke predpomnilnika za boljšo učinkovitost. Obstaja še en ključni vir, ki ga moramo upravljati: okno za kontekst.

Naša splošna strategija, da se izognemo temu, da bi nam zmanjkalo okna konteksta, je, da pogovor zbije, ko število žetonov preseže določen prag. Natančneje, input zamenjamo z novim, manjšim seznamom elementov, ki je reprezentativen za pogovor, kar agentu omogoča, da nadaljuje z razumevanjem dogajanja do tega trenutka. Zgodnja implementacija kompakcije(odpre se v novem oknu) je od uporabnika zahtevala, da ročno sproži ukaz /compact, ki bi poizvedel Responses API z uporabo obstoječega pogovora in prilagojenih navodil za povzetek(odpre se v novem oknu). Codex je uporabil nastalo sporočilo asistenta, ki je vsebovalo povzetek kot nov vnos(odpre se v novem oknu) za nadaljnje korake pogovora.

Od takrat se je Responses API razvil, da podpira posebno /responses/compact končno točko(odpre se v novem oknu), ki izvaja zgoščevanje bolj učinkovito. Vrne seznam elementov(odpre se v novem oknu), ki jih je mogoče uporabiti namesto prejšnjega input za nadaljevanje pogovora, hkrati pa sprosti okno konteksta. Ta seznam vključuje poseben element type=compaction z neprozornim elementom encrypted_content, ki ohranja latentno razumevanje modela o izvirnem pogovoru. Zdaj Codex samodejno uporablja to končno točko za stiskanje pogovora, ko je presežena auto_compact_limit(odpre se v novem oknu).

Kaj sledi

Predstavili smo zanko agenta Codex in pojasnili, kako Codex pri poizvedovanju modela oblikuje in upravlja svoj kontekst. Ob tem smo izpostavili praktične vidike in najboljše prakse, ki veljajo za vsakogar, ki gradi zanko agenta na podlagi Responses API.

Čeprav zanka agenta predstavlja temelj Codexa, je to šele začetek. V prihodnjih prispevkih se bomo poglobili v arhitekturo CLI, raziskali, kako je udejanjena uporaba orodij, in si podrobneje ogledali model peskovniškega delovanja v Codexu.

Avtor

Michael Bolin

Zahvala

Posebna zahvala celotni ekipi, ki je razvila Codex CLI.