Wróć do katalogu
Season 6 18 Odcinki 1h 11m 2026

OpenAI Agents SDK

v0.13 — Edycja 2026. Kompleksowy przewodnik po budowaniu gotowych na produkcję systemów multi-agent przy użyciu OpenAI Agents SDK dla języka Python (v0.13 - 2026). Poznaj podstawowe mechanizmy (core primitives), wzorce orkiestracji, narzędzia, wzorzec Handoff, mechanizmy Guardrails, zarządzanie stanem, MCP oraz integrację głosową w czasie rzeczywistym.

Frameworki AI/ML Systemy wieloagentowe
OpenAI Agents SDK
Teraz odtwarzane
Click play to start
0:00
0:00
1
Więcej niż Swarm: Core Primitives
Poznaj podstawowe koncepcje OpenAI Agents SDK. W tym odcinku omawiamy, dlaczego to SDK w ogóle powstało, w jaki sposób ulepsza Swarm oraz główne zasady projektowe, które stawiają na minimalne abstrakcje.
3m 45s
2
Definiowanie obiektu Agent i Run Loop
Dowiedz się, jak skonfigurować podstawowy obiekt Agent. Analizujemy instrukcje, ustawienia modelu oraz sposoby na płynne wymuszanie ustrukturyzowanych danych wyjściowych.
3m 20s
3
Wyposażanie agentów w Python Function Tools
Daj swoim agentom możliwość działania, przekształcając standardowe funkcje języka Python w wykonywalne narzędzia. Zrozum automatyczne generowanie schematów i wnioskowanie typów.
3m 36s
4
Skalowanie puli narzędzi dzięki Hosted Tool Search
Dowiedz się, jak zarządzać ogromnymi bibliotekami narzędzi bez wyczerpywania budżetu tokenów. Omawiamy odroczone ładowanie, przestrzenie nazw (namespaces) oraz wykonywanie narzędzi w modelu hosted (hosted tool execution).
3m 51s
5
Zdecentralizowana delegacja: Wzorzec Handoff
Opanuj sztukę orkiestracji systemów multi-agent za pomocą wzorca Handoff. Odkryj, jak tworzyć agentów kategoryzujących (triage agents), którzy płynnie przekazują pełną kontrolę wyspecjalizowanym sub-agentom.
3m 51s
6
Scentralizowana orkiestracja: Wzorzec Agents as Tools
Utrzymaj kontrolę nad konwersacją w jednym miejscu, korzystając ze wzorca Agents as Tools. Omawiamy, jak agent-menedżer może syntetyzować odpowiedzi od wielu wyspecjalizowanych sub-agentów.
4m 02s
7
Kształtowanie kontekstu za pomocą Handoff Inputs i filtrów
Optymalizuj zużycie tokenów w systemach multi-agent poprzez modyfikację historii konwersacji pomiędzy przekazaniami (handoffs). Dowiedz się, jak wstrzykiwać metadane i stosować filtry transkrypcji.
4m 08s
8
Kontrolowanie stanu: to_input_list oraz Server IDs
Głębokie zanurzenie w ręczne zarządzanie konwersacją. Zrozum najniższopoziomowe metody zachowywania kontekstu pomiędzy turami oraz wykorzystywania Server IDs po stronie serwera.
4m 19s
9
Automatyzacja pamięci z wbudowanymi obiektami Session
Uprość swoje pętle czatu dzięki wbudowanemu w SDK systemowi pamięci. Omawiamy SQLiteSession, OpenAIConversationsSession oraz zautomatyzowaną trwałość danych.
3m 59s
10
Ochrona przepływów pracy: Input i Output Guardrails
Zabezpiecz swoje potoki AI, wyłapując złośliwe dane wejściowe, zanim dotrą do drogich modeli. Omawiamy mechanizmy Guardrails na poziomie agenta oraz wykonywanie równoległe w porównaniu do blokującego (parallel vs blocking execution).
3m 54s
11
Walidacja akcji: Tool-Level Guardrails
Zapobiegaj krytycznym wyciekom danych na poziomie funkcji. Dowiedz się, jak opakowywać konkretne narzędzia precyzyjnymi mechanizmami Input i Output Guardrails.
4m 17s
12
Wstrzymywanie wykonywania: Human-in-the-Loop oraz RunState
Wdróż zabezpieczenia dla nieodwracalnych akcji, wymuszając zatwierdzenia w modelu Human-in-the-Loop. Analizujemy potok serializacji RunState do wstrzymywania i wznawiania zadań.
3m 46s
13
Wstrzykiwanie lokalnych zależności za pomocą RunContextWrapper
Opanuj wstrzykiwanie zależności w przepływach swoich agentów. Dowiedz się, jak bezpiecznie przekazywać lokalne stany i połączenia z bazą danych do narzędzi, bez wycieku tych informacji do LLM.
4m 44s
14
USB-C dla AI: Wprowadzenie do MCP
Wprowadzenie do Model Context Protocol (MCP). Odkryj, jak ten standard działa jako uniwersalne złącze, pozwalające łatwo podłączyć agentów AI do platform SaaS.
3m 47s
15
Łączenie lokalnych serwerów MCP przez Stdio i HTTP
Zanurz się głębiej w MCP, uruchamiając standardowe serwery lokalne. Naucz się bezpiecznie izolować dostęp do systemu plików i wewnętrznych narzędzi za pomocą MCPServerStdio.
3m 54s
16
Wizualizacja przepływów pracy z wbudowanym Tracingiem
Wyeliminuj debugowanie za pomocą instrukcji print, korzystając z wbudowanej w SDK obserwowalności (observability). Odkryj, jak automatyczne spany (spans) i ślady (traces) łączą całe złożone przepływy pracy.
3m 26s
17
Głos o niskim opóźnieniu z Realtime Agents
Przełam standardowy paradygmat żądanie-odpowiedź. Zobacz, jak Realtime Agents utrzymują aktywne połączenia WebSocket, aby obsługiwać przerwania i wnioskowanie multimodalne.
4m 17s
18
Budowanie reaktywnych interfejsów użytkownika dzięki Streaming Events
Wyjdź poza strumieniowanie tokenów tekstowych. Wykorzystaj Semantic Streaming Events do budowy niezwykle responsywnych interfejsów frontendowych, które reagują na działania agenta w czasie rzeczywistym.
4m 13s

Odcinki

1

Więcej niż Swarm: Core Primitives

3m 45s

Poznaj podstawowe koncepcje OpenAI Agents SDK. W tym odcinku omawiamy, dlaczego to SDK w ogóle powstało, w jaki sposób ulepsza Swarm oraz główne zasady projektowe, które stawiają na minimalne abstrakcje.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 1 z 18. Większość frameworków dla agentów AI zmusza cię do nauki kilkunastu nowych abstrakcji, niestandardowej składni i rozbudowanych hierarchii obiektów. Spędzasz więcej czasu na walce z frameworkiem niż na pisaniu właściwej logiki aplikacji. Dzisiaj przyjrzymy się Beyond Swarm: The Core Primitives. Kiedy programiści słyszą o nowym frameworku dla agentów, często oczekują ogromnego ekosystemu ze stromą krzywą uczenia się. OpenAI Agents SDK to zupełne przeciwieństwo. To ewolucja eksperymentalnej biblioteki Swarm. Swarm udowodnił, że możesz budować złożone interakcje za pomocą bardzo prostych koncepcji. Agents SDK bierze tę filozofię i przygotowuje ją do użytku na produkcji. Jest celowo lekki i w pełni Python-first. Architektura opiera się na dwóch fundamentalnych zasadach projektowych: udostępnianiu bardzo niewielu podstawowych prymitywów i utrzymaniu dużej możliwości konfiguracji wykonania. Nie potrzebujesz tu skomplikowanego grafu węzłów ani zamkniętego języka deklaratywnego, żeby zbudować agenta. SDK daje ci malutki zestaw klocków do budowy. Fundamentem jest obiekt Agent. Definiujesz Agenta, podając mu nazwę i zestaw instrukcji. Jeśli chcesz zbudować prostego nauczyciela historii, tworzysz instancję Agenta, nazywasz go HistoryTutor i przekazujesz mu string z instrukcjami, żeby uczył o wydarzeniach historycznych w sposób jasny i precyzyjny. To cała twoja konfiguracja agenta. Nie ma żadnego ukrytego stanu ani skomplikowanej inicjalizacji. Ale agent sam w sobie to tylko statyczna struktura danych. Nie robi niczego, dopóki nie zostanie uruchomiony. I tu robi się ciekawie. Wykonaniem zajmuje się w całości osobny komponent o nazwie Runner. Runner zarządza pełną pętlą interakcji między twoim lokalnym kodem a zdalnym API OpenAI. W typowej aplikacji musiałbyś napisać własną pętlę while, żeby sprawdzić, czy model chce wykonać tool call, sparsować odpowiedź, uruchomić narzędzie i odesłać wynik. Runner całkowicie to abstrahuje. Żeby rozpocząć proces, przekazujesz swojego agenta HistoryTutor i prompt użytkownika do metody run. Od tego momentu Runner przejmuje kontrolę. Wysyła prompt do modelu. Jeśli model zdecyduje, że musi sprawdzić konkretną datę historyczną, zażąda wykonania tool call. Runner pauzuje, wykonuje lokalną funkcję w Pythonie, którą dostarczyłeś dla tego narzędzia, przechwytuje zwracaną wartość i wysyła ją z powrotem do modelu. Powtarza ten cykl automatycznie. Zwraca kontrolę do twojej aplikacji dopiero wtedy, gdy model uzna, że zadanie jest zakończone i wygeneruje ostateczną odpowiedź tekstową. To ścisłe oddzielenie statycznej definicji Agenta od aktywnego wykonania Runnera sprawia, że SDK jest tak wysoce konfigurowalne. Ponieważ narzędzia to po prostu standardowe funkcje w Pythonie ze zwykłymi type hints, a agent to zwykły obiekt, zachowujesz pełną kontrolę nad flow swojej aplikacji. Możesz łatwo wstrzyknąć własne logowanie, metryki czy obsługę błędów wokół Runnera, bez nadpisywania głębokich klas frameworka. Po prostu piszesz w Pythonie. Prawdziwa wartość tego SDK nie tkwi w tym, co dodaje, ale w tym, co usuwa — schodzi ci z drogi i pozwala na orkiestrację modeli językowych za pomocą zwykłego, czytelnego kodu. Jeśli chcesz wesprzeć nasz podcast, możesz wyszukać DevStoriesEU na Patreonie. To wszystko na dziś. Do usłyszenia następnym razem!
2

