Voltar ao catálogo
Season 6 18 Episódios 1h 6m 2026

OpenAI Agents SDK

v0.13 — Edição de 2026. Um guia completo para criar sistemas multi-agent prontos para produção com o OpenAI Agents SDK para Python (v0.13 - 2026). Aprenda as core primitives, padrões de orquestração, tools, handoffs, guardrails, gestão de estado, MCP e integração de voz em realtime.

Frameworks de AI/ML Sistemas Multi-Agente
OpenAI Agents SDK
A Reproduzir
Click play to start
0:00
0:00
1
Para além do Swarm: As Core Primitives
Descubra os conceitos fundamentais do OpenAI Agents SDK. Este episódio aborda a razão da existência do SDK, como melhora em relação ao Swarm e os princípios fundamentais de design que priorizam abstrações mínimas.
3m 24s
2
Definir o Agent e o Run Loop
Aprenda a configurar o objeto fundacional Agent. Exploramos as instruções, as configurações do modelo e como forçar outputs de dados estruturados de forma contínua.
3m 17s
3
Equipar Agents com Python Function Tools
Capacite os seus agents para agirem, convertendo funções Python padrão em tools executáveis. Compreenda a geração automática de schemas e a inferência de tipos.
3m 10s
4
Escalar Superfícies de Tools com Hosted Tool Search
Aprenda a gerir bibliotecas massivas de tools sem esgotar o seu orçamento de tokens. Abordamos o carregamento diferido, namespaces e a execução de hosted tools.
3m 36s
5
Delegação Descentralizada: O Padrão Handoff
Domine a arte da orquestração multi-agent utilizando o padrão Handoff. Descubra como criar agents de triagem que delegam o controlo total para sub-agents especializados de forma contínua.
3m 28s
6
Orquestração Centralizada: Agents as Tools
Mantenha o controlo da conversa num só lugar utilizando o padrão Agents as Tools. Discutimos como um agent gestor pode sintetizar respostas de vários sub-agents especialistas.
4m 00s
7
Moldar o Contexto com Handoff Inputs e Filters
Otimize a utilização de tokens multi-agent modificando os históricos de conversação entre handoffs. Aprenda a injetar metadados e a aplicar transcript filters.
4m 01s
8
Controlar o Estado: to_input_list e Server IDs
Uma análise aprofundada à gestão manual de conversações. Compreenda os métodos de mais baixo nível para preservar o contexto entre turnos e utilizar response IDs do lado do servidor.
4m 24s
9
Automatizar a Memória com Sessions Integradas
Simplifique os seus chat loops com o sistema de memória integrado do SDK. Exploramos o SQLiteSession, o OpenAIConversationsSession e a persistência automatizada.
3m 54s
10
Proteger Workflows: Input e Output Guardrails
Proteja os seus pipelines de IA intercetando inputs maliciosos antes que cheguem a modelos caros. Abordamos guardrails ao nível do agent e a execução paralela vs. bloqueante.
3m 52s
11
Validar Ações: Tool-Level Guardrails
Previna fugas de dados críticas ao nível da função. Aprenda a envolver tools específicas com input e output guardrails precisos.
3m 55s
12
Pausar a Execução: Human-in-the-Loop e RunState
Implemente salvaguardas para ações irreversíveis forçando aprovações human-in-the-loop. Exploramos o pipeline de serialização RunState para pausar e retomar workloads.
3m 21s
13
Injetar Dependências Locais com RunContextWrapper
Domine a injeção de dependências nos fluxos do seu agent. Aprenda a passar estados locais e ligações a bases de dados de forma segura para as tools sem as divulgar ao LLM.
3m 46s
14
O USB-C para a IA: Introdução ao MCP
Uma introdução ao Model Context Protocol (MCP). Descubra como esta norma atua como um conector universal para ligar facilmente agents de IA a plataformas SaaS.
3m 29s
15
Ligar Servidores MCP Locais via Stdio e HTTP
Aprofunde os seus conhecimentos sobre o MCP executando servidores locais padrão. Aprenda a colocar em sandbox o acesso ao sistema de ficheiros e tools internas de forma segura com o MCPServerStdio.
3m 19s
16
Visualizar Workflows com Tracing Integrado
Elimine o debugging com print statements utilizando a observabilidade integrada do SDK. Descubra como spans e traces automáticos interligam workflows complexos inteiros.
3m 44s
17
Voz de Baixa Latência com Realtime Agents
Quebre o paradigma padrão de request-response. Veja como os Realtime Agents mantêm ligações WebSocket em direto para lidar com interrupções e raciocínio multimodal.
3m 50s
18
Construir UIs Reativas com Streaming Events
Vá além do streaming de tokens de texto. Utilize semantic streaming events para construir interfaces de frontend ultrarreativas que reagem às ações do agent em tempo real.
3m 49s

Episódios

1

Para além do Swarm: As Core Primitives

3m 24s

Descubra os conceitos fundamentais do OpenAI Agents SDK. Este episódio aborda a razão da existência do SDK, como melhora em relação ao Swarm e os princípios fundamentais de design que priorizam abstrações mínimas.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. Agents SDK da OpenAI, episódio 1 de 18. A maioria das frameworks de agentes de IA obriga-te a aprender uma dúzia de novas abstrações, sintaxe personalizada e hierarquias de objetos pesadas. Passas mais tempo a lutar contra a framework do que a escrever a lógica real da tua aplicação. Hoje, olhamos para Além do Swarm: As Primitivas Core. Quando os developers ouvem falar de uma nova framework de agentes, geralmente esperam um ecossistema enorme com uma curva de aprendizagem acentuada. O Agents SDK da OpenAI é exatamente o oposto. É uma evolução da library experimental Swarm. O Swarm provou que conseguias construir interações complexas com conceitos muito simples. O Agents SDK pega nessa filosofia e consolida-a para uso em produção. É deliberadamente leve e totalmente Python-first. A arquitetura baseia-se em dois princípios de design fundamentais: expor muito poucas primitivas core, e manter a execução altamente personalizável. Não precisas de um grafo complexo de nós ou de uma linguagem declarativa proprietária para construir um agent aqui. O SDK dá-te um pequeno conjunto de blocos de construção. A peça fundamental é o objeto Agent. Defines um Agent dando-lhe um nome e um conjunto de instruções. Se quiseres construir um tutor de história simples, instancias um Agent, dás-lhe o nome HistoryTutor, e passas-lhe uma string de texto com instruções para ensinar eventos históricos de forma clara e precisa. Essa é toda a configuração do teu agent. Não há estado oculto nem inicialização complicada. Mas um agent por si só é apenas uma estrutura de dados estática. Não faz nada até ser executado. É aqui que a coisa fica interessante. A execução é gerida inteiramente por um componente separado chamado Runner. O Runner gere todo o loop de interação entre o teu código local e a API remota da OpenAI. Numa aplicação típica, terias de escrever um while-loop customizado para verificar se o modelo quer fazer uma tool call, fazer o parse da resposta, executar a tool, e enviar o resultado de volta. O Runner abstrai tudo isso. Para iniciar o processo, passas o teu agent HistoryTutor e o prompt do utilizador para o método run. O Runner assume o controlo a partir daí. Ele envia o prompt para o modelo. Se o modelo decidir que precisa de procurar uma data histórica específica, vai pedir uma tool call. O Runner faz uma pausa, executa a função Python local que forneceste para essa tool, captura o valor de retorno, e envia-o logo de volta para o modelo. Ele repete este ciclo automaticamente. Só devolve o controlo à tua aplicação quando o modelo determina que a tarefa está concluída e gera uma resposta de texto final. Esta separação estrita entre a definição estática do Agent e a execução ativa do Runner é o que torna o SDK tão personalizável. Como as tools são apenas funções Python standard com type hints normais, e o agent é apenas um plain object, tu manténs o controlo total sobre o fluxo da tua aplicação. Podes facilmente injetar logging customizado, métricas, ou tratamento de erros à volta do Runner sem fazer override a classes profundas da framework. Estás apenas a escrever Python. O verdadeiro valor deste SDK não está no que ele adiciona, mas no que ele remove — ele sai do teu caminho e permite-te orquestrar modelos de linguagem usando código simples e legível. Se quiseres apoiar o programa, podes procurar por DevStoriesEU no Patreon. É tudo por este episódio. Até à próxima!
2

Definir o Agent e o Run Loop

3m 17s

Aprenda a configurar o objeto fundacional Agent. Exploramos as instruções, as configurações do modelo e como forçar outputs de dados estruturados de forma contínua.

