Înapoi la catalog
Season 6 18 Episoade 1h 10m 2026

OpenAI Agents SDK

Ediția v0.13 — 2026. Un ghid complet pentru construirea sistemelor multi-agent pregătite pentru producție cu OpenAI Agents SDK pentru Python (v0.13 - 2026). Învață primitivele de bază, tiparele de orchestrare, tools, handoffs, guardrails, gestionarea stării, MCP și integrarea vocală realtime.

Framework-uri AI/ML Sisteme multi-agent
OpenAI Agents SDK
Se redă acum
Click play to start
0:00
0:00
1
Dincolo de Swarm: Primitivele de bază
Descoperă conceptele fundamentale ale OpenAI Agents SDK. Acest episod acoperă motivul existenței acestui SDK, cum îmbunătățește Swarm și principiile de bază de design care prioritizează abstracțiile minime.
3m 39s
2
Definirea obiectului Agent și a Run Loop-ului
Învață cum să configurezi obiectul fundamental Agent. Explorăm instrucțiunile, setările modelului și cum să forțezi generarea de output-uri de date structurate fără probleme.
3m 38s
3
Echiparea agenților cu Python Function Tools
Oferă agenților tăi capacitatea de a acționa transformând funcțiile Python standard în instrumente executabile. Înțelege generarea automată de scheme și inferența tipurilor.
4m 07s
4
Scalarea suprafețelor de instrumente cu Hosted Tool Search
Învață cum să gestionezi biblioteci masive de instrumente fără a-ți epuiza bugetul de tokeni. Acoperim încărcarea amânată, namespaces și execuția instrumentelor prin Hosted Tool Search.
3m 44s
5
Delegarea descentralizată: Tiparul Handoff
Stăpânește arta orchestrării multi-agent folosind tiparul Handoff. Descoperă cum să creezi agenți de triaj care deleagă fără probleme controlul complet către sub-agenți specializați.
3m 36s
6
Orchestrarea centralizată: Agents as Tools
Păstrează controlul conversației într-un singur loc folosind tiparul Agents as Tools. Discutăm despre cum un agent manager poate sintetiza răspunsurile de la mai mulți sub-agenți specialiști.
4m 00s
7
Modelarea contextului cu Handoff Inputs și Filters
Optimizează utilizarea tokenilor în sistemele multi-agent modificând istoricul conversațiilor între handoffs. Învață cum să injectezi metadate și să aplici filtre pe transcrieri.
4m 08s
8
Controlul stării: to_input_list și Server IDs
O analiză detaliată a gestionării manuale a conversațiilor. Înțelege metodele de cel mai jos nivel pentru păstrarea contextului între rânduri și utilizarea Server IDs.
4m 06s
9
Automatizarea memoriei cu Sessions încorporate
Simplifică-ți buclele de chat cu sistemul de memorie încorporat al SDK-ului. Explorăm SQLiteSession, OpenAIConversationsSession și persistența automată.
4m 03s
10
Protejarea fluxurilor de lucru: Input și Output Guardrails
Securizează-ți pipeline-urile AI prin capturarea inputurilor malițioase înainte ca acestea să ajungă la modelele costisitoare. Acoperim guardrails la nivel de agent și execuția paralelă versus blocantă.
4m 04s
11
Validarea acțiunilor: Tool-Level Guardrails
Previne scurgerile critice de date la nivel de funcție. Învață cum să încapsulezi instrumente specifice cu input și output guardrails precise.
4m 17s
12
Pauzarea execuției: Human-in-the-Loop și RunState
Implementează măsuri de siguranță pentru acțiunile ireversibile prin impunerea aprobărilor de tip Human-in-the-Loop. Explorăm pipeline-ul de serializare RunState pentru pauzarea și reluarea sarcinilor de lucru.
3m 27s
13
Injectarea dependențelor locale cu RunContextWrapper
Stăpânește injectarea dependențelor în fluxurile agenților tăi. Învață cum să transmiți în siguranță stările locale și conexiunile la baza de date către instrumente, fără a le scurge către LLM.
3m 56s
14
USB-C-ul pentru AI: Introducere în MCP
O introducere în Model Context Protocol (MCP). Descoperă cum acest standard acționează ca un conector universal pentru a lega cu ușurință agenții AI de platformele SaaS.
3m 47s
15
Conectarea serverelor MCP locale prin Stdio și HTTP
Aprofundează MCP rulând servere locale standard. Învață să izolezi accesul la sistemul de fișiere și la instrumentele interne în siguranță cu MCPServerStdio.
3m 46s
16
Vizualizarea fluxurilor de lucru cu Tracing încorporat
Elimină depanarea cu instrucțiuni print folosind observabilitatea încorporată în SDK. Descoperă cum span-urile și trace-urile automate leagă fluxuri de lucru complexe în întregime.
4m 03s
17
Voce cu latență redusă folosind Realtime Agents
Rupe paradigma standard de tip cerere-răspuns. Vezi cum Realtime Agents mențin conexiuni WebSocket live pentru a gestiona întreruperile și raționamentul multimodal.
4m 12s
18
Construirea de interfețe reactive cu Streaming Events
Treci dincolo de streaming-ul de tokeni de text. Utilizează Semantic Streaming Events pentru a construi interfețe frontend ultra-responsive care reacționează la acțiunile agenților în timp real.
3m 46s

Episoade

1

Dincolo de Swarm: Primitivele de bază

3m 39s

Descoperă conceptele fundamentale ale OpenAI Agents SDK. Acest episod acoperă motivul existenței acestui SDK, cum îmbunătățește Swarm și principiile de bază de design care prioritizează abstracțiile minime.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 1 din 18. Majoritatea framework-urilor de agenți AI te obligă să înveți o duzină de noi abstracțiuni, sintaxă custom și ierarhii complexe de obiecte. Petreci mai mult timp luptându-te cu framework-ul decât scriind logica aplicației tale. Astăzi, vorbim despre Beyond Swarm: Primitivele de bază. Când dezvoltatorii aud despre un nou agent framework, se așteaptă adesea la un ecosistem masiv cu o curbă de învățare abruptă. SDK-ul OpenAI Agents este exact opusul. Este o evoluție a library-ului experimental Swarm. Swarm a dovedit că poți construi interacțiuni complexe cu concepte foarte simple. SDK-ul Agents preia această filozofie și o consolidează pentru utilizarea în producție. Este în mod deliberat lightweight și complet Python-first. Arhitectura se bazează pe două principii fundamentale de design: expunerea a foarte puține primitive de bază și menținerea execuției extrem de personalizabile. Nu ai nevoie de un graf complex de noduri sau de un limbaj declarativ proprietar pentru a construi un agent aici. SDK-ul îți oferă un set mic de building blocks. Piesa fundamentală este obiectul Agent. Definești un Agent oferindu-i un nume și un set de instrucțiuni. Dacă vrei să construiești un simplu tutor de istorie, instanțiezi un Agent, îl numești HistoryTutor și îi pasezi un string de text care îl instruiește să predea evenimente istorice clar și precis. Aceasta este întreaga configurație a agentului tău. Nu există niciun state ascuns și nicio inițializare complicată. Dar un agent în sine este doar o structură de date statică. Nu face nimic până nu este executat. Aici devine interesant. Execuția este gestionată în întregime de o componentă separată numită Runner. Runner-ul gestionează bucla completă de interacțiune dintre codul tău local și API-ul OpenAI remote. Într-o aplicație tipică, ar trebui să scrii un while-loop custom pentru a verifica dacă modelul vrea să facă un tool call, să faci parse la răspuns, să execuți tool-ul și să trimiți rezultatul înapoi. Runner-ul abstractizează toate astea. Pentru a începe procesul, pasezi agentul HistoryTutor și prompt-ul utilizatorului în metoda run. Runner-ul preia controlul de acolo. Trimite prompt-ul către model. Dacă modelul decide că trebuie să caute o anumită dată istorică, va solicita un tool call. Runner-ul pune pauză, execută funcția Python locală pe care ai furnizat-o pentru acel tool, capturează valoarea returnată și o trimite direct înapoi modelului. Repetă acest ciclu automat. Redă controlul aplicației tale doar atunci când modelul determină că task-ul este finalizat și generează un răspuns text final. Această separare strictă între definiția statică a Agentului și execuția activă a Runner-ului este ceea ce face ca SDK-ul să fie atât de personalizabil. Deoarece tool-urile sunt doar funcții Python standard cu type hints obișnuite, iar agentul este doar un obiect simplu, menții controlul total asupra fluxului aplicației tale. Poți injecta cu ușurință custom logging, metrici sau error handling în jurul Runner-ului, fără a suprascrie clase profunde din framework. Doar scrii Python. Adevărata valoare a acestui SDK nu constă în ceea ce adaugă, ci în ceea ce elimină — îți iese din cale și îți permite să orchestrezi modele de limbaj folosind cod simplu, lizibil. Dacă vrei să ajuți la susținerea emisiunii, poți căuta DevStoriesEU pe Patreon. Cam atât pentru acest episod. Pe curând!
2