Definiowanie obiektu Agent i Run Loop

3m 20s

Dowiedz się, jak skonfigurować podstawowy obiekt Agent. Analizujemy instrukcje, ustawienia modelu oraz sposoby na płynne wymuszanie ustrukturyzowanych danych wyjściowych.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 2 z 18. A co, gdybyś mógł wymusić na swoim modelu językowym, aby zawsze odpowiadał w idealnie sparsowanej strukturze danych, bez pisania ani jednej linijki skomplikowanego regexa? Dzisiaj omówimy definiowanie Agenta i Run Loop, bo to dokładnie w ten sposób osiągasz tak ścisłą kontrolę. Częstym błędem przy rozpoczynaniu pracy z tym SDK jest myślenie, że Agent to aktywny, działający proces. Wcale tak nie jest. W tej architekturze obiekt Agent to wyłącznie kontener konfiguracyjny. Opakowuje on konkretny model językowy w predefiniowany kontekst. Nie wykonuje się sam i nie przechowuje żadnego stanu. Po prostu budujesz blueprint. Aby zdefiniować ten blueprint, tworzysz instancję Agenta. Zaczynasz od parametru instructions. To twój główny system prompt, w którym definiujesz personę, granice i konkretne reguły, których model musi przestrzegać. Następnie podajesz ustawienia modelu. To określa, którego modelu bazowego użyć i konfiguruje standardowe szczegóły inferencji. Na tym etapie twój Agent jest w pełni zdefiniowany, ale całkowicie uśpiony w pamięci. I tu zaczyna się robić ciekawie. Możesz fizycznie wymusić kształt odpowiedzi Agenta za pomocą parametru output type. Wyobraź sobie, że budujesz narzędzie do wyciągania wydarzeń z kalendarza z chaotycznych wątków mailowych. Zamiast pisać instrukcje błagające model o poprawne formatowanie dat, definiujesz konkretną strukturę danych w swoim kodzie. Definiujesz klasę Calendar Event ze ścisłymi polami na tytuł, czas rozpoczęcia i lokalizację. Przekazujesz tę klasę do parametru output type twojego Agenta. Przy takiej konfiguracji, API wymusza schemat. Agent nie może zwrócić zwykłej, tekstowej odpowiedzi konwersacyjnej. Zawsze zwróci zwalidowany obiekt Calendar Event, który kod twojej aplikacji może natychmiast przetworzyć. Masz teraz ścisły, dobrze skonfigurowany blueprint Agenta. Aby zmusić go do faktycznej pracy, potrzebujesz Run Loop. Ponieważ Agent to tylko statyczna definicja, wykonanie jest w całości obsługiwane przez oddzielny komponent Runner. Runner to silnik. Przekazujesz definicję Agenta i user input do Runnera, a on przejmuje wykonanie. Kiedy odpalasz Runnera, wchodzi on w execution loop. Pakuje on instrukcje Agenta, ścisły schemat wyjściowy i prompt użytkownika, a następnie wysyła je do modelu. Run Loop odpowiada za zarządzanie całą tą orkiestracją tam i z powrotem. Jeśli model zdecyduje, że musi wywołać zewnętrzne narzędzie, żeby pobrać brakujące dane, Runner przechwytuje to żądanie, uruchamia lokalny kod narzędzia i przekazuje wynik z powrotem do modelu. Automatycznie obsługuje wszystkie te kroki pośrednie. Pętla kończy się dopiero, gdy model rozwiąże prompt i wygeneruje ostateczny wynik, dokładnie pasujący do twojego output type kalendarza. Utrzymanie statycznej konfiguracji Agenta całkowicie oddzielnie od aktywnego Run Loop to właśnie to, co pozwala ci bezpiecznie reużywać tego samego Agenta do ekstrakcji kalendarza w tysiącach jednoczesnych wywołań, bez ryzyka wycieku danych. Dzięki za wysłuchanie, happy coding wszystkim!
3

Wyposażanie agentów w Python Function Tools

3m 36s

Daj swoim agentom możliwość działania, przekształcając standardowe funkcje języka Python w wykonywalne narzędzia. Zrozum automatyczne generowanie schematów i wnioskowanie typów.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 3 z 18. Ręczne pisanie JSON schemas dla toolsów modelu językowego jest żmudne i podatne na błędy. Jeden brakujący nawias albo niedopasowany typ i model przestaje rozumieć, jak wejść w interakcję z twoim systemem. Zamiast ręcznie pisać te definicje, możesz po prostu napisać standardowy kod w Pythonie i pozwolić, żeby framework zajął się tłumaczeniem. Właśnie tym zajmiemy się dzisiaj: wyposażaniem agentów w Python Function Tools. Częstym błędem jest myślenie, że wystawienie lokalnej logiki dla agenta wymaga utrzymywania dwóch źródeł prawdy. Ludzie zakładają, że potrzebują swojego właściwego kodu w Pythonie, plus osobnego, skomplikowanego pliku konfiguracyjnego JSON, który opisze ten kod modelowi językowemu. Dzięki Agents SDK całkowicie omijasz ręczne pisanie JSON-ów. Po prostu piszesz standardową funkcję w Pythonie i wrzucasz dekorator function tool bezpośrednio nad nią. Kiedy użyjesz tego dekoratora, SDK bierze się do pracy pod spodem, używając wbudowanego w Pythona modułu inspect oraz biblioteki Pydantic. Skanuje sygnaturę twojej funkcji. Czyta nazwy parametrów, wyciąga type hints i pobiera docstring funkcji. Z tych elementów automatycznie generuje ścisły JSON schema i podpina go pod agenta. Spójrzmy na konkretny scenariusz. Chcesz dać swojemu agentowi funkcję o nazwie fetch weather. Ta funkcja potrzebuje do działania precyzyjnych danych geograficznych. Zamiast pozwalać modelowi zgadywać, jakiego formatu stringa użyć, definiujesz konkretną strukturę. Tworzysz własny typ, na przykład TypedDict o nazwie Location, zawierający osobne pola typu string dla miasta i kraju. Następnie używasz tego typu Location jako ścisłego type hinta dla parametru wejściowego w twojej funkcji fetch weather. I tu pojawia się kluczowa kwestia. Musisz dodać do tej funkcji jasny docstring. Możesz napisać proste zdanie mówiące, że ten tool pobiera aktualne warunki pogodowe dla konkretnego miasta i kraju. Framework wyciąga ten tekst i używa go jako głównego opisu toola w prompcie. Twój docstring nie jest już tylko pomocną notatką dla innych programistów. To dosłowna instrukcja obsługi, którą agent analizuje, żeby zdecydować, czy powinien wywołać ten tool. Jeśli użytkownik zapyta, czy potrzebuje kurtki w Tokio, agent przegląda dostępne toolsy. Czyta twój docstring, orientuje się, że funkcja fetch weather dostarczy odpowiedź, i buduje request. Ponieważ dodałeś type hint do wejścia używając słownika Location, Pydantic gwarantuje, że output agenta dokładnie dopasuje się do wymaganych pól, zanim twoja logika w Pythonie w ogóle się wykona. Jeśli model spróbuje przekazać pojedynczy string zamiast słownika, framework wyłapie błąd i zmusi agenta do ponownej próby z poprawną strukturą. SDK wykonuje funkcję lokalnie, przechwytuje zwracaną wartość i przekazuje wynik bezpośrednio z powrotem do pętli wnioskowania agenta. Twoje standardowe type hinty i docstringi w Pythonie nie są już pasywną dokumentacją; tworzą aktywny, wiążący kontrakt API, na którym twój agent polega, żeby wchodzić w interakcję z prawdziwym światem. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.
4

Skalowanie puli narzędzi dzięki Hosted Tool Search

3m 51s

Dowiedz się, jak zarządzać ogromnymi bibliotekami narzędzi bez wyczerpywania budżetu tokenów. Omawiamy odroczone ładowanie, przestrzenie nazw (namespaces) oraz wykonywanie narzędzi w modelu hosted (hosted tool execution).

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 4 z 18. Przekazanie stu narzędzi do modelu językowego niszczy wydajność i przepala twój budżet tokenów, zanim zostanie wykonana choćby jedna akcja. Nie możesz wcisnąć każdego schematu enterprise API w początkowe context window i oczekiwać dobrego wnioskowania. Rozwiązaniem tego problemu jest skalowanie Tool Surfaces za pomocą Hosted Tool Search. Zanim zajmiemy się skalowaniem, musimy zdefiniować hosted tools. Hosted tools wykonują się natywnie na infrastrukturze OpenAI, a nie na twojej lokalnej maszynie. Wbudowane przykłady to Web Search Tool i File Search Tool. Nie piszesz dla nich logiki wykonania, nie zarządzasz web crawlerem ani nie budujesz mechanizmu file chunkingu. Podpinasz je do swojego agenta, a backend OpenAI zajmuje się właściwą pracą. Ale koncepcja hosted tools rozciąga się też na to, jak model odkrywa twoje własne custom tools, gdy masz ich zbyt wiele. Weźmy na przykład agenta CRM. Możesz mieć pięćdziesiąt różnych narzędzi do sprawdzania statusu zamówienia, pobierania historii płatności, aktualizowania adresów wysyłki i pobierania logów z supportu. Jeśli przekażesz wszystkie pięćdziesiąt schematów z góry, przytłoczysz model i zmarnujesz input tokens. Wielu developerów myśli, że musi to rozwiązać, budując etap client-side retrieval. Zakładają, że muszą przechwycić prompt użytkownika, przeszukać lokalną vector database pod kątem odpowiednich schematów narzędzi i dynamicznie wstrzyknąć je do promptu przed wywołaniem modelu językowego. Wcale nie musisz tego robić. Hosted tool search odbywa się natywnie na serwerach OpenAI przy użyciu Responses API. Sam model potrafi przeszukać dostępny tool surface, bez twojego kodu klienckiego w roli pośrednika. Osiągniesz to za pomocą dwóch parametrów: tool namespace i defer loading. Rejestrując swoje narzędzia CRM, grupujesz powiązane funkcje, przypisując je do wspólnego namespace'u. Na przykład, możesz wrzucić wszystkie narzędzia profilu klienta do namespace'u o nazwie customer account. Następnie ustawiasz parametr defer loading na true dla tych narzędzi. I to jest najważniejsza część. Kiedy defer loading jest aktywne, agent nie wysyła poszczególnych schematów narzędzi do modelu językowego na początku konwersacji. Zamiast tego wysyła pojedynczy, lekki schemat, który reprezentuje sam namespace customer account. Model dowiaduje się, że ten namespace istnieje i wie, jak go odpytać w razie potrzeby. Kiedy użytkownik prosi o wyszukanie konkretnego customer ID, model zdaje sobie sprawę, że potrzebuje więcej informacji. Wykonuje natywne wyszukiwanie w namespace'ie customer account. Serwery OpenAI znajdują odpowiednie narzędzie do płatności lub supportu, ładują tylko ten konkretny schemat narzędzia do model context, a następnie model wykonuje tool call. To całkowicie oddziela rozmiar twojej biblioteki narzędzi od początkowego kosztu w tokenach. Możesz podpiąć setki narzędzi do jednego agenta, a początkowy prompt pozostanie malutki. Model ponosi koszt w tokenach tylko za te konkretne schematy narzędzi, które aktywnie zdecyduje się zaciągnąć w runtime'ie. Stosując defer loading, zamieniasz ogromne obciążenie statycznego kontekstu na dynamiczny, precyzyjny mechanizm retrievalu. To tyle na dzisiaj. Do usłyszenia następnym razem!
5