Download
Olá, daqui fala o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 2 de 18. E se pudesses forçar o teu language model a responder sempre numa data structure perfeitamente parsed, sem escreveres uma única linha de regex complexa? Hoje, vamos abordar a definição do Agent e o Run Loop, que é exatamente como consegues esse controlo rigoroso. Um ponto comum de confusão ao começar a usar este SDK é pensar que um agent é um processo ativo em execução. Não é. Nesta arquitetura, o objeto Agent é estritamente um container de configuração. Ele encapsula um language model específico num contexto predefinido. Não se executa a si próprio e não mantém nenhum state por si só. Estás simplesmente a construir um blueprint. Para definir este blueprint, instancias um Agent. Começas com o parâmetro instructions. Este é o teu system prompt principal, onde defines a persona, os limites e as regras específicas que o modelo deve seguir. A seguir, forneces as model settings. Isto determina qual o modelo subjacente a usar e configura os detalhes standard de inferência. Nesta fase, o teu agent está totalmente definido, mas completamente adormecido em memória. É aqui que a coisa fica interessante. Podes restringir fisicamente o formato da resposta do agent usando o parâmetro output type. Imagina que estás a criar uma tool para extrair eventos de calendário de threads de email confusas. Em vez de escreveres instruções a implorar ao modelo para formatar as datas corretamente, defines uma data structure concreta no teu código. Defines uma classe Calendar Event com campos estritos para um título, uma hora de início e uma localização. Passas esta classe para o parâmetro output type do teu Agent. Quando configurado desta forma, a API impõe o schema. O agent não pode devolver uma resposta de texto conversacional. Ele apenas vai devolver um objeto Calendar Event validado que o código da tua aplicação pode ingerir imediatamente. Agora tens um blueprint de agent estrito e bem configurado. Para o pores a trabalhar a sério, precisas do Run Loop. Como o agent é apenas uma definição estática, a execução é gerida inteiramente por um componente Runner separado. O Runner é o motor. Passas a definição do teu agent e o user input para o Runner, e ele assume a execução. Quando fazes trigger do Runner, ele entra num execution loop. Ele agrupa as tuas agent instructions, o output schema estrito e o user prompt, e depois envia-os para o modelo. O run loop é responsável por gerir toda a orquestração de back-and-forth. Se o modelo decidir que precisa de chamar uma tool externa para ir buscar dados em falta, o Runner interceta esse pedido, corre o código da tool local e devolve o resultado ao modelo. Ele lida com todos estes passos intermédios automaticamente. O loop só termina quando o modelo resolve o prompt e produz o output final que corresponde exatamente ao teu output type de calendário. Manter a configuração estática do agent completamente separada do run loop ativo é o que te permite reutilizar com segurança esse exato mesmo agent de extração de calendário em milhares de execuções simultâneas, sem qualquer data bleeding. Obrigado por ouvirem, happy coding a todos!
3

Equipar Agents com Python Function Tools

3m 10s

Capacite os seus agents para agirem, convertendo funções Python padrão em tools executáveis. Compreenda a geração automática de schemas e a inferência de tipos.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 3 de 18. Escrever JSON schemas à mão para tools de modelos de linguagem é aborrecido e frágil. Uma chaveta em falta ou um type incompatível, e o modelo não consegue perceber como interagir com o teu sistema. Em vez de escreveres estas definições à mão, podes simplesmente escrever Python standard e deixar que a framework faça a tradução. É exatamente isso que vamos abordar hoje: equipar Agents com function tools de Python. Um equívoco comum é achar que expor lógica local a um agent exige manter duas fontes de verdade. As pessoas assumem que precisam do seu código Python, mais um ficheiro de configuração JSON separado e complexo que descreve esse código ao modelo de linguagem. Com o Agents SDK, evitas completamente a escrita manual de JSON. Simplesmente escreves uma função Python standard e colocas o decorator de function tool diretamente por cima dela. Quando aplicas esse decorator, o SDK começa a trabalhar nos bastidores usando o módulo inspect built-in do Python e o Pydantic. Ele analisa a signature da tua função. Lê os nomes dos parâmetros, extrai as type hints e retira a docstring da função. A partir desses elementos, gera automaticamente um JSON schema estrito e anexa-o ao agent. Vejamos um cenário concreto. Queres dar ao teu agent uma função chamada fetch weather. Esta função precisa de dados geográficos precisos para funcionar. Em vez de deixares o modelo adivinhar que formato de string usar, defines uma estrutura específica. Crias um type personalizado, talvez um Typed Dictionary chamado Location, contendo campos de string distintos para city e country. A seguir, usas este type Location como a type hint estrita para o parâmetro de input na tua função fetch weather. Aqui está o ponto chave. Tens de adicionar uma docstring clara a esta função. Podes escrever uma frase simples a indicar que esta tool obtém as condições meteorológicas atuais para uma cidade e país específicos. A framework extrai este texto e usa-o como a descrição principal da tool no prompt. A tua docstring já não é apenas uma nota útil para os teus colegas developers. É o manual de instruções literal que o agent avalia para decidir se deve acionar a tool. Se um utilizador perguntar se precisa de um casaco em Tóquio, o agent analisa as tools disponíveis. Lê a tua docstring, percebe que a função fetch weather fornece a resposta, e estrutura um request. Como fizeste o type hint do input com o teu dicionário Location, o Pydantic garante que o output do agent corresponde exatamente aos campos necessários antes mesmo da tua lógica Python ser executada. Se o modelo tentar passar uma única string de texto em vez do dicionário, a framework apanha o erro e força o agent a tentar novamente com a estrutura correta. O SDK executa a função localmente, captura o return value, e alimenta o resultado diretamente de volta no reasoning loop do agent. As tuas type hints e docstrings standard de Python já não são documentação passiva; formam o contrato de API ativo e vinculativo de que o teu agent depende para interagir com o mundo real. Obrigado por passares uns minutos comigo. Até à próxima, fica bem.
4

Escalar Superfícies de Tools com Hosted Tool Search

3m 36s

Aprenda a gerir bibliotecas massivas de tools sem esgotar o seu orçamento de tokens. Abordamos o carregamento diferido, namespaces e a execução de hosted tools.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 4 de 18. Passar cem tools para um modelo de linguagem destrói a performance e queima o teu orçamento de tokens antes de uma única ação ser executada. Não podes enfiar todos os schemas de API enterprise na context window inicial e esperar um bom raciocínio. A solução para isto é o scaling de tool surfaces com Hosted Tool Search. Antes de olharmos para o scaling, precisamos de definir hosted tools. As hosted tools executam nativamente na infraestrutura da OpenAI, em vez de correrem na tua máquina local. Exemplos built-in incluem a Web Search Tool e a File Search Tool. Não escreves a lógica de execução, não geres o web crawler, nem constróis o mecanismo de file chunking para estas tools. Anexas estas tools ao teu agent, e o backend da OpenAI trata do trabalho. Mas o conceito de hosted tools estende-se à forma como o modelo descobre as tuas próprias custom tools quando tens demasiadas. Considera um agent de Customer Relationship Management. Podes ter cinquenta tools distintas para verificar o status de encomendas, extrair o histórico de faturação, atualizar moradas de envio e recuperar logs de suporte. Se passares todos os cinquenta schemas logo à partida, sobrecarregas o modelo e desperdiças input tokens. Muitos developers acham que precisam de resolver isto construindo um passo de retrieval client-side. Eles assumem que devem intercetar o prompt do utilizador, pesquisar numa vector database local por schemas de tools relevantes, e injetá-los dinamicamente no prompt antes de chamar o modelo de linguagem. Não precisas de fazer isso. O Hosted Tool Search acontece nativamente nos servidores da OpenAI usando a Responses API. O próprio modelo é capaz de pesquisar a tool surface disponível sem que o teu client code atue como intermediário. Consegues isto usando dois parâmetros: tool namespace e defer loading. Quando registas as tuas tools de CRM, agrupas funções relacionadas atribuindo-as a um namespace partilhado. Por exemplo, podes colocar todas as tuas tools de perfil de cliente num namespace chamado customer account. A seguir, defines o parâmetro defer loading como true para essas tools. Esta é a parte que importa. Quando o defer loading está ativo, o agent não envia os schemas individuais das tools para o modelo de linguagem no início da conversa. Em vez disso, envia um único schema leve que representa o próprio namespace customer account. O modelo fica a saber que este namespace existe e sabe como o consultar, se necessário. Quando o utilizador pede para procurar um ID de cliente específico, o modelo percebe que precisa de mais informação. Ele executa uma pesquisa nativamente no namespace customer account. Os servidores da OpenAI encontram a tool de faturação ou suporte relevante, carregam apenas o schema dessa tool específica para o context do modelo, e depois o modelo executa a tool call. Isto desacopla completamente o tamanho da tua tool library do teu custo inicial de tokens. Podes anexar centenas de tools a um único agent, e o prompt inicial continua minúsculo. O modelo só incorre no preço de tokens para os schemas de tools específicos que decide ativamente puxar em runtime. Ao fazer o defer loading, estás a trocar um enorme peso de context estático por um mecanismo de retrieval dinâmico e preciso. É tudo por este episódio. Até à próxima!
5