Definirea obiectului Agent și a Run Loop-ului

3m 38s

Învață cum să configurezi obiectul fundamental Agent. Explorăm instrucțiunile, setările modelului și cum să forțezi generarea de output-uri de date structurate fără probleme.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 2 din 18. Ce-ar fi dacă ai putea forța modelul tău de limbaj să răspundă întotdeauna într-o structură de date perfect parsată, fără să scrii nicio linie de regex complex? Astăzi discutăm despre definirea unui Agent și despre Run Loop, exact modul prin care obții acel control strict. O confuzie frecventă când începi să folosești acest SDK este să crezi că un agent este un proces activ, care rulează. Nu este. În această arhitectură, obiectul Agent este strict un container de configurare. El încapsulează un anumit model de limbaj într-un context predefinit. Nu se execută singur și nu are state propriu. Pur și simplu construiești un blueprint. Pentru a defini acest blueprint, instanțiezi un Agent. Începi cu parametrul instructions. Acesta este system prompt-ul tău de bază, unde definești persona, limitele și regulile specifice pe care modelul trebuie să le urmeze. Apoi, oferi setările modelului. Asta dictează ce model de bază să fie folosit și configurează detaliile standard de inference. În această etapă, agentul tău este complet definit, dar complet inactiv în memorie. Aici devine interesant. Poți constrânge fizic forma răspunsului dat de agent folosind parametrul output type. Imaginează-ți că construiești un tool pentru a extrage evenimente de calendar din thread-uri de email dezordonate. În loc să scrii instrucțiuni prin care implori modelul să formateze corect datele, definești o structură de date concretă în codul tău. Definești o clasă Calendar Event cu câmpuri stricte pentru titlu, ora de început și locație. Pasezi această clasă în parametrul output type al Agent-ului tău. Configurat în acest fel, API-ul impune schema. Agentul nu poate returna un răspuns text conversațional. Va returna întotdeauna doar un obiect Calendar Event validat, pe care codul aplicației tale îl poate procesa imediat. Acum ai un blueprint de agent strict și bine configurat. Pentru a-l pune efectiv la treabă, ai nevoie de Run Loop. Deoarece agentul este doar o definiție statică, execuția este gestionată în întregime de o componentă Runner separată. Runner-ul este motorul. Pasezi definiția agentului și input-ul utilizatorului către Runner, iar acesta preia execuția. Când declanșezi Runner-ul, acesta intră într-un execution loop. El grupează instrucțiunile agentului, schema strictă de output și prompt-ul utilizatorului, apoi le trimite către model. Run Loop-ul este responsabil pentru gestionarea întregii orchestrări back-and-forth. Dacă modelul decide că trebuie să apeleze un tool extern pentru a aduce datele lipsă, Runner-ul interceptează acea cerere, rulează codul tool-ului local și trimite rezultatul înapoi la model. Acesta gestionează automat toți acești pași intermediari. Loop-ul se termină doar atunci când modelul rezolvă prompt-ul și produce output-ul final care corespunde exact output type-ului tău de calendar. Menținerea configurației statice a agentului complet separată de Run Loop-ul activ este ceea ce îți permite să reutilizezi în siguranță exact același agent de extragere de calendar în mii de execuții simultane, fără niciun data bleeding. Mulțumesc pentru audiție, happy coding tuturor!
3

Echiparea agenților cu Python Function Tools

4m 07s

Oferă agenților tăi capacitatea de a acționa transformând funcțiile Python standard în instrumente executabile. Înțelege generarea automată de scheme și inferența tipurilor.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 3 din 18. Scrierea manuală de JSON schemas pentru tool-urile de language model este migăloasă și fragilă. O paranteză lipsă sau un type nepotrivit, și modelul nu mai reușește să înțeleagă cum să interacționeze cu sistemul tău. În loc să scrii manual aceste definiții, poți pur și simplu să scrii Python standard și să lași framework-ul să facă traducerea. Exact asta acoperim astăzi: Echiparea agenților cu Python Function Tools. O concepție greșită des întâlnită este că expunerea logicii locale către un agent necesită menținerea a două sources of truth. Lumea presupune că are nevoie de codul Python propriu-zis, plus un fișier de configurare JSON separat și complex, care să descrie acel cod către language model. Cu Agents SDK, ocolești complet scrierea manuală de JSON. Pur și simplu scrii o funcție Python standard și pui decoratorul de function tool direct deasupra ei. Când aplici acel decorator, SDK-ul începe să lucreze under the hood folosind modulul built-in inspect din Python și Pydantic. Acesta scanează semnătura funcției tale. Citește numele parametrilor, extrage type hint-urile și preia docstring-ul funcției. Din aceste elemente, generează automat o JSON schema strictă și o atașează agentului. Să ne uităm la un scenariu concret. Vrei să-i oferi agentului tău o funcție numită fetch weather. Această funcție are nevoie de date geografice precise pentru a funcționa. În loc să lași modelul să ghicească ce format de string să folosească, definești o structură specifică. Creezi un custom type, poate un Typed Dictionary numit Location, care conține câmpuri string distincte pentru city și country. Apoi folosești acest type Location ca type hint strict pentru parametrul de input din funcția ta fetch weather. Iată ideea cheie. Trebuie să adaugi un docstring clar la această funcție. Poți scrie o propoziție simplă care să precizeze că acest tool preia condițiile meteo actuale pentru un anumit oraș și o anumită țară. Framework-ul extrage acest text și îl folosește ca descriere principală a tool-ului în prompt. Docstring-ul tău nu mai este doar o notă utilă pentru colegii tăi developeri. Este manualul de instrucțiuni propriu-zis pe care agentul îl evaluează pentru a decide dacă ar trebui să declanșeze tool-ul. Dacă un utilizator întreabă dacă are nevoie de o geacă în Tokyo, agentul analizează tool-urile disponibile. Citește docstring-ul tău, își dă seama că funcția fetch weather oferă răspunsul și structurează un request. Pentru că ai pus type hint pe input cu dicționarul tău Location, Pydantic garantează că output-ul agentului se potrivește exact cu câmpurile obligatorii înainte măcar ca logica ta Python să se execute. Dacă modelul încearcă să paseze un singur string de text în loc de dicționar, framework-ul prinde eroarea și forțează agentul să încerce din nou cu structura corectă. SDK-ul execută funcția local, capturează valoarea returnată și trimite rezultatul direct înapoi în reasoning loop-ul agentului. Type hint-urile și docstring-urile tale standard din Python nu mai sunt o documentație pasivă; ele formează contractul API activ și obligatoriu pe care se bazează agentul tău pentru a interacționa cu lumea reală. Îți mulțumesc că ai petrecut câteva minute cu mine. Până data viitoare, numai bine.
4

Scalarea suprafețelor de instrumente cu Hosted Tool Search

3m 44s

Învață cum să gestionezi biblioteci masive de instrumente fără a-ți epuiza bugetul de tokeni. Acoperim încărcarea amânată, namespaces și execuția instrumentelor prin Hosted Tool Search.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 4 din 18. Să pasezi o sută de tools unui language model distruge performanța și îți consumă bugetul de token-uri înainte să se execute vreo acțiune. Nu poți să înghesui fiecare enterprise API schema în context window-ul inițial și să te aștepți la un reasoning bun. Soluția pentru asta este scalarea tool surface-urilor cu Hosted Tool Search. Înainte să ne uităm la scalare, trebuie să definim ce sunt hosted tools. Hosted tools se execută nativ pe infrastructura OpenAI, în loc să ruleze pe mașina ta locală. Exemplele built-in includ Web Search Tool și File Search Tool. Nu tu scrii logica de execuție, nu gestionezi web crawler-ul și nu construiești mecanismul de file chunking pentru ele. Le atașezi la agentul tău, iar backend-ul OpenAI se ocupă de munca propriu-zisă. Dar conceptul de hosted tools se extinde și la modul în care modelul îți descoperă propriile custom tools atunci când ai prea multe. Gândește-te la un agent de CRM. Ai putea avea cincizeci de tools distincte pentru verificarea statusului comenzii, extragerea istoricului de billing, actualizarea adreselor de shipping și preluarea de support logs. Dacă pasezi toate cele cincizeci de schemas upfront, copleșești modelul și irosești input tokens. Mulți developeri cred că trebuie să rezolve asta construind un pas de retrieval pe client-side. Ei presupun că trebuie să intercepteze user prompt-ul, să caute într-un vector database local acele tool schemas relevante și să le injecteze dinamic în prompt înainte să apeleze language model-ul. Nu e nevoie să faci asta. Hosted tool search are loc nativ pe serverele OpenAI folosind Responses API. Modelul în sine este capabil să caute în tool surface-ul disponibil fără ca acel client code al tău să acționeze ca intermediar. Obții asta folosind doi parametri: tool namespace și defer loading. Când îți înregistrezi acele CRM tools, grupezi funcțiile similare atribuindu-le unui namespace comun. De exemplu, ai putea plasa toate acele tools de customer profile într-un namespace numit customer account. Apoi, setezi parametrul defer loading pe true pentru acele tools. Asta e partea care contează. Când defer loading este activ, agentul nu trimite acele tool schemas individuale către language model la începutul conversației. În schimb, trimite o singură schema lightweight care reprezintă namespace-ul customer account în sine. Modelul este informat că acest namespace există și știe cum să îi facă un query dacă e nevoie. Când userul cere să caute un anumit customer ID, modelul își dă seama că are nevoie de mai multe informații. Execută un search nativ în namespace-ul customer account. Serverele OpenAI găsesc acel billing sau support tool relevant, încarcă doar acea tool schema specifică în model context, iar apoi modelul execută acel tool call. Asta decuplează complet dimensiunea tool library-ului tău de costul upfront de token-uri. Ai putea atașa sute de tools unui singur agent, iar promptul inițial rămâne minuscul. Modelul suportă prețul în token-uri doar pentru acele tool schemas specifice pe care decide activ să le aducă la runtime. Făcând defer loading, schimbi o povară masivă de context static pe un mecanism de retrieval dinamic și precis. Asta e tot pentru episodul ăsta. Ne auzim data viitoare!
5