Zdecentralizowana delegacja: Wzorzec Handoff

3m 51s

Opanuj sztukę orkiestracji systemów multi-agent za pomocą wzorca Handoff. Odkryj, jak tworzyć agentów kategoryzujących (triage agents), którzy płynnie przekazują pełną kontrolę wyspecjalizowanym sub-agentom.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 5 z 18. Czasami najlepszym sposobem dla menedżera na poradzenie sobie ze złożonym zadaniem jest całkowite usunięcie się z drogi. Jeśli twój główny routing agent próbuje pośredniczyć w każdej interakcji między użytkownikiem a twoimi systemami backendowymi, twoje prompty stają się rozdęte, a execution staje się zawodne. I to jest dokładnie to, co ma naprawić Decentralized Delegation, a w szczególności Handoff Pattern. Handoff to mechanizm, w którym jeden agent przekazuje pełną kontrolę nad konwersacją innemu agentowi. Częstym błędem jest mylenie handoffu ze standardowym tool callingiem. To są fundamentalnie różne rzeczy. Kiedy agent wywołuje normalną funkcję, pauzuje, czeka na zwrócenie danych, a następnie formułuje odpowiedź dla użytkownika. Kiedy agent triggeruje handoff, oddaje całą turę konwersacji. Kontrola przechodzi całkowicie na nowego agenta. Pierwotny agent całkowicie usuwa się z drogi. To ważne, ponieważ dzięki temu twoja architektura pozostaje zdecentralizowana. Jeśli centralny triage agent musi przetwarzać output każdej akcji specjalisty, jego system prompt musi być ogromny. Potrzebuje instrukcji, jak opisywać zasady zwrotów, rozwiązywać problemy techniczne i usuwać konta. Co gorsza, triage agent nieuchronnie będzie próbował opowiadać użytkownikowi o tym, co zrobił specjalista. To marnuje tokeny, zwiększa latency i wprowadza wysokie ryzyko halucynacji. Handoffy temu zapobiegają, pozwalając specjaliście rozmawiać bezpośrednio z użytkownikiem. Wyobraź sobie system obsługi klienta. Deployujesz ogólnego triage agenta, aby witał użytkowników i kategoryzował zgłoszenia. Klient pisze z prośbą o zwrot pieniędzy. Masz również dedykowanego refund agenta, który jest wyposażony w konkretne billing tools i ścisłe instrukcje dotyczące firmowej polityki zwrotów. Aby połączyć ich za pomocą SDK, piszesz standardową funkcję o nazwie transfer to refund. Ale zamiast zwracać stringa lub dane JSON, ta funkcja zwraca obiekt twojego refund agenta. Następnie przekazujesz tę funkcję transferu swojemu triage agentowi, dodając ją do listy dokładnie tak, jak każde inne narzędzie. Kiedy klient prosi o zwrot pieniędzy, triage agent decyduje się wywołać funkcję transferu. I tu jest kluczowa sprawa. Pod spodem, runner loop z SDK wykonuje funkcję i widzi, że zamiast standardowych danych został zwrócony obiekt Agent. Runner natychmiast zamienia aktywnego agenta w swojej pamięci. Bierze istniejącą historię konwersacji i przekazuje ją bezpośrednio do nowo aktywowanego refund agenta. Refund agent przejmuje aktywną turę, przetwarza żądanie użytkownika, triggeruje swoje własne billing tools i odpowiada bezpośrednio użytkownikowi. Możesz również przekazywać dane podczas tego przejścia. Jeśli triage agent już zapytał użytkownika o numer zamówienia, może przekazać ten numer jako argument do funkcji transferu. Funkcja może następnie wstrzyknąć ten numer zamówienia do context variables nowego agenta przed jego zwróceniem. Refund agent budzi się, już wiedząc dokładnie, którą transakcję ma wyszukać. Używając handoffów, sprawiasz, że każdy agent pozostaje mały, skoncentrowany i przewidywalny, pozwalając na naturalny przepływ konwersacji od jednego wąskiego eksperta do kolejnego. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
6

Scentralizowana orkiestracja: Wzorzec Agents as Tools

4m 02s

Utrzymaj kontrolę nad konwersacją w jednym miejscu, korzystając ze wzorca Agents as Tools. Omawiamy, jak agent-menedżer może syntetyzować odpowiedzi od wielu wyspecjalizowanych sub-agentów.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 6 z 18. Jeśli twój asystent AI musi skonsultować się z trzema różnymi działami przed udzieleniem odpowiedzi użytkownikowi, rzadko chcesz, żeby użytkownik rozmawiał z tymi działami bezpośrednio. Chcesz mieć jeden, spójny głos, który obsługuje konwersację i po cichu pobiera informacje w tle. I właśnie to umożliwia scentralizowana orkiestracja wykorzystująca agentów jako toolsy. Możesz to pomylić z handoffami, gdzie agent na stałe przekazuje użytkownika do innego agenta. W przypadku handoffów, nowy agent całkowicie przejmuje konwersację. W scentralizowanej orkiestracji kontrola nigdy nie jest przekazywana. Główny agent, zazwyczaj działający jako manager, zachowuje absolutną kontrolę nad konwersacją. Manager to jedyny głos, jaki użytkownik kiedykolwiek słyszy. Osiągasz to, biorąc w pełni skonfigurowanego agenta i zamieniając go w funkcję callable. Każdy obiekt agenta w SDK ma metodę o nazwie as_tool. Kiedy wywołasz tę metodę, opakowuje ona całego agenta, włączając w to jego specyficzne instrukcje i jego własne toolsy, w standardowy format toola. Następnie przekazujesz tego opakowanego agenta do swojego managera, dokładnie tak, jak przekazałbyś standardową funkcję w Pythonie. Spójrzmy na praktyczny scenariusz. Budujesz portal obsługi klienta. Tworzysz agenta specjalistę od rezerwacji. Jego jedynym zadaniem jest odpytywanie wewnętrznych systemów, porównywanie dat i zwracanie dostępności. Ten agent jest bardzo techniczny. Jego instrukcje są zoptymalizowane pod kątem dokładności bazy danych, a nie uprzejmej konwersacji. Nie chcesz, żeby użytkownik wchodził w interakcję z tym specjalistą. Dlatego wywołujesz metodę as_tool na tym specjaliście od rezerwacji. Następnie tworzysz swojego agenta managera. Dajesz managerowi ścisłe instrukcje, żeby utrzymywał uprzejmy, korporacyjny ton i dbał o relacje z użytkownikiem. Następnie dodajesz opakowanego specjalistę od rezerwacji do listy toolsów managera. Kiedy użytkownik prosi managera o sprawdzenie dostępności na przyszły wtorek, manager przetwarza to żądanie. Rozpoznaje, że brakuje mu samych danych, ale wie, że ma tool, który może je znaleźć. Manager wywołuje tool do rezerwacji. I tu jest kluczowa sprawa. Kiedy ten tool zostaje wywołany, agent specjalista od rezerwacji budzi się, wykonuje swoje własne, odizolowane wewnętrzne kroki i generuje odpowiedź. Ale nie wysyła tej odpowiedzi do użytkownika. Zwraca surowy, oparty na faktach wynik bezpośrednio do managera. Manager otrzymuje te dane, syntetyzuje je, opakowuje w uprzejme korporacyjne powitanie i ostatecznie odpowiada użytkownikowi. Ten wzorzec hub-and-spoke rozwiązuje poważny problem w złożonych aplikacjach: context bloat. Agent manager nie musi znać database schema ani reguł sprawdzania dat. Utrzymuje swój system prompt w czystości, skupiając się całkowicie na routowaniu żądań i formatowaniu odpowiedzi. W międzyczasie agent specjalista nie musi przejmować się historią konwersacji ani głosem marki. Po prostu wykonuje swoje wąskie zadanie i zwraca wynik. Decydując między handoffem a toolem, zadaj sobie pytanie, kto jest właścicielem ostatecznej odpowiedzi. Jeśli wyspecjalizowany agent musi wejść w dłuższą wymianę zdań z użytkownikiem, potrzebujesz handoffu. Ale jeśli wyspecjalizowany agent jest tylko zaawansowanym procesorem danych, dostarczającym odpowiedź do wykorzystania przez głównego asystenta, opakuj go jako tool i pozwól managerowi zarządzać tą relacją. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.
7

Kształtowanie kontekstu za pomocą Handoff Inputs i filtrów

4m 08s