Delegação Descentralizada: O Padrão Handoff

3m 28s

Domine a arte da orquestração multi-agent utilizando o padrão Handoff. Descubra como criar agents de triagem que delegam o controlo total para sub-agents especializados de forma contínua.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 5 de 18. Às vezes, a melhor maneira de um gestor lidar com uma tarefa complexa é simplesmente afastar-se. Se o teu agente de routing principal tentar mediar cada interação entre um utilizador e os teus sistemas de backend, os teus prompts ficam sobrecarregados e a tua execução torna-se instável. É exatamente isto que a Decentralized Delegation, especificamente o Handoff Pattern, foi desenhada para resolver. Um handoff é um mecanismo onde um agente transfere o controlo total da conversa para outro agente. Um erro comum é confundir um handoff com um tool calling normal. Eles são fundamentalmente diferentes. Quando um agente chama uma função normal, ele faz uma pausa, espera que os dados retornem e, em seguida, formula uma resposta para o utilizador. Quando um agente aciona um handoff, ele cede o turno inteiro da conversa. O controlo passa completamente para o novo agente. O agente original afasta-se completamente. Isto é importante porque mantém a tua arquitetura descentralizada. Se um agente de triagem central tiver de processar o output de cada ação de um especialista, o seu system prompt tem de ser enorme. Ele precisa de instruções sobre como formular políticas de reembolso, troubleshooting técnico e eliminação de contas. Pior ainda, o agente de triagem vai inevitavelmente tentar narrar o trabalho do especialista de volta para o utilizador. Isto desperdiça tokens, adiciona latência e introduz um alto risco de alucinação. Os handoffs evitam isto, permitindo que o especialista fale diretamente com o utilizador. Considera um sistema de suporte ao cliente. Fazes o deploy de um agente de triagem geral para receber os utilizadores e categorizar os pedidos. Um cliente entra em contacto a pedir para processar um reembolso. Também tens um agente de reembolso dedicado, que está equipado com tools de faturação específicas e instruções rigorosas sobre a política de devoluções da empresa. Para os ligar usando o SDK, escreves uma função normal chamada transfer to refund. Mas, em vez de retornar uma string ou dados em JSON, esta função retorna o teu objeto do agente de reembolso. A seguir, passas esta função de transferência para o teu agente de triagem, listando-a como qualquer outra tool. Quando o cliente pede um reembolso, o agente de triagem decide chamar a função de transferência. Aqui está o ponto-chave. O runner loop do SDK subjacente executa a função e percebe que foi retornado um objeto Agent em vez de dados normais. O runner troca instantaneamente o agente ativo na sua memória. Ele pega no histórico de conversas existente e envia-o diretamente para o agente de reembolso recém-ativado. O agente de reembolso assume o turno ativo, processa o pedido do utilizador, aciona as suas próprias tools de faturação e responde diretamente ao utilizador. Também podes passar dados durante esta transição. Se o agente de triagem já pediu o número da encomenda ao utilizador, pode passar esse número da encomenda como argumento para a função de transferência. A função pode então injetar esse número da encomenda nas context variables do novo agente antes de o retornar. O agente de reembolso acorda já a saber exatamente qual transação procurar. Ao usar handoffs, manténs cada agente pequeno, focado e previsível, deixando a conversa fluir naturalmente de um especialista para o próximo. É tudo por este episódio. Obrigado por ouvires, e continua a desenvolver!
6

Orquestração Centralizada: Agents as Tools

4m 00s

Mantenha o controlo da conversa num só lugar utilizando o padrão Agents as Tools. Discutimos como um agent gestor pode sintetizar respostas de vários sub-agents especialistas.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. Agents SDK da OpenAI, episódio 6 de 18. Se o teu assistente de IA precisa de consultar três departamentos diferentes antes de responder a um utilizador, raramente queres que o utilizador fale diretamente com esses departamentos. Queres uma única voz consistente a conduzir a conversa, a ir buscar informações silenciosamente nos bastidores. É exatamente isso que a orquestração centralizada usando Agents como Tools te permite fazer. Podes confundir isto com handoffs, onde um agent passa o utilizador permanentemente para outro agent. Com handoffs, o novo agent assume a conversa por completo. Com a orquestração centralizada, o controlo nunca é passado. O agent principal, geralmente a atuar como manager, mantém o controlo absoluto sobre a conversa. O manager é a única voz que o utilizador ouve. Consegues isto ao pegar num agent totalmente configurado e transformá-lo numa função callable. Cada objeto agent no SDK tem um método chamado as_tool. Quando chamas este método, ele faz o wrap de todo o agent, incluindo as suas instruções específicas e as suas próprias tools, num formato de tool standard. A seguir, passas este agent com o wrap ao teu agent manager, exatamente como passarias uma função Python standard. Vejamos um cenário prático. Estás a construir um portal de suporte ao cliente. Crias um agent especialista em reservas. O seu único trabalho é fazer queries a sistemas internos, cruzar datas e devolver a disponibilidade. Este agent é altamente técnico. As suas instruções são otimizadas para precisão na base de dados, não para uma conversa educada. Não queres que o utilizador interaja com este especialista. Por isso, chamas o método as_tool no especialista em reservas. A seguir, crias o teu agent manager. Dás ao manager instruções estritas para manter um tom corporativo e educado, e gerir a relação com o utilizador. Depois, adicionas o especialista em reservas com o wrap à lista de tools do manager. Quando um utilizador pede ao manager para verificar a disponibilidade para a próxima terça-feira, o manager processa o pedido. Ele reconhece que não tem os dados reais, mas sabe que tem uma tool que os pode encontrar. O manager invoca a tool de reservas. Aqui está o ponto chave. Quando essa tool é invocada, o agent especialista em reservas acorda, executa os seus próprios passos internos isolados e produz uma resposta. Mas não envia essa resposta ao utilizador. Ele devolve um resultado raw e factual diretamente ao manager. O manager recebe estes dados, sintetiza-os, faz o wrap numa saudação corporativa educada e, finalmente, responde ao utilizador. Este padrão hub-and-spoke resolve um grande problema em aplicações complexas: o context bloat. O agent manager não precisa de conhecer o schema da base de dados ou as regras para verificar datas. Mantém o seu system prompt limpo, focando-se inteiramente no routing de pedidos e na formatação de respostas. Entretanto, o agent especialista não precisa de se preocupar com o histórico da conversa ou com a voz da marca. Apenas faz o seu trabalho específico e devolve um resultado. Ao decidir entre um handoff e uma tool, pergunta a ti mesmo quem é o dono da resposta final. Se o agent especializado precisar de entrar num diálogo prolongado com o utilizador, queres um handoff. Mas se o agent especializado for apenas um processador de dados sofisticado a fornecer uma resposta para o assistente principal usar, faz o wrap como uma tool e deixa o manager ser o dono da relação. Obrigado por passares uns minutos comigo. Até à próxima, fica bem.
7

Moldar o Contexto com Handoff Inputs e Filters

4m 01s

Otimize a utilização de tokens multi-agent modificando os históricos de conversação entre handoffs. Aprenda a injetar metadados e a aplicar transcript filters.