Delegarea descentralizată: Tiparul Handoff

3m 36s

Stăpânește arta orchestrării multi-agent folosind tiparul Handoff. Descoperă cum să creezi agenți de triaj care deleagă fără probleme controlul complet către sub-agenți specializați.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 5 din 18. Uneori, cea mai bună metodă pentru un manager de a gestiona o sarcină complexă este să se dea complet la o parte. Dacă agentul tău principal de rutare încearcă să medieze fiecare interacțiune dintre un utilizator și sistemele tale de backend, prompt-urile tale devin prea încărcate, iar execuția devine nesigură. Asta e exact problema pe care Decentralized Delegation, și mai precis Handoff Pattern, este conceput să o rezolve. Un handoff este un mecanism prin care un agent transferă controlul deplin al conversației către un alt agent. O greșeală comună este să confunzi un handoff cu un tool call standard. Ele sunt fundamental diferite. Când un agent apelează o funcție normală, el pune pauză, așteaptă să se întoarcă datele, și apoi formulează un răspuns pentru utilizator. Când un agent declanșează un handoff, el cedează complet rândul în conversație. Controlul trece complet la noul agent. Agentul original se dă complet la o parte. Asta contează pentru că îți menține arhitectura descentralizată. Dacă un agent central de triaj trebuie să proceseze output-ul fiecărei acțiuni a specialiștilor, system prompt-ul lui trebuie să fie enorm. Are nevoie de instrucțiuni despre cum să formuleze politicile de refund, troubleshooting-ul tehnic și ștergerea contului. Mai rău, agentul de triaj va încerca inevitabil să povestească utilizatorului ce a făcut specialistul. Asta irosește tokeni, adaugă latență și introduce un risc ridicat de halucinații. Handoff-urile previn asta lăsând specialistul să vorbească direct cu utilizatorul. Gândește-te la un sistem de customer support. Faci deploy la un agent general de triaj care să salute utilizatorii și să categorizeze cererile. Un client îți scrie și cere procesarea unui refund. Ai și un agent dedicat de refund, care este echipat cu tool-uri specifice de billing și instrucțiuni stricte despre politica de retur a companiei. Ca să îi conectezi folosind SDK-ul, scrii o funcție standard numită transfer to refund. Dar în loc să returneze un string sau date JSON, funcția asta returnează obiectul agentului tău de refund. Apoi, dai această funcție de transfer agentului tău de triaj, listând-o exact ca pe orice alt tool. Când clientul cere un refund, agentul de triaj decide să apeleze funcția de transfer. Aici e ideea de bază. Runner loop-ul din SDK execută funcția și vede că a fost returnat un obiect Agent în loc de date standard. Runner-ul schimbă instantaneu agentul activ din memorie. Ia istoricul conversației existente și îl trimite direct în agentul de refund nou activat. Agentul de refund preia rândul activ, procesează cererea utilizatorului, își declanșează propriile tool-uri de billing și îi răspunde direct utilizatorului. Poți, de asemenea, să transmiți date în timpul acestei tranziții. Dacă agentul de triaj i-a cerut deja utilizatorului numărul comenzii, poate transmite acel număr de comandă ca argument în funcția de transfer. Funcția poate apoi să injecteze acel număr de comandă în context variables ale noului agent înainte să îl returneze. Agentul de refund se trezește știind deja exact ce tranzacție să caute. Folosind handoff-uri, îți menții fiecare agent mic, concentrat și predictibil, lăsând conversația să curgă natural de la un expert nișat la altul. Asta e tot pentru acest episod. Mersi că m-ai ascultat și continuă să construiești!
6

Orchestrarea centralizată: Agents as Tools

4m 00s

Păstrează controlul conversației într-un singur loc folosind tiparul Agents as Tools. Discutăm despre cum un agent manager poate sintetiza răspunsurile de la mai mulți sub-agenți specialiști.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 6 din 18. Dacă asistentul tău AI trebuie să consulte trei departamente diferite înainte de a răspunde unui utilizator, rareori vrei ca utilizatorul să vorbească direct cu acele departamente. Vrei o singură voce consistentă care să gestioneze conversația, preluând informații silențios, în culise. Exact asta îți permite orchestrarea centralizată folosind agenți ca tools. Ai putea confunda asta cu handoffs, unde un agent transferă permanent utilizatorul către un alt agent. În cazul unui handoff, noul agent preia complet conversația. Cu orchestrarea centralizată, controlul nu este niciodată transferat. Agentul principal, care acționează de obicei ca manager, păstrează controlul absolut asupra conversației. Managerul este singura voce pe care utilizatorul o aude vreodată. Obții asta luând un agent complet configurat și transformându-l într-o funcție apelabilă. Fiecare obiect agent din SDK are o metodă numită as_tool. Când apelezi această metodă, ea face wrap la întregul agent, inclusiv la instrucțiunile lui specifice și la propriile lui tools, într-un format standard de tool. Apoi, oferi acest agent wrapped agentului tău manager, exact așa cum ai oferi o funcție Python standard. Hai să ne uităm la un scenariu practic. Construiești un portal de suport clienți. Creezi un agent specialist în rezervări. Singurul lui job este să facă query pe sistemele interne, să facă cross-reference la date și să returneze disponibilitatea. Acest agent este extrem de tehnic. Instrucțiunile lui sunt optimizate pentru acuratețea bazei de date, nu pentru o conversație politicoasă. Nu vrei ca utilizatorul să interacționeze cu acest specialist. Așa că, apelezi metoda as_tool pe specialistul în rezervări. Apoi, îți creezi agentul manager. Îi dai managerului instrucțiuni stricte să mențină un ton politicos, corporate, și să gestioneze relația cu utilizatorul. Apoi adaugi specialistul în rezervări wrapped în lista de tools a managerului. Când un utilizator îi cere managerului să verifice disponibilitatea pentru marțea viitoare, managerul procesează requestul. Recunoaște că îi lipsesc datele efective, dar știe că are un tool care le poate găsi. Managerul invocă tool-ul de rezervări. Aici e partea esențială. Când acel tool este invocat, agentul specialist în rezervări se trezește, își execută propriii pași interni izolați și produce un răspuns. Dar nu trimite acel răspuns utilizatorului. Returnează un rezultat raw, factual, direct înapoi la manager. Managerul primește aceste date, le sintetizează, le face wrap într-un salut corporate politicos și, în final, îi răspunde utilizatorului. Acest pattern hub-and-spoke rezolvă o problemă majoră a aplicațiilor complexe: context bloat. Agentul manager nu trebuie să cunoască schema bazei de date sau regulile pentru verificarea datelor. Își păstrează system prompt-ul curat, concentrându-se în întregime pe rutarea de requesturi și formatarea răspunsurilor. În același timp, agentului specialist nu trebuie să-i pese de istoricul conversației sau de brand voice. Își face doar jobul lui specific și returnează un rezultat. Când decizi între un handoff și un tool, întreabă-te cine deține răspunsul final. Dacă agentul specializat trebuie să intre într-un dialog prelungit de tip back-and-forth cu utilizatorul, vrei un handoff. Dar dacă agentul specializat este doar un procesor de date sofisticat care oferă un răspuns pe care asistentul principal să-l folosească, fă-i wrap ca tool și lasă managerul să dețină relația. Mersi că ai petrecut câteva minute cu mine. Până data viitoare, numai bine.
7

Modelarea contextului cu Handoff Inputs și Filters

4m 08s