Optymalizuj zużycie tokenów w systemach multi-agent poprzez modyfikację historii konwersacji pomiędzy przekazaniami (handoffs). Dowiedz się, jak wstrzykiwać metadane i stosować filtry transkrypcji.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 7 z 18. Kiedy przekazujesz klienta do żywego specjalisty, nie zmuszasz go do czytania gigantycznego, surowego transkryptu z każdego automatycznego sprawdzenia systemu, które właśnie miało miejsce. Podajesz mu jasny powód transferu i czyste podsumowanie problemu. A jednak, kiedy deweloperzy łączą agentów AI, często wrzucają cały surowy chat log do context window kolejnego agenta. Dzisiaj to naprawimy, modelując kontekst przy użyciu Handoff Inputs i input filters. Kiedy jeden agent przekazuje kontrolę drugiemu, musi mieć sposób, by zakomunikować, dlaczego ten handoff w ogóle się odbywa. Robisz to za pomocą parametru input type w swojej procedurze handoffu. Definiujesz schemat, zazwyczaj model Pydantic, który dokładnie określa, jakich informacji wymaga odbierający agent. Kiedy obecny agent decyduje się wykonać handoff, pod spodem model językowy generuje payload, który pasuje do tego schematu. Od razu wyjaśnijmy sobie jedno częste nieporozumienie. Łatwo pomylić ten input type z trwałym stanem aplikacji, takim jak ID profilu użytkownika czy połączenie z bazą danych na backendzie, które żyje przez całą sesję. Wcale tak nie jest. Input type służy wyłącznie do przechowywania ulotnych, wygenerowanych przez model metadanych, tworzonych dokładnie w momencie handoffu. Na przykład, jeśli agent robiący triage przekazuje użytkownika do specjalisty od płatności, input type może wymagać pola o nazwie escalation reason. Agent od triage'u generuje krótki string wyjaśniający konkretny błąd płatności, a agent rozliczeniowy otrzymuje te ustrukturyzowane dane natychmiast po wybudzeniu. To załatwia nam temat jawnej wiadomości przy handoffie. Teraz musimy zająć się historią konwersacji. Domyślnie cała historia wiadomości podróżuje razem z handoffem. Każdy prompt użytkownika, każda odpowiedź asystenta i każdy tool call w tle są przekazywane dalej. To szybko przepala tokeny i wypełnia context window nieistotnym szumem. Możesz to kontrolować używając input filter. Input filter to standardowa funkcja w Pythonie, która przechwytuje historię konwersacji tuż przed tym, jak odbierający agent ją przeczyta. Przyjmuje pełną listę poprzednich wiadomości jako argument, przetwarza je i zwraca nową, zmodyfikowaną listę wiadomości. Wyobraź sobie scenariusz, w którym twój początkowy agent spędził dziesięć tur na wywoływaniu różnych narzędzi wyszukiwania i API bazy danych, próbując rozwiązać problem, zanim ostatecznie się poddał i przekierował użytkownika do ogólnego agenta FAQ. Agent FAQ potrzebuje tylko właściwych pytań użytkownika. Absolutnie nie potrzebuje surowych wyników w JSON-ie z dziesięciu nieudanych tool calls. Aby to rozwiązać, piszesz funkcję input filter. W jej środku iterujesz po liście przychodzących wiadomości. Sprawdzasz rolę każdej z nich. Jeśli wiadomość to tool call lub surowy tool result, odrzucasz ją. Jeśli jest to bezpośrednia wiadomość od użytkownika lub końcowa odpowiedź asystenta, dodajesz ją do swojej nowej listy. Następnie zwracasz tę czystą listę i podpinasz swoją funkcję input filter do definicji handoffu. Agent FAQ otrzymuje teraz odchudzoną historię, zawierającą tylko czytelną dla człowieka wymianę zdań. Oto kluczowy wniosek. Handoff inputs dodają ustrukturyzowaną inteligencję do tego przejścia, podczas gdy input filters bezlitośnie wycinają szum. Razem kształtują dokładnie to, co wie odbierający agent. Oszczędzasz tokeny, zmniejszasz opóźnienia i zapobiegasz halucynacjom nowego agenta, które mogłyby wynikać z odrzuconego rozumowania poprzednika. Kontrolowanie kontekstu na granicy handoffu to najskuteczniejszy sposób na utrzymanie szybkości i dokładności systemu multi-agentowego. Jeśli chcesz pomóc w tworzeniu tego podcastu, wyszukaj DevStoriesEU na Patreon — twoje wsparcie wiele dla nas znaczy. To wszystko w tym odcinku. Dzięki za wysłuchanie i twórz dalej!
8

Kontrolowanie stanu: to_input_list oraz Server IDs

4m 19s

Głębokie zanurzenie w ręczne zarządzanie konwersacją. Zrozum najniższopoziomowe metody zachowywania kontekstu pomiędzy turami oraz wykorzystywania Server IDs po stronie serwera.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 8 z 18. Agent AI z amnezją jest bezużyteczny. Ale nieprawidłowe przechowywanie jego pamięci może po cichu zduplikować historię konwersacji i podwoić twoje koszty API. Dzieje się tak, gdy przypadkowo pomieszasz różne metody śledzenia historii czatu. Dzisiaj przyjrzymy się kontrolowaniu stanu: to_input_list i Server IDs. Domyślnie, podstawowy run agenta jest całkowicie bezstanowy. Wysyłasz string, dostajesz string. Jeśli zadasz pytanie uzupełniające, agent nie ma kontekstu tego, o czym przed chwilą rozmawialiście. Musisz dostarczyć historię samemu. Chociaż SDK oferuje wysokopoziomowe wrappery sesji, czasami potrzebujesz najniższego poziomu i najbardziej transparentnego sposobu na utrzymanie historii czatu przez wiele tur, bez żadnego magicznie ukrytego stanu. Są dwa jawne sposoby, żeby sobie z tym poradzić. Pierwsza metoda trzyma source of truth na twojej maszynie, używając metody o nazwie to_input_list. Kiedy agent kończy run, zwraca obiekt result. Ten obiekt zawiera końcową odpowiedź, ale zawiera też ukryte kroki, które agent wykonał, żeby do niej dotrzeć. Jeśli agent wykonał tool call do bazy danych, odczytał output, a następnie sformułował odpowiedź, wszystkie te pośrednie kroki są częścią stanu konwersacji. Wywołanie to_input_list na obiekcie result pakuje całą tę sekwencję. Zwraca płaską tablicę zawierającą oryginalny prompt użytkownika, odpowiedzi agenta, konkretne tool calls i tool outputs. Formatuje to wszystko dokładnie tak, jak API oczekuje tego na wejściu. Jeśli budujesz pętlę czatu w command line, logika wygląda tak. Definiujesz zmienną, która trzyma tablicę konwersacji. Na początku zawiera tylko pierwszy prompt użytkownika. Przekazujesz tę tablicę do agenta. Kiedy agent skończy, bierzesz result i wywołujesz to_input_list, co daje ci pełną, zaktualizowaną historię tej tury. Kiedy użytkownik wpisze swoje drugie pytanie, ręcznie dodajesz jego nową wiadomość na koniec tej listy i przekazujesz całość z powrotem do agenta. Masz pełną kontrolę nad payloadem. A teraz druga część tego tematu. Przesyłanie ogromnej tablicy poprzednich wiadomości i JSON-owych tool outputs w obie strony przez sieć w każdej turze zużywa bandwidth. Jeśli chcesz tego uniknąć, możesz użyć server-side IDs. Każda odpowiedź, którą dostajesz z API, zawiera unikalne ID. Zamiast przekazywać tablicę poprzednich wiadomości do kolejnego runu agenta, przekazujesz parametr o nazwie previous_response_id. Oto kluczowa sprawa. Kiedy podajesz previous_response_id, twój klient wysyła tylko zupełnie nową wiadomość użytkownika. Nie wysyłasz tablicy z historią. Serwer OpenAI wyszukuje to ID, pobiera istniejący wątek kontekstu po swojej stronie, dołącza do niego twoją nową wiadomość i generuje kolejną odpowiedź. To prowadzi nas do krytycznej pułapki. Możesz mieć pokusę, żeby pomieszać te podejścia. Możesz dodać user input do listy client-side, przekazać tę pełną listę do agenta, a do tego przekazać previous_response_id, tak dla bezpieczeństwa. Nie rób tego. Musisz wybrać dokładnie jedną strategię na konwersację. Jeśli podasz zarówno pełną tablicę historii, jak i previous_response_id, serwer skonkatenuje je. Twój agent przeczyta całą rozmowę dwa razy, pogubi się przez zduplikowane tool calls, a ty zapłacisz za te tokeny podwójnie. Wybór między tymi dwiema metodami sprowadza się do kwestii widoczności kontra wydajność. Używaj list client-side, kiedy musisz audytować, filtrować lub modyfikować historię konwersacji między turami. Używaj server-side IDs, kiedy ufasz surowemu wątkowi i chcesz zminimalizować swój network payload. To wszystko w tym odcinku. Dzięki za wysłuchanie i twórz dalej!
9

Automatyzacja pamięci z wbudowanymi obiektami Session

3m 59s