Download
Olá, daqui fala o Alex da DEV STORIES DOT EU. Agents SDK da OpenAI, episódio 7 de 18. Ao transferires um cliente para um especialista humano, não obrigas o especialista a ler um transcript bruto e extenso de todas as verificações automatizadas do sistema que acabaram de ocorrer. Dás-lhe um motivo claro para a transferência e um resumo limpo do problema. No entanto, quando os developers ligam agentes de IA, muitas vezes despejam o chat log bruto inteiro na context window do agente seguinte. Hoje, vamos resolver isso a moldar o contexto com handoff inputs e filters. Quando um agente passa o controlo para outro, precisa de uma forma de comunicar o motivo do handoff. Fazes isso usando o parâmetro input type na tua rotina de handoff. Defines um schema, tipicamente um modelo Pydantic, que especifica exatamente que informação o agente que recebe precisa. Quando o agente atual decide executar o handoff, o language model subjacente gera um payload que corresponde a esse schema. Vamos já esclarecer uma confusão comum. É fácil confundir este input type com um state persistente da aplicação, como um ID de perfil de utilizador ou uma ligação a uma base de dados de backend que se mantém viva durante toda a sessão. Não é. O input type serve estritamente para metadados transitórios, gerados pelo modelo, criados exatamente no momento do handoff. Por exemplo, se um agente de triagem passar um utilizador para um especialista de faturação, o input type pode exigir um campo chamado escalation reason. O agente de triagem gera uma string curta que explica o erro específico de faturação, e o agente de faturação recebe esses dados estruturados imediatamente ao acordar. Isto trata da mensagem explícita de handover. Agora, temos de gerir o histórico da conversa. Por defeito, todo o histórico de mensagens viaja com o handoff. Cada prompt do utilizador, cada resposta do assistente e cada tool call em background são passados para a frente. Isto consome tokens rapidamente e enche a context window com ruído irrelevante. Controlas isto usando um input filter. Um input filter é uma função standard de Python que interceta o histórico da conversa mesmo antes de o agente que o recebe o ler. Recebe a lista completa de mensagens anteriores como argumento, processa-as e devolve uma nova lista de mensagens modificada. Considera um cenário onde o teu agente inicial passou dez turnos a chamar várias search tools e APIs de bases de dados a tentar resolver um problema, antes de finalmente desistir e encaminhar o utilizador para um agente de FAQ geral. O agente de FAQ só precisa das perguntas reais do utilizador. Não precisa de todo dos outputs JSON raw de dez tool calls falhadas. Para resolver isto, escreves uma função de input filter. Lá dentro, iteras pela lista de mensagens recebidas. Verificas o role de cada mensagem. Se a mensagem for uma execução de tool ou um tool result raw, descartas. Se for uma mensagem direta do utilizador ou uma resposta final do assistente, fazes append à tua nova lista. A seguir, devolves esta lista limpa e anexas a tua função de filter à definição do handoff. O agente de FAQ recebe agora um histórico simplificado que contém apenas a troca de mensagens human-readable. Aqui está o insight principal. Os handoff inputs adicionam inteligência estruturada à transição, enquanto os input filters cortam o ruído de forma implacável. Juntos, moldam exatamente o que o agente que recebe sabe. Poupas tokens, reduzes a latência e impedes que o novo agente tenha alucinações baseadas no raciocínio descartado do agente anterior. Controlar o contexto na fronteira de handoff é a forma mais eficaz de manter um sistema multi-agente rápido e preciso. Se quiseres ajudar a manter o programa no ar, podes procurar por DevStoriesEU no Patreon — o teu apoio significa muito. Por hoje é tudo. Obrigado por ouvires, e continua a construir!
8

Controlar o Estado: to_input_list e Server IDs

4m 24s

Uma análise aprofundada à gestão manual de conversações. Compreenda os métodos de mais baixo nível para preservar o contexto entre turnos e utilizar response IDs do lado do servidor.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 8 de 18. Um agente de IA com amnésia é inútil. Mas armazenar a sua memória incorretamente pode duplicar silenciosamente o histórico da conversa e duplicar os teus custos de API. Isto acontece quando misturas acidentalmente diferentes métodos de tracking do histórico do chat. Hoje vamos analisar o controlo de state: to_input_list e Server IDs. Por defeito, uma run básica de um agente é completamente stateless. Envias uma string, recebes uma string. Se fizeres uma pergunta de follow-up, o agente não tem contexto sobre o que acabaram de discutir. Tens de ser tu a fornecer o histórico. Embora o SDK ofereça session wrappers de alto nível, às vezes precisas da forma de mais baixo nível e mais transparente para manter o histórico do chat ao longo de vários turns, sem qualquer state magicamente oculto. Existem duas formas explícitas de lidar com isto. O primeiro método mantém a source of truth na tua máquina usando um método chamado to_input_list. Quando um agente termina uma run, devolve um result object. Este objeto contém a resposta final, mas também contém os passos ocultos que o agente deu para lá chegar. Se o agente fez uma tool call a uma base de dados, leu o output, e depois formulou uma resposta, todos esses passos intermédios fazem parte do state da conversa. Chamar to_input_list no result object empacota toda essa sequência. Devolve um array flat que contém o prompt original do utilizador, as respostas do agente, as tool calls específicas e os tool outputs. Formata tudo isto exatamente como a API espera receber. Se estiveres a construir um chat loop na linha de comandos, a lógica é esta. Defines uma variável para guardar o array da conversa. Inicialmente, contém apenas o primeiro prompt do utilizador. Passas este array para o agente. Quando o agente termina, pegas no resultado e chamas to_input_list, o que te dá o histórico completo e atualizado desse turn. Quando o utilizador escreve a sua segunda pergunta, fazes append manualmente da nova mensagem ao final dessa lista, e passas tudo de volta para o agente. Tens controlo total do payload. Agora, a segunda parte disto. Andar a passar um array enorme de mensagens anteriores e tool outputs em JSON para trás e para a frente na rede a cada turn consome largura de banda. Se quiseres evitar isso, podes usar server-side IDs. Cada resposta que recebes da API inclui um identificador único. Em vez de passares um array de mensagens anteriores para a próxima run do teu agente, passas um parâmetro chamado previous response id. Aqui está o ponto chave. Quando forneces um previous response ID, o teu client envia apenas a nova mensagem do utilizador. Não envias o array de histórico. O servidor da OpenAI procura esse ID, vai buscar a thread de contexto existente do lado dele, anexa-lhe a tua nova mensagem, e gera a resposta seguinte. Isto leva-nos a uma armadilha crítica. Podes sentir a tentação de misturar estas abordagens. Podes fazer append do user input à client-side list, passar essa lista completa para o agente, e também passar o previous response ID só para garantir. Não faças isto. Tens de escolher exatamente uma estratégia por conversa. Se forneceres tanto o array de histórico completo como um previous response ID, o servidor vai concatená-los. O teu agente vai ler a conversa inteira duas vezes, vai ficar confuso com as tool calls duplicadas, e tu vais pagar por esses tokens duas vezes. A escolha entre estes dois métodos resume-se a visibilidade versus eficiência. Usa client-side lists quando precisares de auditar, filtrar ou modificar o histórico da conversa entre turns. Usa server-side IDs quando confiares na raw thread e quiseres minimizar o teu network payload. É tudo por este episódio. Obrigado por ouvires, e continua a desenvolver!
9

Automatizar a Memória com Sessions Integradas

3m 54s