Optimizează utilizarea tokenilor în sistemele multi-agent modificând istoricul conversațiilor între handoffs. Învață cum să injectezi metadate și să aplici filtre pe transcrieri.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 7 din 18. Atunci când transferi un client către un specialist uman, nu îl obligi să citească un transcript brut și masiv al fiecărei verificări automate de sistem care tocmai a avut loc. Îi oferi un motiv clar pentru transfer și un rezumat curat al problemei. Cu toate acestea, când developerii conectează agenți AI, deseori aruncă întregul chat log brut în context window-ul următorului agent. Astăzi, rezolvăm asta modelând contextul cu Handoff Inputs și Filters. Când un agent predă controlul altuia, are nevoie de o metodă prin care să comunice de ce are loc acest handoff. Faci asta folosind parametrul input type din rutina ta de handoff. Definești o schema, de obicei un Pydantic model, care specifică exact de ce informații are nevoie agentul care primește. Când agentul curent decide să execute acel handoff, modelul de limbaj din spate generează un payload care se potrivește cu această schema. Hai să clarificăm din start o confuzie comună. E ușor să confunzi acest input type cu un state persistent al aplicației, cum ar fi un user profile ID sau o conexiune la o bază de date de backend care trăiește pe tot parcursul sesiunii. Nu este așa. Acest input type este strict pentru metadata tranzitorie, generată de model, creată exact în momentul de handoff. De exemplu, dacă un agent de triaj transferă un utilizator către un specialist de billing, acel input type ar putea cere un câmp numit escalation reason. Agentul de triaj generează un string scurt care explică eroarea specifică de billing, iar agentul de billing primește acele structured data imediat cum se activează. Asta rezolvă mesajul explicit de handoff. Acum, trebuie să gestionăm istoricul conversației. By default, întregul istoric de mesaje călătorește odată cu acel handoff. Fiecare prompt al utilizatorului, fiecare răspuns al asistentului și fiecare tool call din background sunt transmise mai departe. Asta consumă tokens rapid și umple context window-ul cu zgomot irelevant. Controlezi asta folosind un input filter. Un input filter este o funcție Python standard care interceptează istoricul conversației fix înainte ca agentul care îl primește să îl citească. Ea ia lista completă de mesaje anterioare ca argument, le procesează și returnează o listă nouă, modificată, de mesaje. Gândește-te la un scenariu în care agentul tău inițial a petrecut zece runde apelând diverse search tools și API-uri de baze de date încercând să rezolve o problemă, înainte să renunțe într-un final și să ruteze utilizatorul către un agent general de FAQ. Agentul de FAQ are nevoie doar de întrebările propriu-zise ale utilizatorului. Nu are absolut deloc nevoie de acele JSON outputs brute a zece tool calls eșuate. Pentru a rezolva asta, scrii o funcție de input filter. În interiorul ei, iterezi prin lista de mesaje primite. Verifici rolul fiecărui mesaj. Dacă mesajul este un tool execution sau un tool result brut, îl elimini. Dacă este un mesaj direct de la utilizator sau un răspuns final de la asistent, îl adaugi la noua ta listă. Apoi returnezi această listă curată și atașezi acea filter function la definiția de handoff. Agentul de FAQ primește acum un istoric simplificat care conține doar acel schimb de replici human-readable. Aici este ideea principală. Aceste handoff inputs adaugă inteligență structurată tranziției, în timp ce acele input filters taie nemilos zgomotul. Împreună, ele modelează exact ceea ce știe agentul care primește. Salvezi tokens, reduci latența și previi ca noul agent să halucineze pe baza raționamentului abandonat de agentul anterior. Controlul contextului la acel handoff boundary este cea mai eficientă metodă pentru a menține un sistem multi-agent rapid și precis. Dacă vrei să ajuți la continuarea emisiunii, poți căuta DevStoriesEU pe Patreon — sprijinul tău contează foarte mult. Asta e tot pentru acest episod. Mulțumesc că m-ai ascultat și continuă să construiești!
8

Controlul stării: to_input_list și Server IDs

4m 06s

O analiză detaliată a gestionării manuale a conversațiilor. Înțelege metodele de cel mai jos nivel pentru păstrarea contextului între rânduri și utilizarea Server IDs.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 8 din 18. Un agent AI cu amnezie este inutil. Dar stocarea incorectă a memoriei sale poate duplica silențios istoricul conversației și îți poate dubla costurile de API. Asta se întâmplă când combini accidental diferite metode de a urmări istoricul de chat. Astăzi ne uităm la controlul state-ului: to_input_list și Server IDs. Implicit, o rulare de bază a unui agent este complet stateless. Trimiți un string, primești un string. Dacă pui o întrebare de tip follow-up, agentul nu are context pentru ce tocmai ați discutat. Trebuie să furnizezi tu istoricul. Deși SDK-ul oferă session wrappers high-level, uneori ai nevoie de cea mai low-level și transparentă metodă de a menține istoricul de chat pe parcursul mai multor turn-uri, fără niciun state ascuns în mod magic. Există două moduri explicite de a gestiona asta. Prima metodă păstrează source of truth pe mașina ta, folosind o metodă numită to_input_list. Când un agent termină o rulare, returnează un result object. Acest obiect conține răspunsul final, dar conține și pașii ascunși pe care i-a făcut agentul pentru a ajunge acolo. Dacă agentul a făcut un tool call către o bază de date, a citit output-ul și apoi a formulat un răspuns, toți acești pași intermediari fac parte din state-ul conversației. Apelarea to_input_list pe result object împachetează întreaga secvență. Returnează un array plat care conține prompt-ul original al utilizatorului, răspunsurile agentului, acele tool calls specifice și tool outputs. Formatează toate astea exact așa cum se așteaptă API-ul să le primească. Dacă construiești un chat loop în command-line, logica e următoarea. Definești o variabilă care să țină array-ul conversației. Inițial, conține doar primul prompt al utilizatorului. Transmiți acest array către agent. Când agentul termină, iei rezultatul și apelezi to_input_list, care îți dă istoricul complet și actualizat al acelui turn. Când utilizatorul tastează a doua întrebare, dai append manual la noul mesaj la finalul acelei liste și transmiți totul înapoi către agent. Ai control total asupra payload-ului. Acum, a doua parte a problemei. Să plimbi un array masiv de mesaje anterioare și tool outputs în format JSON, dus-întors prin rețea la fiecare turn, consumă lățime de bandă. Dacă vrei să eviți asta, poți folosi server-side IDs. Fiecare răspuns pe care îl primești de la API include un identificator unic. În loc să transmiți un array de mesaje anterioare în următoarea rulare a agentului, transmiți un parametru numit previous_response_id. Aici e ideea de bază. Când furnizezi un previous_response_id, clientul tău trimite doar noul mesaj al utilizatorului. Nu trimiți array-ul cu istoricul. Serverul OpenAI caută acel ID, recuperează thread-ul de context existent la capătul lui, atașează noul tău mesaj la el și generează următorul răspuns. Asta ne aduce la o capcană critică. Ai putea fi tentat să combini aceste abordări. Ai putea să dai append la user input în lista client-side, să transmiți acea listă completă către agent și să transmiți și acel previous_response_id, doar ca să fii sigur. Nu face asta. Trebuie să alegi exact o strategie per conversație. Dacă furnizezi atât array-ul complet cu istoricul, cât și un previous_response_id, serverul le va concatena. Agentul tău va citi întreaga conversație de două ori, va fi derutat de acele tool calls duplicate și vei plăti pentru acele tokens de două ori. Alegerea dintre aceste două metode se reduce la vizibilitate versus eficiență. Folosește liste client-side atunci când trebuie să auditezi, să filtrezi sau să modifici istoricul conversației între turn-uri. Folosește server-side IDs atunci când ai încredere în thread-ul brut și vrei să minimizezi network payload-ul. Asta e tot pentru acest episod. Mulțumesc pentru audiție și continuă să construiești!
9

Automatizarea memoriei cu Sessions încorporate

4m 03s