Uprość swoje pętle czatu dzięki wbudowanemu w SDK systemowi pamięci. Omawiamy SQLiteSession, OpenAIConversationsSession oraz zautomatyzowaną trwałość danych.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 9 z 18. Tworzysz persystentnego chatbota. Piszesz kod, który pobiera poprzednie wiadomości z bazy danych, przekazuje je do agenta, wyciąga nową odpowiedź i zapisuje zaktualizowaną listę z powrotem do bazy. To żmudny boilerplate, który pisałeś już dziesiątki razy. Dzisiaj przyjrzymy się automatyzacji pamięci za pomocą wbudowanych sesji, co zastępuje całą tę logikę odczytu i zapisu do bazy danych jednym obiektem. Od razu wyjaśnijmy pewne powszechne nieporozumienie. Kiedy programiści zaczynają korzystać z sesji w tym SDK, często myślą, że nadal muszą ręcznie pobierać i przekazywać historię wiadomości do agent runnera razem z sesją. Wcale nie muszą. Przekazanie obiektu sesji do runnera całkowicie zastępuje ręczne zarządzanie historią. Oddajesz mu stery. Runner automatycznie pobiera poprzednie wiadomości tuż przed rozpoczęciem tury konwersacji i automatycznie dodaje nowe wiadomości w momencie jej zakończenia. Wyobraź sobie persystentnego bota na Slacku, który musi pamiętać preferencje użytkownika przez wiele dni. Chcesz zapisać ten state na dysku bez stawiania ciężkiej, zewnętrznej bazy danych. SDK dostarcza do tego wbudowane narzędzie o nazwie SQLite Session. Ponieważ interakcja z systemem plików wymaga operacji wejścia-wyjścia, to narzędzie jest w pełni asynchroniczne. Aby go użyć, najpierw tworzysz instancję SQLite Session, podając ścieżkę do pliku twojej lokalnej bazy danych. Następnie łączysz się z nią używając asynchronicznego context managera. Pomyśl o tym jak o otwarciu bezpiecznego połączenia, które gwarantuje, że plik bazy danych jest odpowiednio zablokowany i odblokowany. Wewnątrz tego bloku połączenia wywołujesz swojego agent runnera. Zamiast przekazywać do runnera tablicę poprzednich wiadomości, po prostu przekazujesz obiekt sesji i session ID. Session ID to po prostu unikalny string. Dla twojego bota na Slacku, tym ID może być user ID albo channel ID. Runner bierze to ID, przeszukuje plik SQLite, ładuje istniejącą historię, przetwarza prompt użytkownika, a następnie bezpiecznie zapisuje nowy state z powrotem do pliku. Wszystko to dzieje się pod spodem. I tu pojawia się kluczowa kwestia. Nieograniczona historia konwersacji w końcu przekroczy limity twojego context window. Nie chcesz, żeby jakaś drobna rozmowa sprzed trzech miesięcy pompowała zużycie tokenów albo wywaliła twoje dzisiejsze wywołanie API. Żeby to kontrolować, SDK udostępnia Session Settings. Kiedy wywołujesz runnera, możesz dołączyć obiekt Session Settings obok samej sesji. Ten obiekt ustawień przyjmuje parametr określający maksymalną liczbę poprzednich wiadomości. Jeśli ustawisz go na dziesięć, runner automatycznie przytnie załadowaną historię. Zatrzymuje tylko dziesięć najnowszych wiadomości w aktywnym kontekście wysyłanym do modelu, ale twój pełny log historyczny pozostanie bezpieczny i nienaruszony w bazie SQLite. SQLite Session idealnie nadaje się do lokalnej persystencji lub aplikacji na pojedynczym serwerze. Jeśli twój bot na Slacku się rozrośnie i będziesz musiał go skalować na wiele serwerów, SDK poradzi sobie z tym bezproblemowo. Zostawiasz kod runnera bez zmian, po prostu podmieniasz lokalną SQLite Session na opcję rozproszoną, taką jak Redis Session albo Dapr Session. Główny wniosek jest taki, że sesje wymuszają ścisłe separation of concerns. Konfigurując obiekt sesji i przekazując go do runnera, eliminujesz kruchy bazodanowy boilerplate i gwarantujesz, że pamięć agenta jest zawsze idealnie zsynchronizowana z jego execution state. To wszystko na dziś. Dzięki za wysłuchanie — idź zbudować coś fajnego.
10

Ochrona przepływów pracy: Input i Output Guardrails

3m 54s

Zabezpiecz swoje potoki AI, wyłapując złośliwe dane wejściowe, zanim dotrą do drogich modeli. Omawiamy mechanizmy Guardrails na poziomie agenta oraz wykonywanie równoległe w porównaniu do blokującego (parallel vs blocking execution).

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 10 z 18. Twój najpotężniejszy reasoning model jest jednocześnie najdroższy. Jeśli użytkownik spróbuje go oszukać, żeby odrobił za niego pracę domową z matematyki albo złamał zasady bezpieczeństwa, nie chcesz się o tym dowiadywać po dwóch minutach i tysiącu tokenów zużytych na myślenie. Ochrona twoich workflowów za pomocą Input i Output Guardrails to sposób, by temu zapobiec. Guardrails na poziomie agenta działają jak bramkarze dla twoich głównych modeli. Są to osobne funkcje, często napędzane przez mniejsze, szybsze i tańsze modele, które walidują dane wchodzące do agenta lub z niego wychodzące. Przechwytując requesty, pozwalają twoim drogim modelom skupić się na prawdziwej pracy i dbają o to, by aplikacja była bezpieczna i trzymała się tematu. Stosujesz je w dwóch miejscach: na wejściu i na wyjściu. Input guardrails oceniają prompt użytkownika, zanim twój główny agent weźmie się do pracy. Wyobraź sobie scenariusz, w którym masz ciężki, powolny model obsługujący złożoną analizę finansową. Możesz skonfigurować input guardrail, używając szybkiego, lekkiego modelu do sprawdzania każdej przychodzącej wiadomości. Gdy użytkownik zadaje pytanie, ten szybki model je przechwytuje. Sprawdza, czy użytkownik próbuje zmusić agenta do wykonania zadania domowego, czy też próbuje przeprowadzić atak typu prompt injection. Jeśli input zostanie oflagowany, guardrail natychmiast go odrzuca i zwraca standardową wiadomość z odmową. Twój ciężki reasoning model nawet się nie budzi. Oszczędzasz czas i oszczędzasz pieniądze. Output guardrails obsługują drugą stronę transakcji. Zapewniają ostateczną kontrolę, zanim użytkownik zobaczy odpowiedź. Główny agent ukończył swoje zadanie, ale musisz upewnić się, że nie wyciekają żadne poufne dane lub że ton wiadomości jest zgodny z wytycznymi firmy. Output guardrail analizuje wygenerowany tekst. Jeśli wykryje halucynację lub naruszenie zasad, blokuje wiadomość, zanim dotrze do użytkownika. Oto kluczowa kwestia. To, jak te guardrails wpływają na twoją aplikację, zależy całkowicie od ich execution mode. Możesz je uruchomić w blocking mode lub parallel mode. Blocking mode to ścisła sekwencja. Input guardrail musi zakończyć swoją ewaluację i zwrócić wynik pozytywny, zanim główny agent będzie mógł wystartować. Output guardrail musi zakończyć sprawdzanie ostatecznej odpowiedzi, zanim użytkownik otrzyma choćby jedno słowo. To najbezpieczniejsze podejście, które gwarantuje, że nie zmarnujesz pieniędzy na złe requesty, ale dodaje latency do interakcji. Parallel mode wymienia ścisłą kontrolę kosztów na szybkość. Powszechnym błędnym przekonaniem jest to, że parallel execution w jakiś sposób pauzuje głównego agenta, podczas gdy guardrail działa obok niego. Wcale tak nie jest. W parallel mode, input guardrail i główny agent startują dokładnie w tym samym czasie. Agent aktywnie generuje tekst i zużywa tokeny, podczas gdy guardrail wciąż ocenia input prompt. Jeśli guardrail zdecyduje się odrzucić request, anuluje działanie głównego agenta w locie. Użytkownik nadal jest chroniony przed zobaczeniem outputu, ale ty i tak płacisz za tokeny, które główny agent zużył przed przerwaniem. Konfigurujesz to, definiując prostą funkcję, która zwraca decyzję pass lub fail, podpinając ją do swojego agenta i deklarując jej mode. Zawsze dopasowuj execution mode do swoich priorytetów: używaj blocking guardrails, aby chronić swój portfel przed drogimi modelami, oraz parallel guardrails, aby chronić user experience przed latency. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
11

Walidacja akcji: Tool-Level Guardrails

4m 17s

Zapobiegaj krytycznym wyciekom danych na poziomie funkcji. Dowiedz się, jak opakowywać konkretne narzędzia precyzyjnymi mechanizmami Input i Output Guardrails.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 11 z 18. Nawet najsprytniejsze AI może przypadkowo ujawnić secret z bazy danych, jeśli zaciągnie surowe dane bezpośrednio do swojego kontekstu. Możesz zakładać, że twoje główne safety checki wychwytują wszystko, ale odpalają się one tylko na samym początku lub na samym końcu konwersacji. Jeśli chcesz przechwycić wrażliwe dane w środku workflow, potrzebujesz Validating Actions, a konkretnie Tool-Level Guardrails. Częstą pułapką jest zakładanie, że agent-level guardrails chronią twoje systemy pod spodem. Tak nie jest. Agent-level guardrails przetwarzają początkowy prompt użytkownika lub końcową odpowiedź wysyłaną z powrotem do użytkownika. Są one ślepe na wewnętrzną komunikację, gdy agent odpytuje bazę danych lub zewnętrzne API. Jeśli złośliwy prompt oszuka twojego agenta i zmusi go do wywołania wewnętrznego toola, agent-level checki tego nie zatrzymają. Aby chronić same toolsy, OpenAI Agents SDK dostarcza tool guardrails. Siedzą one bezpośrednio na funkcji, działając jako obowiązkowy checkpoint tuż przed lub zaraz po wykonaniu toola. Są dwa typy, które musisz znać. Pierwszy to tool input guardrail. Nakładasz ten decorator, aby zwalidować argumenty, zanim właściwy tool się uruchomi. Powiedzmy, że agent próbuje wywołać toola, który usuwa konto użytkownika. Input guardrail przechwytuje argumenty wygenerowane przez agenta. Sprawdza, czy podane user ID pasuje do prawidłowego formatu, albo czy obecna sesja ma odpowiedni poziom autoryzacji. Jeśli input nie przejdzie tego checka, guardrail całkowicie blokuje uruchomienie toola. Zamiast wykonać usuwanie, zwraca error message bezpośrednio do agenta. Agent odczytuje ten error message i może spróbować ponownie z poprawionymi inputami, bez jakiegokolwiek dotykania właściwej bazy danych. Drugim elementem tej układanki jest tool output guardrail. Działa on po tym, jak tool pomyślnie się wykona, ale zanim wynik zostanie przekazany z powrotem do agenta. To tutaj filtrujesz, redagujesz lub walidujesz payload. Weźmy jako przykład toola do wyszukiwania w bazie danych. Agent prosi o profil developera, a tool pobiera surowy rekord. Jednak tak się składa, że ten rekord zawiera aktywny API key zaczynający się od liter s-k-dash. Jeśli ten surowy klucz wróci do agenta, wejdzie do context window modelu językowego. To ogromne ryzyko bezpieczeństwa. Aby to naprawić, dodajesz tool output guardrail do tej konkretnej funkcji wyszukiwania. Guardrail bierze surowy wynik z bazy danych, skanuje tekst w poszukiwaniu tego wzorca s-k-dash i zastępuje właściwy klucz placeholderem, na przykład stringiem redacted. Dopiero po tym procesie czyszczenia, oczyszczone dane wracają do agenta. Agent nadal dostaje informacje o profilu, których potrzebuje, by odpowiedzieć użytkownikowi, ale secret nigdy nie opuszcza izolowanej granicy wykonania toola. I to jest najważniejsza część. W złożonych, multi-agentowych workflow, różni wyspecjalizowani agenci mogą wywoływać toolsy w nieprzewidywalnych sekwencjach. Nie możesz polegać na promptowaniu agenta, żeby zachowywał się bezpiecznie. Nie możesz też liczyć na to, że końcowy filtr na wyjściu wychwyci wyciek klucza tuż przed wysłaniem go do użytkownika, bo do tego czasu klucz został już wystawiony na model językowy. Musisz zabezpieczyć samego toola. Podpinając guardrail bezpośrednio do funkcji, logika bezpieczeństwa podróżuje razem z toolem. Nie ma znaczenia, który agent go wywoła, ani kiedy zostanie wywołany w danym workflow. Ochrona jest absolutna. Tool guardrails traktują twoje funkcje jako granice zero-trust, dając pewność, że niezależnie od tego, jak bardzo autonomiczny stanie się twój agent, nigdy nie przekaże do środka złych danych, ani nie wyciągnie na zewnątrz wrażliwych danych. To wszystko w tym odcinku. Dzięki za słuchanie i kodujcie dalej!
12