Simplifique os seus chat loops com o sistema de memória integrado do SDK. Exploramos o SQLiteSession, o OpenAIConversationsSession e a persistência automatizada.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 9 de 18. Estás a construir um chatbot persistente. Escreves código para ir buscar mensagens anteriores a uma base de dados, passá-las ao teu agent, extrair a nova response, e escrever a lista atualizada de volta na base de dados. É um boilerplate aborrecido que já escreveste dezenas de vezes. Hoje vamos analisar a automatização de memória com built-in sessions, que substitui toda essa lógica de read e write na base de dados por um único objecto. Vamos esclarecer um equívoco comum logo à partida. Quando os developers começam a usar sessions neste SDK, muitas vezes pensam que ainda precisam de ir buscar e passar manualmente o histórico de mensagens para o agent runner juntamente com a session. Não precisam. Passar um session object ao runner substitui completamente a gestão manual do histórico. Entregas as chaves. O runner recupera automaticamente as mensagens anteriores mesmo antes do conversation turn começar, e faz append automático das novas mensagens no momento em que o turn termina. Imagina um bot de Slack persistente que precisa de se lembrar das preferências do utilizador ao longo de vários dias. Queres guardar este state no disco sem configurar uma base de dados externa pesada. O SDK fornece uma tool built-in para isto chamada SQLite Session. Como interagir com um file system requer operações de input/output, esta tool é totalmente assíncrona. Para a usares, primeiro instancias uma SQLite Session, passando um file path para a tua base de dados local. A seguir, ligas-te a ela usando um async context manager. Pensa nisto como abrir uma ligação segura que garante que o ficheiro da base de dados é devidamente locked e unlocked. Dentro desse bloco de ligação, chamas o teu agent runner. Em vez de passares um array de mensagens anteriores ao runner, passas simplesmente o session object e um session ID. O session ID é apenas uma string única. Para o teu bot de Slack, este ID pode ser o user ID ou o channel ID. O runner pega nesse ID, pesquisa no ficheiro SQLite, faz load do histórico existente, processa o prompt do utilizador, e depois persiste o novo state de volta no ficheiro em segurança. Tudo isto acontece nos bastidores. Aqui está o ponto chave. Um histórico de conversação ilimitado vai acabar por quebrar os limites da tua context window. Não queres que uma conversa menor de há três meses infle o teu token usage ou faça crashar a tua API call hoje. Para controlar isto, o SDK fornece Session Settings. Quando chamas o runner, podes incluir um objecto de Session Settings juntamente com a própria session. Este objecto de settings aceita um parâmetro para o máximo de mensagens passadas. Se o definires para dez, o runner trunca automaticamente o histórico carregado. Ele mantém apenas as dez mensagens mais recentes no active context enviado para o model, mas o teu log histórico completo permanece intacto e seguro na base de dados SQLite. A SQLite Session é ideal para persistência local ou aplicações single server. Se o teu bot de Slack crescer e precisares de escalar para múltiplos servidores, o SDK lida com isso perfeitamente. Manténs o código do teu runner exatamente igual, mas trocas a SQLite session local por uma opção distribuída, como uma Redis Session ou uma Dapr Session. O principal takeaway é que as sessions forçam uma separation of concerns estrita. Ao configurares um session object e o passares ao runner, eliminas o boilerplate frágil de base de dados e garantes que a memória do teu agent está sempre perfeitamente sincronizada com o seu execution state. Por hoje é tudo. Obrigado por ouvires — vai construir algo fixe.
10

Proteger Workflows: Input e Output Guardrails

3m 52s

Proteja os seus pipelines de IA intercetando inputs maliciosos antes que cheguem a modelos caros. Abordamos guardrails ao nível do agent e a execução paralela vs. bloqueante.

Download
Olá, daqui fala o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 10 de 18. O teu modelo de raciocínio mais poderoso é também o mais caro. Se um utilizador o tentar enganar para lhe fazer os trabalhos de casa de matemática ou violar políticas de segurança, não vais querer descobrir isso depois de ele já ter passado dois minutos e mil tokens a pensar no assunto. Proteger os teus workflows com Input e Output Guardrails é a forma de evitares isso. Os guardrails ao nível do agent atuam como seguranças para os teus modelos principais. São funções separadas, muitas vezes alimentadas por modelos mais pequenos, mais rápidos e mais baratos, que validam os dados que entram ou saem do teu agent. Ao intercetar as requests, mantêm os teus modelos caros focados em trabalho real e garantem que a tua aplicação permanece segura e dentro do tema. Podes aplicá-los em dois lugares: no input e no output. Os input guardrails avaliam o prompt do utilizador antes que o teu agent principal comece a trabalhar. Imagina um cenário em que tens um modelo pesado e lento a lidar com análises financeiras complexas. Podes configurar um input guardrail usando um modelo rápido e leve para rever cada mensagem recebida. Quando um utilizador faz uma pergunta, este modelo rápido interceta-a. Ele verifica se o utilizador está a tentar que o agent faça um trabalho escolar, ou talvez a tentar um ataque de prompt injection. Se o input for sinalizado, o guardrail rejeita-o imediatamente e devolve uma mensagem de recusa padrão. O teu modelo de raciocínio pesado nem sequer acorda. Poupas tempo e poupas dinheiro. Os output guardrails lidam com a outra ponta da transação. Eles fazem uma verificação final antes de o utilizador ver a resposta. O agent principal concluiu a sua tarefa, mas precisas de garantir que não há fuga de dados sensíveis, ou que o tom está alinhado com as diretrizes da tua empresa. O output guardrail revê o texto gerado. Se detetar uma alucinação ou uma violação de política, bloqueia a mensagem antes de chegar ao utilizador. Aqui está o ponto-chave. A forma como estes guardrails impactam a tua aplicação depende inteiramente do seu execution mode. Podes executá-los em blocking mode ou em parallel mode. O blocking mode é uma sequência estrita. Um input guardrail tem de terminar a sua avaliação e devolver uma aprovação antes que o agent principal possa começar. Um output guardrail tem de terminar a verificação da resposta final antes de o utilizador receber uma única palavra. Esta é a abordagem mais segura e garante que não vais desperdiçar dinheiro com bad requests, mas adiciona latência à interação. O parallel mode troca o controlo rigoroso de custos por velocidade. Um equívoco comum é achar que a execução em paralelo pausa o agent principal enquanto o guardrail corre ao lado dele. Isso não acontece. No parallel mode, o input guardrail e o agent principal arrancam exatamente ao mesmo tempo. O agent está ativamente a gerar texto e a consumir tokens enquanto o guardrail ainda está a avaliar o input prompt. Se o guardrail decidir rejeitar a request, vai cancelar o agent principal a meio da execução. O utilizador continua protegido de ver o output, mas tu continuas a pagar pelos tokens que o agent principal consumiu antes de ser interrompido. Configuras isto definindo uma função simples que devolve uma decisão de pass ou fail, associando-a ao teu agent e declarando o seu modo. Alinha sempre o teu execution mode com as tuas prioridades: usa blocking guardrails para proteger a tua carteira de modelos caros, e parallel guardrails para proteger a experiência do utilizador da latência. É tudo por este episódio. Obrigado por ouvires, e continua a desenvolver!
11

Validar Ações: Tool-Level Guardrails

3m 55s

Previna fugas de dados críticas ao nível da função. Aprenda a envolver tools específicas com input e output guardrails precisos.

Download
Olá, daqui fala o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 11 de 18. Mesmo a IA mais inteligente pode acidentalmente expor um segredo da base de dados se puxar raw data diretamente para o seu context. Podes assumir que os teus top-level safety checks apanham tudo, mas esses só correm mesmo no início ou no fim de uma conversa. Se quiseres intercetar dados sensíveis a meio do workflow, precisas de Validating Actions, especificamente Tool-Level Guardrails. Uma armadilha comum é assumir que os agent-level guardrails protegem os teus sistemas subjacentes. Eles não protegem. Os agent guardrails processam o prompt inicial do utilizador ou a resposta final enviada de volta ao utilizador. Eles são cegos à troca de dados interna quando um agente chama uma base de dados ou uma API de terceiros. Se um prompt malicioso enganar o teu agente para chamar uma tool interna, os agent-level checks não o vão impedir. Para proteger as próprias tools, o OpenAI Agents SDK fornece tool guardrails. Estes ficam diretamente na função, atuando como um checkpoint obrigatório logo antes ou logo depois da tool executar. Existem dois tipos que precisas de conhecer. O primeiro é o tool input guardrail. Aplicas este decorator para validar argumentos antes da própria tool correr. Imagina que um agente tenta chamar uma tool que apaga uma conta de utilizador. O input guardrail interceta os argumentos que o agente gerou. Ele verifica se o user ID fornecido corresponde a um formato válido, ou se a sessão atual tem o nível de autorização correto. Se o input falhar esta verificação, o guardrail impede totalmente a tool de correr. Em vez de executar a eliminação, devolve uma mensagem de erro diretamente ao agente. O agente depois lê esse erro e pode tentar novamente com inputs corrigidos, sem nunca tocar na base de dados real. Agora, a segunda parte disto é o tool output guardrail. Este opera depois da tool executar com sucesso, mas antes do resultado ser devolvido ao agente. É aqui que filtras, mascaras ou validas o payload. Pega numa tool de database lookup como exemplo. O agente pede um perfil de developer, e a tool vai buscar o raw record. No entanto, esse registo por acaso contém uma API key ativa a começar pelas letras s-k-traço. Se essa raw key voltar para o agente, entra na context window do language model. Isso é um enorme risco de segurança. Para corrigir isto, adicionas um tool output guardrail a essa função de lookup específica. O guardrail pega no resultado bruto da base de dados, analisa o texto à procura desse padrão s-k-traço, e substitui a chave real por uma placeholder string como redacted. Só depois deste processo de limpeza é que os dados limpos são devolvidos ao agente. O agente continua a receber a informação de perfil de que precisa para responder ao utilizador, mas o segredo nunca sai da fronteira de execução isolada da tool. Esta é a parte que interessa. Em workflows multi-agent complexos, diferentes agentes especializados podem invocar tools em sequências imprevisíveis. Não podes depender de fazer prompting ao agente para se comportar de forma segura. Também não podes esperar que o filtro de output final apanhe um leak de uma chave mesmo antes de ir para o utilizador, porque, nessa altura, a chave já foi exposta ao language model. Tens de blindar a própria tool. Ao anexar o guardrail diretamente à função, a lógica de segurança viaja com a tool. Não importa qual agente a chama ou quando é chamada no workflow. A proteção é absoluta. Os tool guardrails tratam as tuas funções como zero-trust boundaries, garantindo que, por muito autónomo que o teu agente se torne, nunca poderá passar bad data para dentro, ou puxar dados sensíveis para fora. É tudo por este episódio. Obrigado por ouvires, e continua a programar!
12