Simplifică-ți buclele de chat cu sistemul de memorie încorporat al SDK-ului. Explorăm SQLiteSession, OpenAIConversationsSession și persistența automată.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 9 din 18. Construiești un chat bot persistent. Scrii cod ca să iei mesajele anterioare dintr-o bază de date, să le pasezi agentului tău, să extragi noul răspuns și să scrii lista actualizată înapoi în baza de date. Este un boilerplate plictisitor pe care l-ai scris de zeci de ori. Astăzi ne uităm la automatizarea memoriei cu Built-in Sessions, care înlocuiește toată acea logică de read și write din baza de date cu un singur obiect. Hai să clarificăm din start o concepție greșită des întâlnită. Când developerii încep să folosească sesiuni în acest SDK, se gândesc adesea că încă trebuie să facă fetch și să paseze manual istoricul mesajelor către agent runner, alături de sesiune. Nu e cazul. Să oferi un obiect de tip session runner-ului înlocuiește complet managementul manual al istoricului. Îi predai cheile. Runner-ul preia automat mesajele anterioare fix înainte să înceapă un conversation turn și face append automat la noile mesaje în momentul în care turn-ul se termină. Gândește-te la un Slack bot persistent care trebuie să țină minte preferințele utilizatorului de la o zi la alta. Vrei să stochezi acest state pe disk fără să configurezi o bază de date externă greoaie. SDK-ul oferă un tool built-in pentru asta, numit SQLite Session. Pentru că interacțiunea cu un file system necesită operațiuni de input output, acest tool este complet asincron. Ca să-l folosești, mai întâi instanțiezi un SQLite Session, oferind un file path pentru baza ta de date locală. Apoi, te conectezi la el folosind un async context manager. Gândește-te la asta ca la deschiderea unei conexiuni sigure care garantează că fișierul bazei de date este locked și unlocked corect. În interiorul acelui connection block, apelezi agent runner-ul. În loc să pasezi un array de mesaje anterioare către runner, pur și simplu pasezi obiectul de tip session și un session ID. Session ID-ul este doar un string unic. Pentru Slack bot-ul tău, acest ID ar putea fi user ID-ul sau channel ID-ul. Runner-ul ia acel ID, caută în fișierul SQLite, face load la istoricul existent, procesează user prompt-ul, și apoi persistă în siguranță noul state înapoi în fișier. Toate astea se întâmplă în fundal. Iată ideea cheie. Un conversation history nelimitat îți va depăși până la urmă limitele de context window. Nu vrei ca un chat minor de acum trei luni să îți umfle token usage-ul sau să îți dea crash la API call astăzi. Pentru a controla asta, SDK-ul oferă Session Settings. Când apelezi runner-ul, poți include un obiect Session Settings alături de session-ul în sine. Acest obiect de settings acceptă un parametru pentru numărul maxim de mesaje anterioare. Dacă îl setezi la zece, runner-ul trunchiază automat istoricul încărcat. Păstrează doar cele mai recente zece mesaje în contextul activ trimis către model, dar întregul tău log istoric rămâne neatins și în siguranță în baza de date SQLite. SQLite Session este ideal pentru persistență locală sau aplicații single server. Dacă Slack bot-ul tău crește și trebuie să scalezi pe mai multe servere, SDK-ul gestionează asta seamless. Păstrezi codul de runner exact la fel, dar schimbi SQLite Session-ul local cu o opțiune distribuită, cum ar fi un Redis Session sau un Dapr Session. Ideea principală este că sesiunile impun un separation of concerns strict. Configurând un obiect de tip session și pasându-l runner-ului, elimini acel boilerplate fragil de bază de date și garantezi că memoria agentului tău este mereu perfect sincronizată cu execution state-ul său. Asta e tot pentru azi. Mersi că m-ai ascultat — du-te și construiește ceva cool.
10

Protejarea fluxurilor de lucru: Input și Output Guardrails

4m 04s

Securizează-ți pipeline-urile AI prin capturarea inputurilor malițioase înainte ca acestea să ajungă la modelele costisitoare. Acoperim guardrails la nivel de agent și execuția paralelă versus blocantă.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 10 din 18. Cel mai puternic model de reasoning al tău este și cel mai scump. Dacă un utilizator încearcă să-l păcălească pentru a-i face temele la matematică sau pentru a încălca politicile de siguranță, nu vrei să afli asta după ce a petrecut deja două minute și a consumat o mie de tokens gândindu-se la asta. Protejarea workflow-urilor tale cu Input și Output Guardrails este modul prin care previi acest lucru. Guardrails la nivel de agent acționează ca niște bouncers pentru modelele tale principale. Sunt funcții separate, adesea susținute de modele mai mici, mai rapide și mai ieftine, care validează datele ce intră sau ies din agentul tău. Interceptând request-urile, acestea îți mențin modelele scumpe concentrate pe munca reală și se asigură că aplicația ta rămâne sigură și on-topic. Le aplici în două locuri: la input și la output. Input guardrails evaluează prompt-ul utilizatorului înainte ca agentul tău principal să se apuce de treabă. Imaginează-ți un scenariu în care ai un model greu și lent care gestionează analize financiare complexe. Poți seta un input guardrail folosind un model rapid și lightweight pentru a revizui fiecare mesaj primit. Când un utilizator pune o întrebare, acest model rapid o interceptează. Verifică dacă utilizatorul încearcă să-l facă pe agent să-i rezolve o temă pentru școală, sau poate încearcă un atac de prompt injection. Dacă input-ul este marcat, guardrail-ul îl respinge imediat și returnează un mesaj standard de refuz. Modelul tău greu de reasoning nici măcar nu se trezește. Economisești timp și economisești bani. Output guardrails gestionează celălalt capăt al tranzacției. Ele oferă o verificare finală înainte ca utilizatorul să vadă răspunsul. Agentul principal și-a terminat task-ul, dar trebuie să te asiguri că nu se scurg date sensibile, sau că tonul se aliniază cu regulile companiei tale. Output guardrail-ul revizuiește textul generat. Dacă detectează o halucinație sau o încălcare a politicilor, blochează mesajul înainte să ajungă la utilizator. Aici este ideea de bază. Modul în care aceste guardrails îți afectează aplicația depinde în totalitate de modul lor de execuție. Le poți rula în blocking mode sau în parallel mode. Blocking mode este o secvență strictă. Un input guardrail trebuie să-și termine evaluarea și să returneze un rezultat pozitiv înainte ca agentul principal să aibă voie să pornească. Un output guardrail trebuie să termine verificarea răspunsului final înainte ca utilizatorul să primească măcar un singur cuvânt. Asta este cea mai sigură abordare și garantează că nu vei irosi bani pe request-uri proaste, dar adaugă latență interacțiunii. Parallel mode sacrifică controlul strict al costurilor pentru viteză. O concepție greșită comună este că execuția paralelă pune cumva pe pauză agentul principal în timp ce guardrail-ul rulează pe lângă el. Nu e așa. În parallel mode, input guardrail-ul și agentul principal pornesc exact în același timp. Agentul generează activ text și consumă tokens în timp ce guardrail-ul încă evaluează input prompt-ul. Dacă guardrail-ul decide să respingă request-ul, va anula agentul principal din mers. Utilizatorul este în continuare protejat și nu va vedea output-ul, dar tu tot plătești pentru tokens pe care agentul principal i-a consumat înainte să fie întrerupt. Configurezi asta definind o funcție simplă care returnează o decizie de pass sau fail, atașând-o agentului tău și declarându-i modul. Potrivește întotdeauna modul de execuție cu prioritățile tale: folosește blocking guardrails pentru a-ți proteja portofelul de modele scumpe, și parallel guardrails pentru a-ți proteja user experience-ul de latență. Asta e tot pentru acest episod. Mulțumesc pentru audiție și continuă să construiești!
11

Validarea acțiunilor: Tool-Level Guardrails

4m 17s

Previne scurgerile critice de date la nivel de funcție. Învață cum să încapsulezi instrumente specifice cu input și output guardrails precise.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 11 din 18. Chiar și cel mai inteligent AI poate divulga accidental un secret din baza de date dacă trage date raw direct în contextul său. Ai putea presupune că verificările tale de siguranță top-level prind totul, dar acestea rulează doar la începutul sau la sfârșitul unei conversații. Dacă vrei să interceptezi date sensibile mid-workflow, ai nevoie de Validating Actions, mai exact Tool-Level Guardrails. O capcană comună este să presupui că agent-level guardrails îți protejează sistemele de bază. Nu o fac. Agent guardrails procesează prompt-ul inițial al utilizatorului sau răspunsul final trimis înapoi acestuia. Ele sunt oarbe la acel back-and-forth intern atunci când un agent apelează o bază de date sau un API third-party. Dacă un prompt malițios îți păcălește agentul să apeleze un tool intern, verificările agent-level nu îl vor opri. Pentru a proteja tool-urile în sine, OpenAI Agents SDK oferă tool guardrails. Acestea stau direct pe funcție, acționând ca un checkpoint obligatoriu chiar înainte sau imediat după ce tool-ul se execută. Există două tipuri pe care trebuie să le știi. Primul este tool input guardrail. Aplici acest decorator pentru a valida argumentele înainte ca tool-ul propriu-zis să ruleze. Să zicem că un agent încearcă să apeleze un tool care șterge un cont de utilizator. Input guardrail-ul interceptează argumentele pe care le-a generat agentul. Verifică dacă user ID-ul furnizat se potrivește cu un format valid, sau dacă sesiunea curentă are nivelul corect de autorizare. Dacă input-ul pică această verificare, guardrail-ul oprește complet rularea tool-ului. În loc să execute ștergerea, returnează un mesaj de eroare direct către agent. Agentul citește apoi acea eroare și poate încerca din nou cu input-uri corectate, fără să atingă vreodată baza de date propriu-zisă. Acum, a doua parte este tool output guardrail. Acesta operează după ce tool-ul se execută cu succes, dar înainte ca rezultatul să fie returnat agentului. Aici filtrezi, redactezi sau validezi payload-ul. Ia ca exemplu un tool de database lookup. Agentul cere un profil de developer, iar tool-ul aduce înregistrarea raw. Totuși, acea înregistrare se întâmplă să conțină un API key activ care începe cu literele s-k-dash. Dacă acel key raw se întoarce la agent, intră în context window-ul language model-ului. Asta reprezintă un risc masiv de securitate. Pentru a repara asta, adaugi un tool output guardrail la acea funcție specifică de lookup. Guardrail-ul ia rezultatul raw din baza de date, scanează textul după acel pattern s-k-dash și înlocuiește key-ul real cu un string placeholder, cum ar fi redacted. Doar după acest proces de scrubbing, datele curățate sunt returnate agentului. Agentul primește în continuare informațiile de profil de care are nevoie pentru a răspunde utilizatorului, dar secretul nu părăsește niciodată execution boundary-ul izolat al tool-ului. Asta e partea care contează. În workflow-uri multi-agent complexe, diferiți agenți specializați ar putea invoca tool-uri în secvențe imprevizibile. Nu te poți baza pe prompting-ul agentului pentru a se comporta în siguranță. De asemenea, nu poți spera că filtrul final de output va prinde un key scăpat chiar înainte să ajungă la utilizator, pentru că până atunci, key-ul a fost deja expus language model-ului. Trebuie să securizezi tool-ul în sine. Prin atașarea guardrail-ului direct la funcție, logica de securitate călătorește odată cu tool-ul. Nu contează ce agent îl apelează sau când este apelat în workflow. Protecția este absolută. Tool guardrails îți tratează funcțiile ca zero-trust boundaries, asigurându-se că, indiferent cât de autonom devine agentul tău, nu poate niciodată să introducă date greșite sau să extragă date sensibile. Asta e tot pentru acest episod. Mulțumesc că m-ai ascultat și continuă să construiești!
12

