For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegação principal
Theme
Feb 4, 2026 Apps SDK

15 lições que aprendemos ao criar Apps para o ChatGPT

E como incorporamos essas lições a uma Habilidade do Codex para ajudar você a criar Apps para o ChatGPT 10 vezes mais rápido.

Autor: Nikolay Rodionov (Co-founder, Alpic)

15 lições que aprendemos ao criar Apps para o ChatGPT

Na Alpic, acreditamos que a próxima geração de produtos e serviços terá como base experiências centradas em IA, com interfaces em que os usuários colaboram com modelos em vez de seguir fluxos predefinidos em interfaces tradicionais.

Quando a OpenAI lançou o Apps SDK, começamos imediatamente a desenvolver com ele. Ao longo de três meses, criamos 24 Apps para o ChatGPT, tanto para uso interno quanto para clientes B2B e B2C de áreas como turismo, varejo e SaaS.

Logo percebemos que criar Apps para o ChatGPT é fundamentalmente diferente de criar aplicativos tradicionais para a Web ou para dispositivos móveis. Padrões que funcionam bem na Web, como buscar dados no momento em que são necessários, controlar o estado pela interface ou pedir que o usuário configure opções explicitamente, muitas vezes deixam de funcionar ou chegam a prejudicar a experiência em um ambiente com agentes de IA.

Este artigo reúne as 15 lições mais importantes que aprendemos ao criar Apps para o ChatGPT em situações reais. Em seguida, mostramos como incorporamos essas lições a um framework de código aberto para a comunidade, o Skybridge, e a uma Habilidade do Codex para ajudar desenvolvedores a conceber, criar, testar e lançar Apps com muito mais rapidez.

O problema dos três corpos

Nos aplicativos tradicionais da Web, tudo era simples. Havia apenas um usuário e uma interface. Em um aplicativo para o ChatGPT, um terceiro corpo entra no sistema: o modelo.

Uma das maiores dificuldades ao desenvolver para o ChatGPT é controlar como as informações circulam entre os três. Se o usuário clicar no botão “Selecionar” do widget, a interface mostrará a mudança, mas o modelo, que conduz a conversa, só saberá o que aconteceu se você fornecer esse contexto explicitamente. Se o usuário pedir em seguida “Me dê mais detalhes sobre este produto”, o modelo não terá como saber qual produto o usuário está vendo.

Chamamos isso de assimetria de contexto. Cada corpo conhece parte do sistema, e nenhum tem uma visão completa. Para criar bons Apps para o ChatGPT, é mais importante decidir quais informações compartilhar, quando compartilhá-las e quem precisa ter acesso a elas do que manter tudo sincronizado. Essas decisões fazem a diferença entre um aplicativo difícil de usar e uma experiência fluida com agentes de IA.

1. Nem todo contexto deve ser compartilhado

Nosso primeiro impulso foi “compartilhar tudo em todos os lugares”. Esse acabou sendo um dos nossos primeiros erros.

Na prática, diferentes partes de um App para o ChatGPT muitas vezes precisam de visões intencionalmente diferentes do mesmo estado. Por quê?

  • Por questões de desempenho: os widgets da interface costumam precisar de muito mais dados do que o modelo terá de usar. Em um aplicativo de reservas de viagens, por exemplo, podem ser imagens, variações de preço e opções pré-carregadas. Enviar tudo isso ao modelo aumentaria o consumo de tokens e a latência, além de dificultar a identificação das informações relevantes.
  • Pela lógica do aplicativo: em alguns casos, a assimetria é intencional. Em um dos nossos primeiros aplicativos, o jogo de mistério Murder in the Valleys, o modelo precisa saber quem é o assassino para interpretar seu papel corretamente, mas a interface e o usuário não podem ter essa informação. Em um jogo no estilo Time’s Up, ocorre o inverso. A interface mostra a palavra secreta ao usuário, e o modelo não pode conhecê-la.

Em vez de “sincronizar tudo o tempo todo”, aprendemos a decidir explicitamente quem precisa saber o quê. Formalizamos essa distinção usando campos diferentes na saída da ferramenta:

Campo Finalidade Quem tem acesso
structuredContent Dados tipados para o widget e o modelo O widget e o modelo (por meio das funções toolOutput e callTool)
_meta Metadados da resposta Apenas o widget. O campo fica oculto para o modelo.