Pausar a Execução: Human-in-the-Loop e RunState

3m 21s

Implemente salvaguardas para ações irreversíveis forçando aprovações human-in-the-loop. Exploramos o pipeline de serialização RunState para pausar e retomar workloads.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 12 de 18. Não deixarias um novo estagiário fazer drop a uma database de produção sem pedir permissão primeiro. O teu agente de IA também não o deveria poder fazer. Quando um agente tem acesso a tools altamente destrutivas ou sensíveis, precisas de uma forma de o parar, verificar o seu trabalho e dar luz verde manualmente. Isto resolve-se pausando a execução: Human-in-the-Loop e RunState. Se precisas que um humano aprove uma ação, o teu primeiro instinto pode ser pausar o script de Python e esperar por input do teclado. Não faças isso. Manter um processo vivo enquanto esperas por uma resposta de e-mail ou por um clique num dashboard desperdiça recursos do servidor. Também quebra completamente se o servidor reiniciar ou se fizeres deploy de código novo. O OpenAI Agents SDK lida com isto de forma limpa, permitindo que o processo de Python termine completamente e seja retomado mais tarde num servidor completamente diferente. Tudo começa na definição da tool. Quando escreves uma função para o teu agente, como uma tool chamada delete production database, aplicas uma flag a definir needs approval como true. Quando o agente processa um prompt e decide que tem de chamar esta tool específica, o engine para imediatamente. A tool não corre. Em vez disso, o runner devolve o controlo ao código da tua aplicação. Aqui está o ponto chave. Quando a execução para, o runner dá-te um objeto RunState. Este objeto guarda todo o contexto da run até àquele exato milissegundo. Ele conhece o histórico da conversa, o processo de pensamento interno do agente e a tool call específica que ele quer executar a seguir. Pegas neste objeto RunState e serializas numa string JSON standard. Guardas esse payload JSON na tua database, ou fazes push para uma queue, ou escreves no disco. Assim que esse state estiver guardado em segurança, o teu script de Python termina. A tua aplicação está agora idle. Podem passar horas ou até dias. Eventualmente, um engineering manager faz login num web dashboard, vê a eliminação pendente da database e clica em approve. Esse clique faz trigger a uma web request completamente nova. O teu backend acorda e lê o payload JSON guardado na database. Ele desserializa essa string de volta para um objeto RunState válido. Depois, inicias uma nova execução do runner. Passas a mesma instância do agente, o RunState restaurado e a decisão do humano. Se passares uma aprovação, o runner executa a tool de eliminação da database e o agente continua a responder ao utilizador. Se o manager clicou em reject, passas uma rejeição em vez disso. O runner não executa a tool. Ele devolve a rejeição ao agente como um tool error, forçando o agente a adaptar o seu plano ou a dizer ao utilizador que a ação foi negada. Ao serializar o RunState, transformas um script síncrono num workflow assíncrono, permitindo que humanos e agentes colaborem em segurança independentemente do intervalo de tempo, sem deixar um único processo do servidor pendurado. Se quiseres ajudar a manter o show a rolar, podes apoiar-nos procurando por DevStoriesEU no Patreon. Obrigado por estares aí. Espero que tenhas aprendido algo novo.
13

Injetar Dependências Locais com RunContextWrapper

3m 46s

Domine a injeção de dependências nos fluxos do seu agent. Aprenda a passar estados locais e ligações a bases de dados de forma segura para as tools sem as divulgar ao LLM.

Download
Olá, daqui fala o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 13 de 18. Como é que dizes a uma função qual é o utilizador que está a falar no momento, sem ensinar acidentalmente ao LLM o ID privado do utilizador na base de dados? Se o colocares no system prompt, estás a expor dados internos e a desperdiçar tokens. Para passares um state local e seguro para as tuas tools, usas a Dependency Injection local com o RunContextWrapper. Um erro comum ao construir agents é tratar o language model como o intermediário para tudo. Os developers tentam frequentemente embutir connection strings da base de dados, API keys internas ou identificadores privados de utilizadores diretamente nas system instructions. Fazem isto na esperança de que o modelo passe essas credenciais sensíveis de volta para as tool calls como parâmetros. Isto é um risco de segurança significativo. Também consome tokens desnecessários da context window e aumenta a probabilidade de o modelo alucinar parâmetros incorretos. A abordagem correta é contornar completamente o language model para o teu state de execução local. O RunContextWrapper fornece uma camada de transporte segura para injetar dependências diretamente nas tuas tools e lifecycle hooks. O atributo context associado a este wrapper é puramente state local de Python. O modelo nunca o vê, nunca o lê e nunca precisa de raciocinar sobre ele. Considera um cenário concreto. Um utilizador autenticado está a conversar com o teu agent de suporte ao cliente e pede para ver os seus registos de faturação recentes. O teu sistema precisa de fazer o fetch destes registos, o que significa que a tua tool de faturação precisa do ID interno do utilizador na base de dados para correr a query à base de dados com segurança. Primeiro, defines a tua dependência local no código da tua aplicação. Podes criar uma data class estruturada chamada User Info que guarda o ID interno do utilizador. A seguir, escreves a tua tool function para fazer o fetch do histórico de faturação. Na signature desta tool function, defines um parâmetro especificamente tipado para aceitar o objeto context. O SDK percebe este type hint e sabe que não deve expor este parâmetro ao language model. Dentro do corpo da função, acedes ao parâmetro context, extrais a tua dependência User Info e usas esse ID privado do utilizador para fazer uma query segura ao teu backend. Aqui está o ponto chave. Quando te preparas para executar a run do agent, não passas simplesmente a mensagem raw do utilizador. Crias uma instância do RunContextWrapper. Anexas a tua data class User Info preenchida diretamente ao wrapper. Depois, passas este wrapper para o execution runner. O fluxo lógico trata do resto automaticamente. Quando o utilizador pede o seu histórico de faturação, o language model decide acionar a tua tool de faturação. O modelo fornece apenas os argumentos que conhece da conversa pública, talvez a filtrar por um mês específico ou por um número de fatura. Não tem absolutamente nenhuma ideia de quem é o utilizador no teu backend. Antes de a função realmente correr, o SDK interceta a call. Inspeciona a signature da tool, percebe que a tool requer o context local e injeta automaticamente o state que anexaste ao RunContextWrapper. A tool é executada usando o ID seguro do utilizador, obtém os registos e devolve os dados ao modelo para formular uma resposta. Este exato mesmo mecanismo de dependency injection funciona para execution hooks, permitindo-te passar connection pools ativas da base de dados ou tracing IDs para o teu event logging de forma transparente. Ao separar o raciocínio externo do modelo da execução interna do teu código, a tua infraestrutura permanece segura e os teus prompts ficam totalmente focados no comportamento. Mantém as tuas dependências de execução completamente locais e força a tua arquitetura a depender inteiramente do state seguro injetado em runtime. Obrigado por ouvirem, tenham todos um ótimo dia!
14

O USB-C para a IA: Introdução ao MCP

3m 29s

Uma introdução ao Model Context Protocol (MCP). Descubra como esta norma atua como um conector universal para ligar facilmente agents de IA a plataformas SaaS.