Pauzarea execuției: Human-in-the-Loop și RunState

3m 27s

Implementează măsuri de siguranță pentru acțiunile ireversibile prin impunerea aprobărilor de tip Human-in-the-Loop. Explorăm pipeline-ul de serializare RunState pentru pauzarea și reluarea sarcinilor de lucru.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 12 din 18. Nu ai lăsa un intern nou să dea drop la o bază de date de producție fără să ceară permisiunea mai întâi. Nici agentul tău AI nu ar trebui să poată face asta. Când un agent are acces la tools extrem de distructive sau sensibile, ai nevoie de o modalitate de a-l opri, de a-i verifica munca și de a-i da undă verde manual. Acest lucru se rezolvă prin Pausing Execution: Human-in-the-Loop și RunState. Dacă ai nevoie ca un om să aprobe o acțiune, primul tău instinct ar putea fi să pui pe pauză scriptul Python și să aștepți input de la tastatură. Nu face asta. Menținerea unui proces activ în timp ce aștepți un răspuns pe email sau un click într-un dashboard irosește resursele serverului. De asemenea, crapă complet dacă serverul se restartează sau dacă faci deploy la cod nou. SDK-ul OpenAI Agents gestionează asta elegant, permițând procesului Python să se închidă complet și să fie reluat mai târziu pe un server complet diferit. Totul începe la definiția tool-ului. Când scrii o funcție pentru agentul tău, cum ar fi un tool numit delete production database, aplici un flag needs approval setat pe true. Când agentul procesează un prompt și decide că trebuie să apeleze acest tool specific, engine-ul se oprește imediat. Tool-ul nu rulează. În schimb, runner-ul cedează controlul înapoi codului aplicației tale. Aici e partea esențială. Când execuția se oprește, runner-ul îți dă un obiect RunState. Acest obiect conține întregul context al run-ului până la acea milisecundă exactă. Știe istoricul conversației, procesul intern de gândire al agentului și tool call-ul specific pe care vrea să îl execute în continuare. Iei acest obiect RunState și îl serializezi într-un string JSON standard. Salvezi acel payload JSON în baza de date, îi dai push într-un queue sau îl scrii pe disc. Odată ce starea este stocată în siguranță, scriptul tău Python se închide. Aplicația ta este acum idle. Pot trece ore sau chiar zile. În cele din urmă, un engineering manager se loghează într-un dashboard web, vede ștergerea bazei de date în așteptare și dă click pe approve. Acel click declanșează un web request complet nou. Backend-ul tău se trezește și citește payload-ul JSON salvat din baza de date. Deserializează acel string înapoi într-un obiect RunState valid. Apoi, pornești o nouă execuție a runner-ului. Îi pasezi aceeași instanță de agent, RunState-ul restaurat și decizia omului. Dacă pasezi o aprobare, runner-ul execută tool-ul de ștergere a bazei de date, iar agentul continuă să îi răspundă utilizatorului. Dacă managerul a dat click pe reject, pasezi în schimb o respingere. Runner-ul nu execută tool-ul. Trimite respingerea înapoi agentului ca un tool error, forțând agentul să își adapteze planul sau să îi spună utilizatorului că acțiunea a fost refuzată. Prin serializarea RunState-ului, transformi un script sincron într-un workflow asincron, permițând oamenilor și agenților să colaboreze în siguranță indiferent de intervalul de timp, fără să ții blocat niciun proces pe server. Dacă vrei să ajuți la continuarea emisiunii, ne poți sprijini căutând DevStoriesEU pe Patreon. Mersi că ai stat cu noi. Sper că ai învățat ceva nou.
13

Injectarea dependențelor locale cu RunContextWrapper

3m 56s

Stăpânește injectarea dependențelor în fluxurile agenților tăi. Învață cum să transmiți în siguranță stările locale și conexiunile la baza de date către instrumente, fără a le scurge către LLM.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 13 din 18. Cum îi spui unei funcții care utilizator discută în prezent, fără să înveți accidental LLM-ul ID-ul privat din baza de date a utilizatorului? Dacă îl pui în system prompt, expui date interne și irosești tokens. Pentru a transmite un local state sigur către tool-urile tale, folosești injectarea de dependențe locale cu RunContextWrapper. O greșeală comună când construiești agenți este să tratezi modelul de limbaj ca pe un intermediar pentru absolut tot. Developerii încearcă adesea să includă connection strings pentru baza de date, API keys interne sau identificatori privați de utilizator direct în instrucțiunile de sistem. Fac asta sperând că modelul va transmite ascultător acele credențiale sensibile înapoi în tool calls ca parametri. Ăsta e un risc major de securitate. De asemenea, consumă tokens inutili din context window și crește șansa ca modelul să halucineze parametri incorecți. Abordarea corectă este să ocolești complet modelul de limbaj pentru local execution state-ul tău. RunContextWrapper oferă un transport layer securizat pentru a injecta dependențe direct în tools și lifecycle hooks. Atributul de context atașat acestui wrapper este pur și simplu local state din Python. Modelul nu îl vede niciodată, nu îl citește niciodată și nu trebuie să raționeze pe baza lui. Ia în calcul un scenariu concret. Un utilizator autentificat discută cu agentul tău de customer support și cere să își vadă facturile recente. Sistemul tău trebuie să aducă aceste înregistrări, ceea ce înseamnă că tool-ul tău de facturare are nevoie de ID-ul intern din baza de date al utilizatorului pentru a rula un database query în siguranță. Mai întâi, îți definești dependența locală în codul aplicației. Poți crea o clasă de date structurată numită User Info care ține ID-ul intern al utilizatorului. Apoi, scrii funcția de tool pentru a aduce istoricul de facturare. În semnătura acestei funcții de tool, definești un parametru tipizat special ca să accepte obiectul de context. SDK-ul înțelege acest type hint și știe să nu expună acest parametru către modelul de limbaj. În interiorul corpului funcției, accesezi parametrul de context, extragi dependența User Info și folosești acel ID privat de utilizator pentru a face un query sigur către backend-ul tău. Aici e ideea principală. Când te pregătești să execuți agent run-ul, nu transmiți doar mesajul brut al utilizatorului. Creezi o instanță de RunContextWrapper. Atașezi clasa de date User Info populată direct la wrapper. Apoi, pasezi acest wrapper către execution runner. Fluxul logic se ocupă automat de restul. Când utilizatorul cere istoricul de facturare, modelul de limbaj decide să declanșeze tool-ul tău de facturare. Modelul oferă doar argumentele pe care le știe din conversația publică, poate filtrând după o anumită lună sau un număr de factură. Nu are absolut nicio idee cine este utilizatorul în backend-ul tău. Înainte ca funcția să ruleze efectiv, SDK-ul interceptează apelul. Inspectează semnătura tool-ului, observă că tool-ul necesită contextul local și injectează automat state-ul pe care l-ai atașat la RunContextWrapper. Tool-ul se execută folosind ID-ul de utilizator securizat, preia înregistrările și returnează datele către model pentru a formula un răspuns. Exact același mecanism de dependency injection funcționează și pentru execution hooks, permițându-ți să pasezi fără probleme connection pools active pentru baza de date sau tracing IDs în event logging-ul tău. Prin separarea raționamentului extern al modelului de execuția internă a codului tău, infrastructura rămâne securizată, iar prompturile rămân concentrate în întregime pe comportament. Păstrează-ți dependențele de execuție complet locale și forțează-ți arhitectura să se bazeze în întregime pe state-ul securizat injectat la runtime. Mulțumesc pentru audiție, o zi grozavă tuturor!
14

USB-C-ul pentru AI: Introducere în MCP

3m 47s