No jogo Time’s Up, por exemplo, enviávamos a palavra secreta apenas ao widget pelo campo _meta. Assim, o modelo tentava adivinhar a palavra com base nas dicas do usuário.

2. O carregamento sob demanda nem sempre funciona bem em aplicativos de IA

Como vínhamos do desenvolvimento para a Web, adotamos o carregamento sob demanda por padrão. Buscávamos dados quando o usuário clicava, carregávamos detalhes conforme necessário e procurávamos enviar o mínimo de dados possível no início.

No ChatGPT, a lógica se inverte. As chamadas de ferramentas muitas vezes levam vários segundos por causa das medidas de isolamento de segurança e do tempo de raciocínio do modelo.

Na prática, aprendemos a antecipar o carregamento sempre que possível. Enviávamos o máximo de dados já na primeira resposta da ferramenta e usávamos window.openai.toolOutput para hidratar o widget. Quase sempre, isso tornava a experiência mais rápida e a interface mais ágil.

Se o widget puder buscar dados com segurança em um endpoint público de API e não precisar compartilhar informações com o modelo, você sempre pode usar chamadas XHR tradicionais dentro do widget. Na maioria dos casos, porém, é desejável que o modelo consiga chamar ferramentas por conta própria para que o usuário possa continuar interagindo pela conversa.

3. O modelo precisa saber o que o usuário vê

Um problema sutil, mas importante, surge quando o usuário interage com um widget, por exemplo, selecionando um produto específico em uma lista, e depois faz uma pergunta no chat. Se o modelo não souber a qual parte da interface o usuário se refere, não conseguirá responder corretamente.

Para resolver isso, usamos window.openai.setWidgetState(state), que permite armazenar dados específicos do estado. Esses dados são adicionados ao contexto do modelo na próxima interação com o usuário.

À medida que os aplicativos ficavam mais complexos, percebemos que estávamos adicionando setWidgetState em muitos pontos para que o modelo pudesse acompanhar a navegação. Decidimos então descrever o contexto da interface de forma declarativa. Em vez de atualizar o modelo de forma imperativa a cada interação, adicionamos um atributo data-llm diretamente aos componentes:

<div
  data-llm={
    selectedTab === "details"
      ? "User is viewing product details"
      : "User is viewing reviews"
  }
>
  Product details
</div>

Para automatizar esse processo, criamos um plugin do Vite que lê esses atributos e atualiza o widgetState. Assim, o modelo recebe o contexto relevante da interface no momento certo, sem que os desenvolvedores precisem sincronizar cada interação manualmente.

Você encontra esse plugin do Vite, além de muitas outras dicas deste artigo, no framework de código aberto que criamos para compartilhar com a comunidade o que aprendemos.

4. Interações diferentes exigem APIs diferentes

Os Apps para o ChatGPT têm vários caminhos de interação entre o widget, o servidor e o modelo. Cada caminho atende a um tipo diferente de interação, por isso eles não são intercambiáveis.

Uma das principais lições que aprendemos ao criar Apps para o ChatGPT foi explicitar esses caminhos de comunicação e escolher de forma consciente o mecanismo responsável por cada parte da experiência.

O mapa dessas interações fica mais ou menos assim:

Diagrama das diferentes interações entre o widget, o servidor e o modelo

Essas lições estabelecem os fundamentos de um App para o ChatGPT: como o contexto é compartilhado, como o modelo fica sabendo o que o usuário vê e como as diferentes interações se propagam pelo sistema. A próxima seção parte desses fundamentos para explorar as implicações para o design de interfaces.

Repensando a interface para a IA

Os Apps para o ChatGPT funcionam em um ambiente inteiramente novo. Logo aprendemos a deixar de lado nossas ideias preconcebidas sobre interfaces para aproveitar ao máximo os novos recursos. Esta seção aborda o que precisamos aprender e desaprender sobre design de interfaces para criar aplicativos eficazes.

5. A interface precisa se adaptar aos modos de exibição e às restrições de cada um

Os Apps para o ChatGPT não têm um layout único. Dependendo de como e quando são acionados, o mesmo widget pode ser renderizado em três modos de exibição.