Download
Olá, daqui fala o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 14 de 18. Para de escrever wrappers de API customizados sempre que o teu agente precisar de falar com um novo serviço. Se estás cansado de mapear manualmente endpoints REST para schemas JSON só para que o teu modelo de linguagem perceba o que um serviço faz, existe finalmente um standard universal. Vamos olhar para o Model Context Protocol, ou MCP, e como usá-lo. Pensa no MCP como a porta USB-C para a IA. Antes do USB-C, cada dispositivo precisava de um cabo de carregamento específico e proprietário. No mundo da IA, cada sistema externo requer glue code customizado. Se queres que um agente leia uma base de dados ou crie um ticket de suporte, escreves um cliente REST. Depois, escreves um schema complexo a descrever esse cliente ao modelo. Finalmente, escreves a lógica para apanhar a resposta do modelo e disparar o request HTTP propriamente dito. O MCP substitui esse trabalho manual. É um standard aberto que dita exatamente como as tools se descrevem a si próprias, aos seus inputs e aos seus outputs diretamente a um modelo de IA. As pessoas muitas vezes confundem o MCP com APIs REST standard. Uma API REST envia dados entre máquinas, mas espera que saibas exatamente como estruturar o request de antemão. O MCP standardiza a camada de discovery. Um servidor MCP diz ao agente exatamente que tools tem e que parâmetros são necessários, falando no formato exato de que o modelo precisa. No OpenAI Agents SDK, consomes estes servidores MCP externos usando uma classe chamada Hosted MCP Tool. Aqui está o ponto principal. Não redefines o schema da tool no teu código Python de todo. Em vez disso, inicializas a Hosted MCP Tool dando-lhe o URL de um servidor MCP remoto. Esta ligação opera sobre Server-Sent Events, o que permite ao servidor fazer push de atualizações de volta para o teu agente de forma segura. Quando anexas esta Hosted MCP Tool ao setup do teu agente, acontece um handshake. O agente liga-se ao servidor remoto, pergunta que tools estão disponíveis, faz pull das descrições completas e regista-as automaticamente. Vamos ancorar isto a um cenário concreto. Queres dar ao teu agente a capacidade de agendar reuniões. Sem o MCP, terias de estudar a API do Google Calendar. Escreverias uma função em Python para autenticar e criar eventos. Depois, escreverias o schema da tool para que o agente soubesse como é o título de um evento ou um timestamp. Com o MCP, fazes o deploy de um servidor MCP do Google Calendar pré-construído remotamente. No código da tua aplicação, crias uma nova instância da Hosted MCP Tool e apontas para esse URL remoto. Passas essa única instância ao teu agente. O servidor remoto diz instantaneamente ao agente que tem uma tool chamada schedule meeting. Quando o modelo de linguagem decide agendar essa reunião, o SDK faz proxy da chamada. Ele encaminha o request de forma segura pela rede para o servidor remoto, executa a ação e devolve o resultado. Escreveste zero linhas de lógica de integração com o calendário. O verdadeiro poder do MCP é desacoplar a lógica core do teu agente das integrações externas, permitindo-te trocar ou fazer upgrade aos serviços de backend apenas mudando um URL. Obrigado por ouvirem, bom código a todos!
15

Ligar Servidores MCP Locais via Stdio e HTTP

3m 19s

Aprofunde os seus conhecimentos sobre o MCP executando servidores locais padrão. Aprenda a colocar em sandbox o acesso ao sistema de ficheiros e tools internas de forma segura com o MCPServerStdio.

Download
Daqui fala o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 15 de 18. Dar acesso direto a um modelo de linguagem ao teu filesystem local parece um verdadeiro pesadelo de segurança. Mas se colocares esse acesso estritamente numa sandbox através de um protocolo standard, torna-se numa forma segura e poderosa de processar dados locais. Hoje, vamos explorar a ligação de servidores MCP locais via stdio e HTTP. O Model Context Protocol define como os teus agentes comunicam com ferramentas externas e fontes de dados. Quando queres correr estes servidores na tua própria infraestrutura, o OpenAI Agents SDK oferece dois métodos de transporte local. O primeiro é o standard input e output, usando a class chamada MCPServerStdio. Às vezes as pessoas pensam que isto requer um setup complexo de networking local. Mas não requer. Quando usas o transporte stdio, o SDK simplesmente faz spawn do servidor MCP como um child process local. O agente envia requests escrevendo no standard input desse processo e lê as respostas do seu standard output. Considera um cenário em que queres que o teu agente leia ficheiros, mas apenas de um diretório local específico. Instancias o MCPServerStdio e passas-lhe o comando para correr. Por exemplo, podes passar o comando do package manager do Node, npx, seguido pelos argumentos para iniciar o servidor oficial de filesystem do MCP, e o absolute path para o teu diretório de destino. Como este servidor corre como um subprocess, tens de gerir o seu lifecycle. Se o teu script Python terminar ou fizer crash, não vais querer um processo node órfão a correr em background. O SDK impõe uma gestão limpa do lifecycle, exigindo um context manager assíncrono. Defines um bloco async with para inicializar o servidor stdio. Quando a execução entra no bloco, o SDK faz spin up do child process. Quando a execução sai do bloco, faz o tear down do processo de forma limpa. Dentro desse bloco, ligas o servidor a correr ao teu agente. Crias um MCP client, passas-lhe a tua instance do servidor stdio e, em seguida, forneces esse client ao teu agente. O agente agora tem acesso temporário e com scope ao teu diretório local. Agora, e se quiseres expor uma API interna privada, ou ligar-te a um serviço que já está a correr? Não queres fazer spawn de um novo subprocess para isso. Isto leva-nos à segunda opção de transporte, que é o MCPServerStreamableHttp. Em vez de passares um comando executável, forneces a esta class o URL do teu serviço existente. Isto é perfeito para ligar o teu agente com segurança a um microservice interno a correr em localhost. O agente comunica fazendo streaming de dados por HTTP. Aqui está o ponto chave. O próprio agente não faz ideia de qual transporte escolheste. O código de ligação dentro da tua aplicação fica exatamente igual. Continuas a usar um context manager, continuas a criar um MCP client, e continuas a entregá-lo ao agente. O SDK abstrai completamente a transport layer. O ponto mais importante a reter aqui é que podes desenvolver uma custom tool como um script stdio local para testes, e mais tarde fazer o deploy dela como um serviço HTTP standalone em produção, sem alterar uma única linha da lógica do teu agente. É tudo por este episódio. Obrigado por ouvires, e continua a construir!
16

Visualizar Workflows com Tracing Integrado

3m 44s

Elimine o debugging com print statements utilizando a observabilidade integrada do SDK. Descubra como spans e traces automáticos interligam workflows complexos inteiros.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 16 de 18. Fazer debugging de um sistema multi-agent com print statements é um pesadelo. Ficas a ver os logs a passar, a tentar corresponder manualmente uma tool execution na linha cinquenta com uma model generation na linha duzentas. Felizmente, nunca mais vais ter de fazer isso. Este episódio é sobre visualizar workflows com built-in tracing. Quando os developers começam a construir agent workflows complexos, o seu primeiro instinto costuma ser escrever logging wrappers customizados. Escrevem boilerplate code para fazer o tracking exato de quando um agent arranca, que argumentos uma tool recebe, e quanto tempo o modelo demora a responder. Não construas isso. O Agents SDK trata disso por ti, completamente out of the box. Sempre que corres um agent, pedes uma generation, ou fazes trigger a uma tool call, o SDK faz automaticamente o wrap dessa ação num span. Um span é simplesmente um registo estruturado e cronometrado de uma única operação. Estes spans capturam os inputs, os outputs e a duração da tarefa. São enviados automaticamente para o dashboard da OpenAI. Isto significa que ficas com uma timeline visual completa da execução do teu workflow sem escreveres uma única linha de código de telemetria. Aqui está o ponto chave. Enquanto o SDK trata dos detalhes granulares, tu controlas o agrupamento de alto nível. Imagina que tens um cenário multi-turn onde um agent gera uma piada, um segundo agent a avalia, e o primeiro agent a refina com base no feedback. Por default, o SDK vai fazer o tracking de cada uma destas model generations e tool calls como spans distintos. Mas para um humano a olhar para um dashboard, todo este vaivém é apenas uma unidade lógica de trabalho. Podes agrupar estas ações usando um trace block customizado. Abres um context block usando a função trace e dás-lhe um nome descritivo, como joke generation loop. Dentro desse bloco, executas a lógica do teu agent multi-turn. O SDK respeita esta hierarquia. Vai fazer o nest de todos os spans gerados automaticamente para as runs, avaliações e refinamentos individuais debaixo do teu parent trace customizado. Quando abres o dashboard da OpenAI, vês primeiro o joke generation loop de top-level. Podes depois expandi-lo para investigar a sequência exata de model calls e tool executions que aconteceram lá dentro. Isto cobre a visibilidade, mas e a privacidade? Há momentos em que absolutamente não podes enviar telemetria. Se o teu agent lida com registos médicos sensíveis, dados financeiros, ou exige uma compliance rigorosa de Zero Data Retention, enviar logs de input e output para um dashboard é uma violação de segurança. Para estas situações, o SDK fornece um context block com tracing disabled. Quando fazes o wrap da execução do teu agent dentro deste bloco, o SDK para completamente de gerar e enviar spans. A execução corre localmente, o resultado é devolvido à tua aplicação, mas nenhum registo do prompt, das tool calls ou da response vai aparecer no dashboard da OpenAI. Assim que o código sai desse bloco disabled, o tracing automático normal é retomado para o resto da tua aplicação. O tracing no SDK significa que paras de escrever boilerplate logging, obténs visual debugging imediato, e ainda manténs controlo total sobre quando os teus dados permanecem inteiramente locais. É tudo por agora. Obrigado por ouvires, e continua a programar!
17