Wstrzymywanie wykonywania: Human-in-the-Loop oraz RunState

3m 46s

Wdróż zabezpieczenia dla nieodwracalnych akcji, wymuszając zatwierdzenia w modelu Human-in-the-Loop. Analizujemy potok serializacji RunState do wstrzymywania i wznawiania zadań.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 12 z 18. Nie pozwoliłbyś nowemu stażyście na usunięcie produkcyjnej bazy danych bez wcześniejszej zgody. Twój agent AI też nie powinien mieć takiej możliwości. Kiedy agent ma dostęp do bardzo destrukcyjnych lub wrażliwych narzędzi, potrzebujesz sposobu, żeby go zatrzymać, sprawdzić jego pracę i ręcznie dać mu zielone światło. Rozwiązuje to Pausing Execution: Human-in-the-Loop oraz RunState. Jeśli potrzebujesz, żeby człowiek zatwierdził akcję, twoim pierwszym odruchem może być zapauzowanie skryptu w Pythonie i czekanie na input z klawiatury. Nie rób tego. Utrzymywanie procesu przy życiu, kiedy czekasz na odpowiedź na maila albo kliknięcie w dashboardzie, marnuje zasoby serwera. Wszystko też całkowicie się psuje, jeśli serwer się zrestartuje albo zrobisz deploy nowego kodu. OpenAI Agents SDK radzi sobie z tym bardzo czysto, pozwalając procesowi w Pythonie na całkowite zakończenie i wznowienie działania później, na zupełnie innym serwerze. Wszystko zaczyna się od definicji toola. Kiedy piszesz funkcję dla swojego agenta, na przykład toola o nazwie delete production database, ustawiasz flagę needs approval na true. Kiedy agent przetwarza prompt i decyduje, że musi wywołać ten konkretny tool, silnik natychmiast się zatrzymuje. Tool się nie uruchamia. Zamiast tego, runner zwraca kontrolę z powrotem do kodu twojej aplikacji. I tu jest kluczowa sprawa. Kiedy egzekucja się zatrzymuje, runner daje ci obiekt RunState. Ten obiekt przechowuje cały kontekst uruchomienia aż do tej konkretnej milisekundy. Zna historię konwersacji, wewnętrzny proces myślowy agenta i konkretny tool call, który chce wykonać jako następny. Bierzesz ten obiekt RunState i serializujesz go do standardowego stringa JSON. Zapisujesz ten payload JSON do bazy danych, wrzucasz go na kolejkę albo zapisujesz na dysku. Kiedy ten stan jest już bezpiecznie zapisany, twój skrypt w Pythonie kończy działanie. Twoja aplikacja jest teraz bezczynna. Mogą minąć godziny, a nawet dni. W końcu engineering manager loguje się do webowego dashboardu, widzi oczekujące usunięcie bazy danych i klika approve. To kliknięcie triggeruje zupełnie nowy web request. Twój backend się budzi i odczytuje zapisany payload JSON z bazy danych. Deserializuje tego stringa z powrotem do prawidłowego obiektu RunState. Następnie uruchamiasz nowe wykonanie runnera. Przekazujesz tę samą instancję agenta, przywrócony RunState i decyzję człowieka. Jeśli przekażesz approval, runner wykonuje tool do usunięcia bazy danych, a agent kontynuuje odpowiadanie użytkownikowi. Jeśli manager kliknął reject, zamiast tego przekazujesz rejection. Runner nie wykonuje toola. Przekazuje to rejection z powrotem do agenta jako tool error, zmuszając agenta do dostosowania swojego planu albo poinformowania użytkownika, że akcja została odrzucona. Serializując RunState, zamieniasz synchroniczny skrypt w asynchroniczny workflow, pozwalając ludziom i agentom na bezpieczną współpracę niezależnie od upływu czasu, bez pozostawiania ani jednego wiszącego procesu na serwerze. Jeśli chcesz pomóc nam tworzyć ten podcast, możesz nas wesprzeć, szukając DevStoriesEU na Patreonie. Dzięki za wspólnie spędzony czas. Mam nadzieję, że dowiedziałeś się czegoś nowego.
13

Wstrzykiwanie lokalnych zależności za pomocą RunContextWrapper

4m 44s

Opanuj wstrzykiwanie zależności w przepływach swoich agentów. Dowiedz się, jak bezpiecznie przekazywać lokalne stany i połączenia z bazą danych do narzędzi, bez wycieku tych informacji do LLM.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 13 z 18. Jak powiedzieć funkcji, który użytkownik aktualnie czatuje, bez przypadkowego przekazania do LLM prywatnego ID użytkownika z bazy danych? Jeśli wrzucisz to w system prompt, ujawniasz wewnętrzne dane i marnujesz tokeny. Aby przekazać bezpieczny, lokalny state do swoich toolsów, używasz wstrzykiwania lokalnych zależności za pomocą RunContextWrapper. Częstym błędem podczas budowania agentów jest traktowanie modelu językowego jako pośrednika do wszystkiego. Deweloperzy często próbują osadzać connection stringi do bazy danych, wewnętrzne klucze API lub prywatne ID użytkowników bezpośrednio w instrukcjach systemowych. Robią to z nadzieją, że model posłusznie przekaże te wrażliwe dane uwierzytelniające z powrotem do tool calls jako parametry. To poważne zagrożenie bezpieczeństwa. Zużywa to również niepotrzebnie tokeny z context window i zwiększa ryzyko, że model wyhalucynuje nieprawidłowe parametry. Prawidłowe podejście to całkowite pominięcie modelu językowego dla twojego lokalnego execution state. RunContextWrapper zapewnia bezpieczną warstwę transportową do wstrzykiwania zależności bezpośrednio do twoich toolsów i lifecycle hooks. Atrybut context dołączony do tego wrappera to wyłącznie lokalny state w Pythonie. Model nigdy go nie widzi, nigdy go nie czyta i nigdy nie musi o nim wnioskować. Weźmy konkretny scenariusz. Zalogowany użytkownik czatuje z twoim agentem obsługi klienta i prosi o pokazanie ostatnich danych rozliczeniowych. Twój system musi pobrać te rekordy, co oznacza, że twój billing tool wymaga wewnętrznego ID użytkownika, aby bezpiecznie wykonać zapytanie do bazy danych. Najpierw definiujesz swoją lokalną zależność w kodzie aplikacji. Możesz stworzyć ustrukturyzowaną data class o nazwie UserInfo, która przechowuje wewnętrzne ID użytkownika. Następnie piszesz funkcję toola do pobierania historii rozliczeń. W sygnaturze tej funkcji toola definiujesz parametr odpowiednio otypowany, by przyjąć obiekt context. SDK rozumie ten type hint i wie, żeby nie ujawniać tego parametru modelowi językowemu. W ciele funkcji odwołujesz się do parametru context, wyciągasz zależność UserInfo i używasz tego prywatnego ID użytkownika, żeby bezpiecznie odpytać swój backend. I tu jest kluczowa sprawa. Kiedy przygotowujesz się do odpalenia agent run, nie przekazujesz tylko surowej wiadomości od użytkownika. Tworzysz instancję RunContextWrapper. Podpinasz swoją wypełnioną data class UserInfo bezpośrednio do wrappera. Następnie przekazujesz ten wrapper do runnera. Cała logika automatycznie zajmuje się resztą. Kiedy użytkownik prosi o historię rozliczeń, model językowy decyduje się wywołać twój billing tool. Model dostarcza tylko te argumenty, które zna z publicznej konwersacji, na przykład filtrując po konkretnym miesiącu lub numerze faktury. Nie ma absolutnie pojęcia, kim jest użytkownik na twoim backendzie. Zanim funkcja faktycznie się wykona, SDK przechwytuje to wywołanie. Sprawdza sygnaturę toola, zauważa, że tool wymaga lokalnego contextu, i automatycznie wstrzykuje state, który podpiąłeś do RunContextWrapper. Tool wykonuje się z użyciem bezpiecznego ID użytkownika, pobiera rekordy i zwraca dane do modelu, żeby sformułować odpowiedź. Dokładnie ten sam mechanizm dependency injection działa dla execution hooks, pozwalając ci płynnie przekazywać aktywne connection poole do bazy danych albo tracing IDs do twojego event loggingu. Oddzielając zewnętrzne wnioskowanie modelu od wewnętrznego wykonywania twojego kodu, twoja infrastruktura pozostaje bezpieczna, a twoje prompty skupiają się wyłącznie na zachowaniu. Trzymaj swoje execution dependencies całkowicie lokalnie i wymuś na swojej architekturze całkowite poleganie na bezpiecznym state wstrzykiwanym w runtime. Dzięki za wysłuchanie, miłego dnia wszystkim!
14

USB-C dla AI: Wprowadzenie do MCP

3m 47s