Os Apps podem aparecer no corpo da conversa, sobre a conversa (picture-in-picture, ou PiP) ou em tela cheia quando precisam de mais espaço. Os modos PiP e tela cheia permitem criar interfaces mais ricas, mas também acrescentam elementos sobrepostos que o widget não controla. É essencial respeitar as áreas seguras de cada dispositivo, como o espaço ocupado pelo botão de fechar que permanece visível no celular, para evitar cortes no conteúdo e facilitar as interações.

Com o tempo, identificamos alguns padrões de uso para cada modo de exibição:

Como aparece Quando usar
No corpo da conversa Modo de exibição padrão. O widget permanece no histórico da conversa. Para interações rápidas.
Tela cheia O widget ocupa a tela inteira, com a barra do chat na parte inferior. Quando o widget é complexo e precisa de muito espaço, como no caso de mapas.
Picture-in-picture O widget tem o mesmo tamanho que teria no corpo da conversa, mas permanece sobre ela. Quando o widget continua relevante nas próximas interações da conversa, mesmo depois de gerada a resposta.

6. A consistência visual importa em uma interface incorporada

No início, tínhamos dúvidas sobre quanta liberdade visual poderíamos ter em um App para o ChatGPT. A interface era nova para os usuários, mas precisava parecer familiar e manter a consistência tanto entre os nossos aplicativos quanto com o restante do ecossistema do ChatGPT. Ao contrário de um produto independente, o widget faz parte de uma interface que já existe, e qualquer inconsistência visual chama a atenção de imediato.

Felizmente, o kit de interface do Apps SDK da OpenAI nos deu um ponto de partida claro.

Criado com Tailwind CSS, o kit oferece componentes prontos para uso, ícones e tokens de design alinhados ao sistema de design do ChatGPT. Com ele, conseguimos avançar rapidamente e garantir que os widgets parecessem nativos e mantivessem a consistência visual com o restante da interface, mesmo quando criávamos componentes personalizados, como os da integração com o Mapbox.

7. Filtros em linguagem natural

Painéis tradicionais costumam ter barras laterais cheias de caixas de seleção e controles deslizantes para definir intervalos. Em interfaces com agentes de IA, isso muitas vezes é um retrocesso. Se o usuário pode expressar o que quer em linguagem natural, por exemplo, “Destinos ensolarados na Europa por menos de US$ 200”, obrigá-lo a passar por vários controles só dificulta a tarefa. Ele deveria poder simplesmente dizer o que quer.

Por isso, optamos por uma interface “sem filtros” na maioria dos nossos aplicativos. Em vez de uma barra lateral com opções de filtragem e ordenação, fornecemos ao modelo uma lista de valores (LOV) para os parâmetros das ferramentas.

Assim, o modelo pode usar a mensagem do usuário diretamente como entrada, sem precisar “adivinhar” quais opções estão disponíveis. Em outras palavras, ele consegue converter a linguagem natural diretamente nos parâmetros exigidos pela API do backend. Se o usuário disser “ensolarado”, o modelo sabe que deve chamar a ferramenta com weather=“sunny”.

8. Arquivos abrem novas possibilidades de interação

Ao criar aplicativos mais complexos, aprendemos que os arquivos não devem ser tratados como entradas secundárias. Nos Apps para o ChatGPT, eles permitem novos tipos de interação. Em vez de começar com formulários ou filtros, a experiência pode partir de algo que o usuário já tem.

Em um aplicativo de comércio eletrônico, por exemplo, o usuário pode enviar a foto de um produto no chat, pedir ao modelo que o identifique e continuar diretamente no widget para encontrar o produto correspondente ou descobrir outros.

Isso é possível porque os arquivos podem circular pelos dois lados do sistema. Do lado do modelo, as ferramentas podem consumir diretamente os arquivos enviados no chat por meio de openai/fileParams, o que permite ao modelo raciocinar sobre imagens ou outros materiais fornecidos pelo usuário. Do lado da interface, os widgets também podem trabalhar diretamente com arquivos usando window.openai.uploadFile e window.openai.getFileDownloadUrl. Assim, podem solicitar o envio de arquivos durante a interação ou gerar arquivos que os usuários podem baixar e reutilizar.

Como levar o aplicativo para produção

Quando os aplicativos saem do ambiente de desenvolvimento local, entram em jogo outras questões de segurança, configuração e ferramentas. É delas que trata este terceiro conjunto de lições.