O introducere în Model Context Protocol (MCP). Descoperă cum acest standard acționează ca un conector universal pentru a lega cu ușurință agenții AI de platformele SaaS.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 14 din 18. Nu mai scrie wrapper-e API custom de fiecare dată când agentul tău trebuie să comunice cu un serviciu nou. Dacă te-ai săturat să mapezi manual endpoint-urile REST la JSON schemas doar pentru ca modelul tău de limbaj să înțeleagă ce face un serviciu, există în sfârșit un standard universal. Ne uităm la Model Context Protocol, sau MCP, și la cum să-l folosești. Gândește-te la MCP ca la portul USB-C pentru AI. Înainte de USB-C, fiecare dispozitiv avea nevoie de un cablu de încărcare specific, proprietar. În lumea AI, fiecare sistem extern necesită glue code custom. Dacă vrei ca un agent să citească o bază de date sau să creeze un support ticket, scrii un REST client. Apoi scrii o schema complexă care descrie acel client modelului. În cele din urmă, scrii logica pentru a prinde răspunsul modelului și a declanșa request-ul HTTP propriu-zis. MCP înlocuiește acea muncă manuală. Este un standard deschis care dictează exact cum se descriu tool-urile, input-urile și output-urile lor direct către un model AI. Lumea confundă adesea MCP cu REST API-urile standard. Un REST API trimite date între mașini, dar se așteaptă să știi exact cum să structurezi request-ul în prealabil. MCP standardizează discovery layer-ul. Un server MCP îi spune agentului exact ce tool-uri deține și ce parametri sunt necesari, vorbind exact în formatul de care are nevoie modelul. În OpenAI Agents SDK, consumi aceste servere MCP externe folosind o clasă numită Hosted MCP Tool. Iată ideea de bază. Nu redefini deloc tool schema în codul tău Python. În schimb, inițializezi Hosted MCP Tool dându-i URL-ul unui server MCP remote. Această conexiune funcționează prin Server-Sent Events, ceea ce permite serverului să dea push la update-uri înapoi către agentul tău în siguranță. Când atașezi acest Hosted MCP Tool la setup-ul agentului tău, are loc un handshake. Agentul contactează serverul remote, întreabă ce tool-uri sunt disponibile, face pull la descrierile complet formate și le înregistrează automat. Hai să ancorăm asta într-un scenariu concret. Vrei să-i oferi agentului tău posibilitatea de a programa întâlniri. Fără MCP, ai studia Google Calendar API. Ai scrie o funcție Python pentru autentificare și creare de evenimente. Apoi ai scrie tool schema, astfel încât agentul să știe cum arată un titlu de eveniment sau un timestamp. Cu MCP, dai deploy remote la un server MCP Google Calendar pre-construit. În codul aplicației tale, creezi o nouă instanță de Hosted MCP Tool și o îndrepți către acel URL remote. Pasezi acea singură instanță agentului tău. Serverul remote îi spune instantaneu agentului că are un tool numit schedule meeting. Când modelul de limbaj decide să programeze acea întâlnire, SDK-ul face proxy la apel. Rutează în siguranță request-ul prin rețea către serverul remote, execută acțiunea și returnează rezultatul. Ai scris zero linii de logică pentru integrarea calendarului. Adevărata putere a MCP este decuplarea logicii core a agentului de integrările externe, permițându-ți să schimbi sau să faci upgrade la serviciile de backend doar prin schimbarea unui URL. Mulțumesc pentru ascultare, happy coding tuturor!
15

Conectarea serverelor MCP locale prin Stdio și HTTP

3m 46s

Aprofundează MCP rulând servere locale standard. Învață să izolezi accesul la sistemul de fișiere și la instrumentele interne în siguranță cu MCPServerStdio.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. SDK-ul OpenAI Agents, episodul 15 din 18. Să oferi unui language model acces direct la filesystem-ul tău local sună ca un coșmar absolut de securitate. Dar dacă pui acel acces strict într-un sandbox printr-un protocol standardizat, devine o modalitate sigură și puternică de a procesa date locale. Astăzi ne uităm la conectarea de servere MCP locale prin stdio și HTTP. Model Context Protocol definește modul în care agenții tăi comunică cu tool-uri externe și surse de date. Când vrei să rulezi aceste servere în propria infrastructură, SDK-ul OpenAI Agents oferă două metode de transport local. Prima este standard input și output, folosind clasa numită MCPServerStdio. Lumea crede uneori că asta necesită un setup complex de rețea locală. Nu e așa. Când folosești transportul stdio, SDK-ul pur și simplu face spawn la serverul MCP ca un child process local. Agentul trimite request-uri scriind la standard input-ul acelui proces și citește response-urile din standard output-ul său. Imaginează-ți un scenariu în care vrei ca agentul tău să citească fișiere, dar numai dintr-un anumit director local. Instanțiezi MCPServerStdio și îi pasezi comanda de rulare. De exemplu, ai putea să pasezi comanda de node package manager npx, urmată de argumentele pentru a lansa serverul oficial de filesystem MCP, și calea absolută către directorul tău target. Pentru că acest server rulează ca un subprocess, trebuie să-i gestionezi lifecycle-ul. Dacă scriptul tău Python se termină sau dă crash, nu vrei ca un proces node orfan să rămână agățat în background. SDK-ul forțează un lifecycle management curat prin necesitatea unui context manager asincron. Definești un bloc async with pentru a inițializa serverul stdio. Când execuția intră în bloc, SDK-ul pornește child process-ul. Când execuția iese din bloc, face un teardown curat al procesului. În interiorul acelui bloc, conectezi serverul care rulează la agentul tău. Creezi un MCP Client, îi pasezi instanța ta de server stdio, și apoi oferi acel client agentului tău. Agentul are acum acces temporar și scoped la directorul tău local. Acum, ce faci dacă vrei să expui un API intern privat, sau să te conectezi la un serviciu care rulează deja? Nu vrei să faci spawn la un nou subprocess pentru asta. Asta ne aduce la a doua opțiune de transport, care este MCPServerStreamableHttp. În loc să pasezi o comandă executabilă, oferi acestei clase URL-ul serviciului tău existent. Asta e perfect pentru a conecta în siguranță agentul tău la un microserviciu intern care rulează pe localhost. Agentul comunică făcând streaming de date prin HTTP. Iată ideea cheie. Agentul în sine nu are nicio idee ce transport ai ales. Codul de conectare din aplicația ta arată exact la fel. Tot folosești un context manager, tot creezi un MCP client, și tot i-l dai agentului. SDK-ul abstractizează complet transport layer-ul. Cea mai utilă concluzie aici este că poți dezvolta un custom tool ca un script stdio local pentru testare, și mai târziu să-i faci deploy ca un serviciu HTTP standalone în producție, fără să schimbi nicio linie din logica agentului tău. Asta e tot pentru acest episod. Mersi că m-ai ascultat și spor la construit!
16

Vizualizarea fluxurilor de lucru cu Tracing încorporat

4m 03s

Elimină depanarea cu instrucțiuni print folosind observabilitatea încorporată în SDK. Descoperă cum span-urile și trace-urile automate leagă fluxuri de lucru complexe în întregime.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 16 din 18. Debugging-ul unui sistem multi-agent cu print statements este un coșmar. Te uiți cum se derulează log-urile, încercând să potrivești manual un tool execution de la linia cincizeci cu un model generation de la linia două sute. Din fericire, nu va mai trebui să faci asta niciodată. Acest episod este despre vizualizarea de workflows cu built-in tracing. Când developerii încep să construiască agent workflows complexe, primul lor instinct este adesea să scrie custom logging wrappers. Ei scriu boilerplate code pentru a urmări exact când pornește un agent, ce argumente primește un tool și cât timp îi ia modelului să răspundă. Nu construi asta. Agents SDK-ul se ocupă de asta pentru tine, complet out of the box. De fiecare dată când rulezi un agent, ceri un generation sau declanșezi un tool call, SDK-ul încadrează automat acea acțiune într-un span. Un span este pur și simplu o înregistrare temporizată și structurată a unei singure operațiuni. Aceste spans capturează inputs, outputs și durata task-ului. Ele sunt trimise automat către dashboard-ul OpenAI. Asta înseamnă că obții o cronologie vizuală completă a execuției workflow-ului fără să scrii o singură linie de telemetry code. Iată ideea principală. În timp ce SDK-ul gestionează detaliile granulare, tu controlezi gruparea high-level. Să presupunem că ai un scenariu multi-turn în care un agent generează o glumă, un al doilea agent o evaluează, iar primul agent o rafinează pe baza feedback-ului. By default, SDK-ul va urmări fiecare dintre aceste model generations și tool calls ca spans distincte. Dar pentru un om care se uită la un dashboard, tot acest back-and-forth este doar o singură unitate logică de lucru. Poți grupa aceste acțiuni folosind un custom trace block. Deschizi un context block folosind funcția trace și îi dai un nume descriptiv, cum ar fi joke generation loop. În interiorul acelui block, execuți logica de agent multi-turn. SDK-ul respectă această ierarhie. Va imbrica toate acele spans generate automat pentru rulările, evaluările și rafinările individuale sub acel custom parent trace. Când deschizi dashboard-ul OpenAI, vezi mai întâi acel top-level joke generation loop. Apoi îl poți extinde pentru a investiga secvența exactă de model calls și tool executions care au avut loc în interior. Asta acoperă vizibilitatea, dar cum rămâne cu confidențialitatea? Există momente în care absolut nu trebuie să trimiți telemetry. Dacă agentul tău gestionează dosare medicale sensibile, date financiare sau necesită o conformitate strictă cu Zero Data Retention, trimiterea de input și output logs către un dashboard reprezintă o încălcare a securității. Pentru aceste situații, SDK-ul oferă un tracing disabled context block. Când încadrezi execuția agentului în acest block, SDK-ul oprește complet generarea și trimiterea de spans. Execuția rulează local, rezultatul este returnat aplicației tale, dar nicio înregistrare a prompt-ului, a acelor tool calls sau a răspunsului nu va apărea pe dashboard-ul OpenAI. Odată ce codul iese din acel disabled block, automatic tracing-ul normal se reia pentru restul aplicației tale. Tracing-ul în SDK înseamnă că te oprești din scris boilerplate logging, obții visual debugging imediat și păstrezi în continuare controlul total asupra momentului în care datele tale rămân în întregime locale. Asta e tot pentru acest episod. Mulțumesc că m-ai ascultat și continuă să construiești!
17