Wprowadzenie do Model Context Protocol (MCP). Odkryj, jak ten standard działa jako uniwersalne złącze, pozwalające łatwo podłączyć agentów AI do platform SaaS.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 14 z 18. Przestań pisać customowe wrappery API za każdym razem, gdy twój agent musi komunikować się z nową usługą. Jeśli masz dość ręcznego mapowania endpointów REST na JSON schemas tylko po to, żeby twój model językowy zrozumiał, co robi dana usługa, to w końcu mamy uniwersalny standard. Przyjrzymy się Model Context Protocol, czyli MCP, i temu, jak go używać. Pomyśl o MCP jak o porcie USB-C dla AI. Przed USB-C każde urządzenie potrzebowało specyficznego, dedykowanego kabla do ładowania. W świecie AI każdy zewnętrzny system wymaga customowego glue code'u. Jeśli chcesz, żeby agent odczytał bazę danych albo utworzył ticket w supporcie, piszesz klienta REST. Następnie piszesz skomplikowane schema, które opisuje tego klienta dla modelu. Na koniec piszesz logikę, która przechwytuje odpowiedź modelu i odpala właściwy request HTTP. MCP zastępuje tę ręczną robotę. To otwarty standard, który dokładnie określa, jak narzędzia mają opisywać siebie, swoje inputy i outputy bezpośrednio do modelu AI. Ludzie często mylą MCP ze standardowymi REST API. REST API przesyła dane między maszynami, ale oczekuje, że z góry będziesz dokładnie wiedzieć, jak ustrukturyzować request. MCP standaryzuje warstwę discovery. Serwer MCP mówi agentowi dokładnie, jakie narzędzia udostępnia i jakie parametry są wymagane, używając dokładnie takiego formatu, jakiego potrzebuje model. W OpenAI Agents SDK korzystasz z tych zewnętrznych serwerów MCP za pomocą klasy Hosted MCP Tool. I tu jest kluczowa sprawa. W ogóle nie redefiniujesz schema narzędzia w swoim kodzie w Pythonie. Zamiast tego, inicjalizujesz Hosted MCP Tool, podając mu URL zdalnego serwera MCP. To połączenie działa po Server-Sent Events, co pozwala serwerowi bezpiecznie pushować aktualizacje z powrotem do twojego agenta. Kiedy podpinasz ten Hosted MCP Tool do setupu swojego agenta, następuje handshake. Agent łączy się ze zdalnym serwerem, pyta, jakie narzędzia są dostępne, pobiera ich gotowe opisy i automatycznie je rejestruje. Przełóżmy to na konkretny scenariusz. Chcesz dać swojemu agentowi możliwość planowania spotkań. Bez MCP musiałbyś przestudiować API Google Calendar. Napisałbyś funkcję w Pythonie do autentykacji i tworzenia eventów. Następnie napisałbyś schema narzędzia, żeby agent wiedział, jak wygląda tytuł eventu albo timestamp. Z MCP deployujesz zdalnie gotowy serwer MCP dla Google Calendar. W kodzie swojej aplikacji tworzysz nową instancję Hosted MCP Tool i kierujesz ją na ten zdalny URL. Przekazujesz tę jedną instancję do swojego agenta. Zdalny serwer natychmiast mówi agentowi, że ma narzędzie o nazwie schedule meeting. Kiedy model językowy zdecyduje się zaplanować to spotkanie, SDK robi proxy tego calla. Bezpiecznie routuje request przez sieć do zdalnego serwera, wykonuje akcję i zwraca wynik. Nie napisałeś przy tym ani jednej linijki logiki integracji z kalendarzem. Prawdziwą mocą MCP jest decoupling głównej logiki twojego agenta od zewnętrznych integracji, co pozwala ci podmieniać lub aktualizować serwisy backendowe po prostu zmieniając URL. Dzięki za wysłuchanie, happy coding wszystkim!
15

Łączenie lokalnych serwerów MCP przez Stdio i HTTP

3m 54s

Zanurz się głębiej w MCP, uruchamiając standardowe serwery lokalne. Naucz się bezpiecznie izolować dostęp do systemu plików i wewnętrznych narzędzi za pomocą MCPServerStdio.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 15 z 18. Przyznanie modelowi językowemu bezpośredniego dostępu do twojego lokalnego systemu plików brzmi jak absolutny koszmar dla bezpieczeństwa. Ale jeśli ściśle odizolujesz ten dostęp w sandboxie za pomocą ustandaryzowanego protokołu, staje się to bezpiecznym i potężnym sposobem na przetwarzanie lokalnych danych. Dzisiaj przyjrzymy się łączeniu lokalnych serwerów MCP przez stdio i HTTP. Model Context Protocol definiuje, jak twoje agenty komunikują się z zewnętrznymi narzędziami i źródłami danych. Kiedy chcesz uruchomić te serwery we własnej infrastrukturze, OpenAI Agents SDK dostarcza dwie lokalne metody transportu. Pierwsza z nich to standardowe wejście i wyjście, wykorzystująca klasę o nazwie MCPServerStdio. Ludzie czasem myślą, że wymaga to skomplikowanej konfiguracji lokalnej sieci. Wcale tak nie jest. Kiedy używasz transportu stdio, SDK po prostu uruchamia serwer MCP jako lokalny child process. Agent wysyła requesty, zapisując je na standardowe wejście tego procesu, i odczytuje odpowiedzi z jego standardowego wyjścia. Wyobraź sobie scenariusz, w którym chcesz, żeby twój agent czytał pliki, ale tylko z jednego, konkretnego lokalnego katalogu. Tworzysz instancję MCPServerStdio i przekazujesz jej komendę do uruchomienia. Na przykład, możesz przekazać komendę Node Package Managera, czyli npx, a po niej argumenty do odpalenia oficjalnego serwera systemu plików MCP i ścieżkę bezwzględną do twojego docelowego katalogu. Ponieważ ten serwer działa jako subprocess, musisz zarządzać jego cyklem życia. Jeśli twój skrypt w Pythonie zakończy działanie lub się wywali, nie chcesz, żeby osierocony proces Node'a wisiał gdzieś w tle. SDK wymusza czyste zarządzanie cyklem życia, wymagając asynchronicznego context managera. Definiujesz blok async with, żeby zainicjować serwer stdio. Kiedy wykonanie wchodzi do tego bloku, SDK uruchamia child process. Kiedy wykonanie wychodzi z bloku, czysto zamyka ten proces. Wewnątrz tego bloku łączysz działający serwer ze swoim agentem. Tworzysz klienta MCP, przekazujesz mu swoją instancję serwera stdio, a następnie podajesz tego klienta swojemu agentowi. Twój agent ma teraz ograniczony, tymczasowy dostęp do twojego lokalnego katalogu. A co, jeśli chcesz wystawić prywatne, wewnętrzne API albo połączyć się z serwisem, który już działa? Nie chcesz do tego odpalać nowego subprocessu. I tu dochodzimy do drugiej opcji transportu, czyli MCPServerStreamableHttp. Zamiast przekazywać wykonywalną komendę, podajesz tej klasie URL twojego istniejącego serwisu. To idealne rozwiązanie do bezpiecznego podłączenia twojego agenta do wewnętrznego mikroserwisu działającego na localhost. Agent komunikuje się, streamując dane po HTTP. I tu jest kluczowa sprawa. Sam agent nie ma pojęcia, który transport wybrałeś. Kod połączenia w twojej aplikacji wygląda dokładnie tak samo. Nadal używasz context managera, nadal tworzysz klienta MCP i nadal przekazujesz go agentowi. SDK całkowicie abstrahuje warstwę transportową. Najbardziej przydatnym wnioskiem z tego jest to, że możesz stworzyć customowe narzędzie jako lokalny skrypt stdio do testów, a później zdeployować je jako samodzielny serwis HTTP na produkcji, bez zmieniania ani jednej linijki logiki twojego agenta. To wszystko w tym odcinku. Dzięki za wysłuchanie i kodujcie dalej!
16

Wizualizacja przepływów pracy z wbudowanym Tracingiem

3m 26s

Wyeliminuj debugowanie za pomocą instrukcji print, korzystając z wbudowanej w SDK obserwowalności (observability). Odkryj, jak automatyczne spany (spans) i ślady (traces) łączą całe złożone przepływy pracy.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 16 z 18. Debugowanie systemu wieloagentowego za pomocą printów to koszmar. Patrzysz na przewijające się logi, próbując ręcznie dopasować wykonanie tool calla w linijce pięćdziesiątej do generacji modelu w linijce dwusetnej. Na szczęście już nigdy więcej nie musisz tego robić. Ten odcinek jest o wizualizacji workflow z wbudowanym tracingiem. Kiedy programiści zaczynają budować złożone workflow agentów, ich pierwszym odruchem jest często pisanie własnych wrapperów do logowania. Piszą boilerplate, żeby dokładnie śledzić, kiedy agent startuje, jakie argumenty dostaje tool i ile czasu zajmuje modelowi odpowiedź. Nie rób tego. Agents SDK robi to za ciebie, całkowicie out of the box. Za każdym razem, gdy odpalasz agenta, prosisz o generację lub triggerujesz tool call, SDK automatycznie opakowuje tę akcję w span. Span to po prostu ustrukturyzowany zapis pojedynczej operacji w czasie. Te spany przechwytują inputy, outputy i czas trwania zadania. Są one automatycznie wysyłane do dashboardu OpenAI. Oznacza to, że dostajesz pełną wizualną oś czasu wykonania twojego workflow bez pisania ani jednej linijki kodu do telemetrii. Oto kluczowa sprawa. Podczas gdy SDK ogarnia najdrobniejsze detale, ty kontrolujesz grupowanie na wysokim poziomie. Powiedzmy, że masz scenariusz multi-turn, w którym agent generuje żart, drugi agent go ocenia, a pierwszy agent poprawia go na podstawie feedbacku. Domyślnie SDK będzie śledzić każdą z tych generacji modelu i tool calli jako oddzielne spany. Ale dla człowieka patrzącego na dashboard, cała ta wymiana to po prostu jedna logiczna jednostka pracy. Możesz pogrupować te akcje używając własnego bloku trace. Otwierasz blok kontekstu za pomocą funkcji trace i nadajesz mu opisową nazwę, na przykład joke generation loop. Wewnątrz tego bloku wykonujesz logikę swojego agenta multi-turn. SDK respektuje tę hierarchię. Zagnieździ wszystkie automatycznie wygenerowane spany dla poszczególnych uruchomień, ewaluacji i poprawek pod twoim własnym nadrzędnym trace'em. Kiedy otworzysz dashboard OpenAI, najpierw zobaczysz główny joke generation loop. Możesz go potem rozwinąć, żeby zbadać dokładną sekwencję wywołań modelu i tool calli, które wydarzyły się w środku. To załatwia sprawę widoczności, ale co z prywatnością? Są sytuacje, w których absolutnie nie możesz wysyłać telemetrii. Jeśli twój agent przetwarza wrażliwe dane medyczne, finansowe albo wymaga ścisłej zgodności z Zero Data Retention, wysyłanie logów z inputem i outputem do dashboardu jest naruszeniem bezpieczeństwa. Dla takich sytuacji SDK udostępnia blok kontekstu tracing disabled. Kiedy opakujesz wykonanie swojego agenta w ten blok, SDK całkowicie przestaje generować i wysyłać spany. Wykonanie przebiega lokalnie, wynik wraca do twojej aplikacji, ale żaden ślad promptu, tool calli ani odpowiedzi nie pojawi się na dashboardzie OpenAI. Kiedy kod wyjdzie z tego wyłączonego bloku, normalny automatyczny tracing zostaje wznowiony dla reszty twojej aplikacji. Tracing w SDK oznacza, że przestajesz pisać boilerplate do logowania, zyskujesz natychmiastowe wizualne debugowanie i nadal masz pełną kontrolę nad tym, kiedy twoje dane zostają całkowicie lokalne. To wszystko w tym odcinku. Dzięki za wysłuchanie i budujcie dalej!
17