Voz de Baixa Latência com Realtime Agents

3m 50s

Quebre o paradigma padrão de request-response. Veja como os Realtime Agents mantêm ligações WebSocket em direto para lidar com interrupções e raciocínio multimodal.

Download
Olá, daqui é o Alex da DEV STORIES DOT EU. Agents SDK da OpenAI, episódio 17 de 18. A parte mais difícil de construir IA de voz não é gerar a fala. É saber quando se calar imediatamente porque o interlocutor humano interrompeu a meio da frase. Se dependes do ciclo tradicional de request e response, a latência da rede vai sempre denunciar o bot. Esse é exatamente o problema resolvido por Low-Latency Voice com Realtime Agents. Muitos developers confundem esta arquitetura com um pipeline de voz standard. Num setup tradicional, tu capturas o áudio, passas por um modelo de Speech-to-Text, envias esse texto para um language model e, finalmente, passas o output de texto por um sintetizador de Text-to-Speech. Esse pipeline introduz latência em cada passo. Os Realtime Agents descartam esse pipeline por completo. Eles usam um único modelo multimodal que raciocina nativamente sobre o áudio. O áudio entra diretamente, e sai diretamente em stream. Não é necessária nenhuma tradução intermédia de texto para que o sistema entenda o utilizador. Para conseguir isto, tens de quebrar o paradigma standard de request-response por HTTP. Em vez de enviar um payload e esperar por uma resposta completa, o sistema mantém uma ligação persistente aberta. No SDK, geres isto usando dois componentes principais. O primeiro é o RealtimeAgent. Este objeto guarda as tuas system instructions e quaisquer funções ou tools a que o modelo precise de ter acesso. Ele define a lógica, as capacidades e a personalidade do teu assistente. O segundo componente é o RealtimeRunner. O runner é o motor de execução. Ele gere o event loop assíncrono e lida com o stream de rede persistente, normalmente através de uma ligação WebSocket ou WebRTC. Imagina um bot de apoio ao cliente por telefone a lidar com uma chamada recebida. Fazes a ponte com o teu provider de voz, talvez a integrar via SIP ou WebSockets, a reencaminhar o áudio contínuo para a tua aplicação Python. Crias o teu RealtimeAgent, equipando-o com uma tool para fazer fetch de contas de utilizador. A seguir, passas esse agent e o teu cliente de ligação de rede para o RealtimeRunner. Quando chamas o método run no runner, ele assume o controlo. Ele mantém a ligação ativa, a ouvir constantemente o stream de áudio, enquanto lida simultaneamente com quaisquer function calls que o agent precise de fazer. Ele faz push e pull de events em ambas as direções em simultâneo. O utilizador liga e pede o saldo da sua conta. O agent aciona a tool de fetch da conta, obtém os dados e começa imediatamente a fazer stream da sua resposta falada de volta para quem ligou. A meio da frase, o utilizador fala de repente por cima do bot, dizendo que, na verdade, quer reportar um cartão perdido. Aqui está o ponto-chave. Como a ligação WebSocket está persistentemente aberta e o modelo ingere nativamente o stream de áudio de entrada em tempo real, o servidor deteta a voz humana instantaneamente. Ele dispara um event que interrompe o seu próprio output de áudio e regista a truncagem. Não tens de escrever lógica customizada para calcular exatamente que chunk de áudio estava a tocar quando o utilizador falou. A arquitetura de streaming lida com a interrupção de forma transparente. O modelo absorve o novo contexto de áudio da interrupção e começa imediatamente a fazer stream da resposta atualizada sobre o cancelamento do cartão perdido. Consegues dinâmicas conversacionais naturais inteiramente porque a network layer e a model layer são construídas para streaming contínuo. O verdadeiro poder da Realtime API no Agents SDK é tratar a voz como um stream contínuo de primeira classe, em vez de um batch de texto traduzido disfarçado. É tudo por este episódio. Obrigado por ouvires, e continua a desenvolver!
18

Construir UIs Reativas com Streaming Events

3m 49s

Vá além do streaming de tokens de texto. Utilize semantic streaming events para construir interfaces de frontend ultrarreativas que reagem às ações do agent em tempo real.

Download
Olá, daqui fala o Alex da DEV STORIES DOT EU. OpenAI Agents SDK, episódio 18 de 18. Os teus utilizadores não querem apenas ler o texto enquanto é escrito no ecrã. Querem ver exatamente o que a IA está a fazer nos bastidores. Se estás a tentar criar um loading spinner a fazer parsing de chunks de tokens raw para adivinhar quando uma search tool está a correr, estás a fazer isso da maneira mais difícil. Construir UIs reativas com streaming events resolve exatamente este problema. Os developers costumam tratar os outputs da IA como uma máquina de escrever básica. Ficam à escuta de uma stream de texto raw e escrevem lógica de parsing frágil para descobrir se o agent está prestes a chamar uma função. Essa abordagem é frágil. Falha se o modelo alterar ligeiramente a sua formulação, e deixa o teu frontend atrasado em relação ao state real de execução. O OpenAI Agents SDK oferece uma alternativa estrutural. Em vez de esperares por strings, acionas o teu agent usando um método chamado run streamed no teu runner. Este método não devolve plain text. Em vez disso, gera uma sequência assíncrona de eventos semânticos, cada um empacotado como um objeto Run Item Stream Event. Pensa num Run Item Stream Event como uma notificação precisa sobre o lifecycle interno do agent. À medida que o agent processa um request, emite sinais distintos e previsíveis. Diz-te exatamente quando uma nova mensagem é adicionada à thread. Diz-te quando o controlo é transferido de um agent de triagem para um agent especializado. De forma crucial para o desenvolvimento frontend, diz-te o milissegundo exato em que uma tool invocation começa e termina. Vamos aplicar isto a um cenário concreto. Queres que o teu frontend mostre um spinner a dizer A pesquisar na base de dados enquanto o agent procura um registo de cliente. Chamas o run streamed e fazes um loop sobre os resultados. Dentro desse loop assíncrono, inspecionas cada evento à medida que chega. Quando um evento chega, verificas as suas propriedades para ver que tipo de update representa. Quando um evento indica que uma tool call começou, podes ler o nome real da tool diretamente do payload do evento. Não tens de fazer parsing de nenhuma linguagem natural. Se o nome da tool corresponder à tua função de pesquisa na base de dados, fazes imediatamente push de um state update para o teu frontend para renderizar o spinner. Quando um evento subsequente sinaliza que a execução da tool está concluída, fazes dispatch de outro update para ocultar o spinner. Estes stream events também carregam message deltas standard. Se o agent estiver a gerar uma resposta textual longa, a stream emite chunk events que fazes append à UI. A arquitetura separa o output raw da conversa das ações semânticas. Encaminhas os text chunks para a janela de chat, e encaminhas os eventos de lifecycle da tool e do agent para o teu state manager da UI. Esta separation of concerns permite-te criar interfaces que parecem instantaneamente responsivas e profundamente ligadas à lógica do agent. Estás a reagir ao execution path real do sistema, e não a adivinhar as suas intenções com base em palavras. Aqui está o insight principal. Para de tratar o output do teu agent apenas como uma stream de conversa. Trata-o como uma event-driven state machine, onde cada ação interna é uma oportunidade para manter o teu utilizador visualmente informado. Como este é o episódio final da série, recomendo que leias a documentação oficial e tentes orquestrar estas streams por ti mesmo. Se tiveres ideias para o que devemos abordar numa série futura, visita devstories dot eu e diz-nos. Por hoje é tudo. Até à próxima!