Voce cu latență redusă folosind Realtime Agents

4m 12s

Rupe paradigma standard de tip cerere-răspuns. Vezi cum Realtime Agents mențin conexiuni WebSocket live pentru a gestiona întreruperile și raționamentul multimodal.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 17 din 18. Cea mai grea parte când construiești un voice AI nu este generarea vorbirii. Ci să știi când să taci instantaneu pentru că apelantul uman te-a întrerupt în mijlocul propoziției. Dacă te bazezi pe ciclul tradițional de request-response, network latency-ul va da mereu botul de gol. Asta e exact problema pe care o rezolvă Low-Latency Voice cu Realtime Agents. Mulți developeri confundă arhitectura asta cu un voice pipeline standard. Într-un setup tradițional, capturezi audio, îl treci printr-un model Speech-to-Text, trimiți textul ăla către un language model, și la final împingi output-ul de text printr-un sintetizator Text-to-Speech. Acest pipeline introduce latență la fiecare pas. Realtime Agents elimină complet acest pipeline. Folosesc un singur model multimodal care raționează nativ direct pe audio. Audio intră direct, iar audio iese direct sub formă de stream. Nu e nevoie de nicio traducere intermediară în text pentru ca sistemul să înțeleagă userul. Ca să obții asta, trebuie să spargi paradigma standard de HTTP request-response. În loc să trimiți un payload și să aștepți un reply complet, sistemul ține deschisă o conexiune persistentă. În SDK, gestionezi asta folosind două componente principale. Prima este RealtimeAgent. Acest obiect ține system instructions și orice funcții sau tools la care modelul are nevoie de acces. Definește logica, capabilitățile și personalitatea asistentului tău. A doua componentă este RealtimeRunner. Runner-ul este motorul de execuție. El gestionează event loop-ul asincron și se ocupă de network stream-ul persistent, de obicei printr-o conexiune de tip WebSocket sau WebRTC. Gândește-te la un bot de customer service prin telefon care preia un apel primit. Faci bridge cu voice provider-ul tău, poate integrând prin SIP sau WebSockets, și rutezi audio-ul continuu către aplicația ta de Python. Îți creezi RealtimeAgent-ul, echipându-l cu un tool ca să facă fetch la conturile de useri. Apoi, pasezi acel agent și clientul de conexiune la rețea în RealtimeRunner. Când apelezi metoda run pe runner, el preia controlul. Ține conexiunea alive, ascultând constant audio stream-ul, în timp ce gestionează simultan orice function calls pe care agentul trebuie să le facă. Face push și pull la evenimente în ambele direcții, concurent. Userul sună și cere soldul contului. Agentul face trigger la tool-ul de account-fetch, ia datele, și începe imediat să facă stream la răspunsul vocal înapoi către apelant. La jumătatea propoziției, userul vorbește brusc peste bot, spunând că vrea de fapt să declare un card pierdut. Aici e ideea cheie. Pentru că acea conexiune WebSocket este deschisă persistent, iar modelul face ingest nativ la audio stream-ul primit în timp real, serverul detectează instant vocea umană. Dă fire la un eveniment care îi oprește propriul audio output și înregistrează trunchierea. Nu trebuie să scrii custom logic ca să calculezi exact ce audio chunk rula atunci când userul a vorbit. Arhitectura de streaming gestionează întreruperea perfect. Modelul absoarbe noul context audio din întrerupere și începe imediat să facă stream la răspunsul updatat despre anularea cardului pierdut. Obții o dinamică conversațională naturală doar pentru că network layer-ul și model layer-ul sunt construite pentru continuous streaming. Adevărata putere a Realtime API-ului din Agents SDK este că tratează vocea ca pe un continuous stream first-class, mai degrabă decât ca pe un batch de text tradus, deghizat. Asta e tot pentru acest episod. Mersi că m-ai ascultat, și keep building!
18

Construirea de interfețe reactive cu Streaming Events

3m 46s

Treci dincolo de streaming-ul de tokeni de text. Utilizează Semantic Streaming Events pentru a construi interfețe frontend ultra-responsive care reacționează la acțiunile agenților în timp real.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. OpenAI Agents SDK, episodul 18 din 18. Utilizatorii tăi nu vor doar să citească textul pe măsură ce este tastat pe ecran. Vor să vadă exact ce face AI-ul în culise. Dacă încerci să construiești un loading spinner făcând parsing pe chunk-uri de tokeni raw pentru a ghici când rulează un search tool, te complici inutil. Construirea de UI-uri reactive cu streaming events rezolvă exact această problemă. Developerii tratează adesea output-urile AI-ului ca pe o simplă mașină de scris. Ei ascultă un text stream raw și scriu o logică de parsing fragilă pentru a-și da seama dacă agentul urmează să facă un function call. Această abordare este fragilă. Se strică dacă modelul își schimbă puțin formularea și îți lasă frontend-ul în urma execution state-ului real. OpenAI Agents SDK oferă o alternativă structurală. În loc să aștepți string-uri, îți declanșezi agentul folosind o metodă numită run streamed pe runner-ul tău. Această metodă nu returnează plain text. În schimb, returnează o secvență asincronă de evenimente semantice, fiecare împachetat ca un obiect Run Item Stream Event. Gândește-te la un Run Item Stream Event ca la o notificare precisă despre lifecycle-ul intern al agentului. Pe măsură ce agentul procesează un request, emite semnale distincte și previzibile. Îți spune exact când un mesaj nou este adăugat în thread. Îți spune când controlul se transferă de la un agent de triaj la un agent specializat. Foarte important pentru frontend development, îți spune milisecunda exactă în care începe și se termină un tool invocation. Să aplicăm asta pe un scenariu concret. Vrei ca frontend-ul tău să afișeze un spinner care spune Searching database în timp ce agentul caută o înregistrare a unui client. Apelezi run streamed și iterezi prin rezultate. În interiorul acelui loop asincron, inspectezi fiecare eveniment pe măsură ce sosește. Când un eveniment vine pe fir, îi verifici proprietățile ca să vezi ce fel de update reprezintă. Când un eveniment indică faptul că a început un tool call, poți citi numele real al tool-ului direct din payload-ul evenimentului. Nu trebuie să faci parsing pe limbaj natural. Dacă numele tool-ului se potrivește cu funcția ta de database search, faci imediat push la un state update către frontend pentru a randa spinner-ul. Când un eveniment ulterior semnalează că execuția tool-ului este completă, dai dispatch la un alt update pentru a ascunde spinner-ul. Aceste stream events conțin, de asemenea, message deltas standard. Dacă agentul generează un răspuns text lung, stream-ul emite chunk events pe care le adaugi la UI. Arhitectura separă output-ul conversațional raw de acțiunile semantice. Rutezi text chunks către fereastra de chat și rutezi evenimentele de lifecycle ale tool-ului și agentului către UI state manager-ul tău. Acest separation of concerns îți permite să construiești interfețe care se simt instant responsive și profund conectate la logica agentului. Reacționezi la execution path-ul real al sistemului, nu îi ghicești intențiile pe baza cuvintelor. Iată ideea cheie. Nu mai trata output-ul agentului ca pe un simplu conversation stream. Tratează-l ca pe un event-driven state machine, unde fiecare acțiune internă este o oportunitate de a-ți ține utilizatorul informat vizual. Fiindcă acesta este ultimul episod al seriei, te încurajez să citești documentația oficială și să încerci să orchestrezi aceste stream-uri tu însuți. Dacă ai idei despre ce ar trebui să acoperim într-o serie viitoare, vizitează devstories dot eu și spune-ne. Asta e tot pentru acest episod. Pe data viitoare!