9. As CSPs são o novo CORS

Por segurança, a OpenAI renderiza os Apps em dois níveis de iframes aninhados. As políticas de segurança de conteúdo (CSPs) são um mecanismo nativo de isolamento de iframes. Essa configuração aplica as políticas de forma rigorosa, o que muitas vezes leva ao clássico “funciona localmente, mas falha em produção”.

No desenvolvimento tradicional para a Web, às vezes é possível trabalhar com uma política permissiva. O Apps SDK exige precisão.

No manifesto do aplicativo, isso significa declarar com cuidado os domínios permitidos para cada tipo de interação:

Campo Finalidade Exemplo Erros comuns
connectDomains Requisições de API e XHR https://api.weather.com Incluir a API de produção e esquecer a de homologação.
resourceDomains Imagens, fontes e scripts https://cdn.jsdelivr.net Usar uma CDN genérica como delivr.net sem incluí-la na lista de domínios permitidos.
frameDomains Incorporação de iframes https://www.youtube.com Incorporar um vídeo do YouTube ou uma instância do Mapbox sem permitir o domínio correspondente.
redirectDomains Links externos que abrem sem aviso https://app.alpic.ai Esquecer o domínio de checkout ou de callback do OAuth.

Dar prioridade à configuração das CSPs desde o início nos poupou bastante tempo de depuração em produção.

10. Pequenas opções de configuração do widget têm grande impacto

Além das CSPs, algumas configurações do widget determinam como o controle é dividido entre o widget, o modelo e o ambiente host. É fácil deixar essas opções passarem despercebidas, mas elas definem limites importantes para navegação, acesso a ferramentas e publicação.

Limites do host e da navegação

  • widgetDomain é obrigatório para enviar o aplicativo para análise. Ele define o destino padrão do botão “Abrir em <App>” no modo de tela cheia e é usado para determinar as origens permitidas, já que os widgets são renderizados em <widgetDomain>.web-sandbox.oaiusercontent.com. Usamos setOpenInAppUrl para direcionar os usuários ao caminho adequado de acordo com o contexto.

Limites do modelo e das ferramentas

  • As anotações das ferramentas devem seguir as diretrizes de publicação. Opções como readOnly, destructiveHint e openWorldHint são obrigatórias e passam por validação quando o aplicativo é enviado para análise.
  • A visibilidade das ferramentas define quais delas o modelo pode chamar. Marque explicitamente como privada cada ferramenta que deve ficar fora do alcance do modelo.

Limites de execução do widget

  • widgetAccessible controla se o widget pode chamar ferramentas por conta própria usando callTool.

Cada configuração é pequena por si só, mas, juntas, elas determinam se o aplicativo funcionará corretamente depois de publicado.

Como acelerar os ciclos de desenvolvimento

O Apps SDK evolui rapidamente, e tem sido empolgante desenvolver aplicativos acompanhando essa evolução. Para tornar nosso fluxo de desenvolvimento mais simples e eficiente, decidimos criar um framework de código aberto e compartilhá-lo com a comunidade. As próximas lições podem ajudar você a evitar algumas das dificuldades que enfrentamos no início.

11. Ciclos rápidos de desenvolvimento exigem hot reload

Uma das primeiras questões que abordamos foi a rapidez com que conseguíamos testar cada alteração. A combinação de um cache de recursos com TTL longo e do uso de JSON-RPC para encaminhar esses recursos impede que o recarregamento automático de módulos, como o do Vite ou do Next.js, funcione nos Apps para o ChatGPT sem adaptações.

Depois de dedicar bastante tempo a entender o funcionamento interno do Vite, criamos um plugin que permite recarregar widgets em tempo real diretamente no ChatGPT. O plugin intercepta as requisições de recursos enviadas ao servidor MCP e injeta as atualizações em tempo real no iframe do ChatGPT. Poder fazer uma alteração na IDE e ver o resultado imediatamente no ChatGPT reduziu muito o tempo entre cada mudança e sua verificação.

12. Nem todo teste precisa ser feito no ChatGPT

Testar no ChatGPT é a melhor referência, mas um emulador local pode acelerar os primeiros ciclos de desenvolvimento, principalmente quando você está trabalhando em definições de ferramentas que exigem atualizar a conexão com o servidor MCP personalizado no ChatGPT.