Głos o niskim opóźnieniu z Realtime Agents

4m 17s

Przełam standardowy paradygmat żądanie-odpowiedź. Zobacz, jak Realtime Agents utrzymują aktywne połączenia WebSocket, aby obsługiwać przerwania i wnioskowanie multimodalne.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 17 z 18. Najtrudniejszą częścią budowania voice AI nie jest generowanie mowy. Chodzi o to, żeby wiedzieć, kiedy natychmiast się zamknąć, bo dzwoniący człowiek przerwał ci w połowie zdania. Jeśli polegasz na tradycyjnym cyklu request-response, network latency zawsze zdemaskuje bota. I dokładnie ten problem rozwiązuje Low-Latency Voice z Realtime Agents. Wielu developerów myli tę architekturę ze standardowym voice pipeline. W tradycyjnym setupie przechwytujesz audio, przepuszczasz je przez model Speech-to-Text, wysyłasz ten tekst do modelu językowego, a na końcu przepychasz output tekstowy przez syntezator Text-to-Speech. Ten pipeline wprowadza latency na każdym kroku. Realtime Agents całkowicie odrzucają ten pipeline. Używają pojedynczego, multimodalnego modelu, który natywnie wnioskuje na podstawie audio. Audio wchodzi bezpośrednio i audio streamuje się bezpośrednio na zewnątrz. System nie wymaga żadnego pośredniego tłumaczenia na tekst, żeby zrozumieć użytkownika. Żeby to osiągnąć, musisz złamać standardowy paradygmat HTTP request-response. Zamiast wysyłać payload i czekać na pełną odpowiedź, system utrzymuje otwarte, stałe połączenie. W SDK zarządzasz tym za pomocą dwóch głównych komponentów. Pierwszy to RealtimeAgent. Ten obiekt przechowuje twoje instrukcje systemowe oraz wszelkie funkcje lub toolsy, do których model potrzebuje dostępu. Definiuje logikę, możliwości i osobowość twojego asystenta. Drugi komponent to RealtimeRunner. Runner to silnik wykonawczy. Zarządza asynchronicznym event loopem i obsługuje stały stream sieciowy, zazwyczaj przez połączenie WebSocket lub WebRTC. Wyobraź sobie bota telefonicznej obsługi klienta, który odbiera połączenie przychodzące. Mostkujesz swojego voice providera, być może integrując się przez SIP lub WebSockets, i routujesz ciągłe audio do swojej aplikacji w Pythonie. Tworzysz swojego RealtimeAgenta, wyposażając go w tool do pobierania kont użytkowników. Następnie przekazujesz tego agenta i swojego klienta połączenia sieciowego do RealtimeRunnera. Kiedy wywołasz metodę run na runnerze, przejmuje on kontrolę. Utrzymuje połączenie przy życiu, stale nasłuchując streamu audio, jednocześnie obsługując wszelkie function calls, które agent musi wykonać. Współbieżnie pushuje i pulluje eventy w obu kierunkach. Użytkownik dzwoni i pyta o saldo swojego konta. Agent triggeruje tool do pobierania danych, pobiera je i natychmiast zaczyna streamować swoją głosową odpowiedź z powrotem do dzwoniącego. W połowie zdania użytkownik nagle wchodzi botowi w słowo, mówiąc, że tak naprawdę chce zgłosić zgubioną kartę. I tu jest kluczowa sprawa. Ponieważ połączenie WebSocket jest stale otwarte, a model natywnie przyjmuje przychodzący stream audio w czasie rzeczywistym, serwer natychmiast wykrywa ludzki głos. Odpala event, który zatrzymuje jego własny output audio i rejestruje ucięcie. Nie musisz pisać customowej logiki, żeby dokładnie obliczyć, który chunk audio był odtwarzany, kiedy użytkownik się odezwał. Architektura streamingowa bezproblemowo radzi sobie z przerwaniem. Model absorbuje nowy kontekst audio z tego przerwania i natychmiast zaczyna streamować zaktualizowaną odpowiedź o anulowaniu zgubionej karty. Zyskujesz naturalną dynamikę konwersacji wyłącznie dlatego, że warstwa sieciowa i warstwa modelu są zbudowane do ciągłego streamingu. Prawdziwą siłą Realtime API w Agents SDK jest traktowanie głosu jako pełnoprawnego, ciągłego streamu, a nie jako ukrytego batcha przetłumaczonego tekstu. To wszystko w tym odcinku. Dzięki za wysłuchanie i koduj dalej!
18

Budowanie reaktywnych interfejsów użytkownika dzięki Streaming Events

4m 13s

Wyjdź poza strumieniowanie tokenów tekstowych. Wykorzystaj Semantic Streaming Events do budowy niezwykle responsywnych interfejsów frontendowych, które reagują na działania agenta w czasie rzeczywistym.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. OpenAI Agents SDK, odcinek 18 z 18. Twoi użytkownicy nie chcą po prostu czytać tekstu, który wypisuje się na ekranie. Chcą dokładnie widzieć, co AI robi za kulisami. Jeśli próbujesz zbudować loading spinner, parsując surowe chunki tokenów, żeby zgadnąć, kiedy działa search tool, niepotrzebnie utrudniasz sobie życie. Budowanie reaktywnych UI za pomocą streaming events rozwiązuje dokładnie ten problem. Deweloperzy często traktują output AI jak zwykłą maszynę do pisania. Nasłuchują surowego streamu tekstu i piszą kruchą logikę do parsowania, żeby ustalić, czy agent zamierza wywołać funkcję. Takie podejście jest bardzo kruche. Psuje się, jeśli model choć trochę zmieni sposób formułowania zdań, a twój frontend zostaje w tyle za rzeczywistym execution state. OpenAI Agents SDK oferuje strukturalną alternatywę. Zamiast czekać na stringi, odpalasz agenta za pomocą metody run streamed na swoim runnerze. Ta metoda nie zwraca zwykłego tekstu. Zamiast tego zwraca asynchroniczną sekwencję semantycznych eventów, z których każdy jest spakowany jako obiekt Run Item Stream Event. Pomyśl o Run Item Stream Event jak o precyzyjnym powiadomieniu o wewnętrznym lifecycle agenta. Kiedy agent przetwarza request, emituje wyraźne, przewidywalne sygnały. Mówi ci dokładnie, kiedy nowa wiadomość zostaje dodana do threadu. Mówi ci, kiedy kontrola przechodzi z triage agenta do wyspecjalizowanego agenta. Co kluczowe dla frontend developmentu, podaje ci dokładną milisekundę, w której tool invocation się zaczyna i kończy. Przełóżmy to na konkretny scenariusz. Chcesz, żeby twój frontend wyświetlał spinner z napisem Searching database, podczas gdy agent szuka rekordu klienta. Wywołujesz run streamed i iterujesz po wynikach w pętli. Wewnątrz tej asynchronicznej pętli sprawdzasz każdy event, gdy tylko się pojawi. Kiedy event do ciebie trafia, sprawdzasz jego properties, żeby zobaczyć, jaki rodzaj update'u reprezentuje. Kiedy event wskazuje, że rozpoczął się tool call, możesz odczytać dokładną nazwę toola bezpośrednio z payloadu eventu. Nie musisz parsować żadnego języka naturalnego. Jeśli nazwa toola pasuje do twojej funkcji wyszukiwania w bazie danych, natychmiast pushujesz state update do frontendu, żeby wyrenderować spinner. Kiedy kolejny event zasygnalizuje, że tool execution dobiegło końca, dispatchujesz kolejny update, żeby ukryć spinner. Te stream events niosą ze sobą również standardowe message deltas. Jeśli agent generuje długą odpowiedź tekstową, stream emituje chunk events, które appendujesz do UI. Ta architektura oddziela surowy conversational output od semantycznych akcji. Routujesz text chunks do okna czatu, a tool i agent lifecycle events routujesz do swojego UI state managera. Takie separation of concerns pozwala ci budować interfejsy, które wydają się natychmiast responsywne i głęboko połączone z logiką agenta. Reagujesz na rzeczywisty execution path systemu, a nie zgadujesz jego intencje na podstawie słów. Oto kluczowy wniosek. Przestań traktować output agenta jako zwykły conversation stream. Traktuj go jak event-driven state machine, gdzie każda wewnętrzna akcja to okazja, żeby na bieżąco informować użytkownika wizualnie. Ponieważ to ostatni odcinek serii, zachęcam cię do przejrzenia oficjalnej dokumentacji i spróbowania samodzielnego orkiestrowania tych streamów. Jeśli masz pomysły na to, co powinniśmy poruszyć w przyszłej serii, wejdź na devstories dot eu i daj nam znać. To tyle w tym odcinku. Do usłyszenia następnym razem!