Para acelerar esses primeiros ciclos, criamos um emulador local leve que simula o ambiente host do ChatGPT, com ferramentas de depuração e logs específicos dos aplicativos. Assim, conseguíamos testar alterações no estado do React e no layout em milissegundos e reservar os testes no próprio ChatGPT para validar as interações com o modelo e os casos extremos.

13. Testar em dispositivos móveis exige suporte explícito

Os testes em dispositivos móveis trouxeram outro desafio. Para testar no ChatGPT, é preciso criar um túnel até o servidor local, mas o Vite usa localhost por padrão, o que impede o acesso à mesma URL a partir de outros dispositivos.

Resolvemos isso ampliando nosso plugin do Vite para oferecer encaminhamento de domínio nas portas expostas pelo túnel. Com isso, conseguimos testar em dispositivos iOS e Android e incluir a validação em dispositivos móveis no nosso fluxo habitual de desenvolvimento.

14. Abstrações conhecidas, como os hooks do React, aceleram o desenvolvimento do frontend

O Apps SDK oferece recursos avançados, mas a maioria deles está disponível por meio de APIs JavaScript de baixo nível. Como já trabalhávamos com React havia muito tempo, queríamos usar conceitos que dominávamos.

Por isso, introduzimos abstrações familiares a quem usa React, como os hooks useCallTool, useWidgetState e useLocale. Para fluxos de dados complexos, também criamos recursos mais avançados de gerenciamento de estado, como createStore, baseado no Zustand. Recuperar esses padrões conhecidos de frontend reduziu o código repetitivo e aproximou o desenvolvimento de widgets dos fluxos modernos de desenvolvimento para a Web.

Como transformamos as lições em uma Habilidade do Codex

15. Transforme as lições em ferramentas reutilizáveis

À medida que esses padrões se repetiam em vários aplicativos, ficou claro quanto tempo perdíamos redescobrindo as mesmas soluções. Para tornar o desenvolvimento de Apps para o ChatGPT mais rápido e previsível, decidimos incorporar as lições diretamente às nossas ferramentas, tanto para uso próprio quanto para a comunidade.

Isso deu origem a duas iniciativas complementares:

  1. O framework Skybridge: esse framework React de código aberto reúne muitos dos padrões descritos neste artigo em componentes reutilizáveis. Entre eles estão nossos hooks (useCallTool, useToolInfo), as ferramentas de desenvolvimento (HMR e emulador local) e o atributo data-llm.
  2. A Habilidade do Codex chatgpt-apps-builder: com base no framework, criamos uma Habilidade do Codex dedicada a apoiar todo o ciclo de vida do aplicativo:
    • Concepção: explorar ideias para criar um aplicativo “com agentes de IA” que vá além de uma simples adaptação da versão para a Web.
    • Geração de código: escrever ao mesmo tempo o frontend em React e o backend do servidor MCP, ambos já configurados com os padrões adequados de experiência do usuário e de interface.
    • Testes locais: iniciar servidores de desenvolvimento e conectar os aplicativos locais ao ChatGPT para testar alterações em tempo real com hot reload.
    • Garantia de qualidade e publicação: verificar de forma estruturada se o aplicativo atende às diretrizes de envio da OpenAI, incluindo a validação das CSPs, a avaliação das áreas seguras da interface e os testes em produção.
    • Implantação do aplicativo: ajudar nas etapas finais necessárias para lançar o aplicativo e continuar a aprimorá-lo.

Para instalar e usar a Habilidade, execute o seguinte comando:

npx skills add alpic-ai/skybridge

Conclusão

Criar Apps para o ChatGPT exige repensar como o contexto circula, como as interfaces se comportam e como usuários e modelos colaboram. Muitas das lições deste artigo surgiram das diferenças entre os padrões conhecidos da Web e o funcionamento dos sistemas com agentes de IA na prática.

Ao compartilhar essas lições e incorporá-las ao nosso framework de código aberto e à nossa Habilidade do Codex, esperamos ajudar as equipes a gastar menos tempo redescobrindo os mesmos problemas e mais tempo explorando as possibilidades desse novo modelo de interação. Os Apps mais interessantes para o ChatGPT irão além de simples adaptações de produtos existentes. Serão experiências concebidas desde o início para essa nova forma de interação centrada em IA.