1. Por que o processo de release para o ChatGPT App é mais complexo que um deploy comum
Na parte anterior do módulo falamos sobre como observar a qualidade e a estabilidade do App (logs, métricas, SLO). Agora vamos entender como organizar o próprio processo de release de modo que essas métricas não despenquem a cada deploy.
Em um web app comum tudo é mais ou menos simples: você faz deploy de uma nova versão do backend e do frontend — o usuário atualiza a página e passa a usar a nova versão. Se algo quebrou, muitas vezes basta reverter o deploy.
No ChatGPT App o stack é mais capcioso. Você tem pelo menos quatro camadas que têm “vidas” diferentes:
- Manifesto e esquema de ferramentas (MCP tools / OpenAPI);
- Infraestrutura: aplicativo Next.js e servidor MCP/Agents/ACP;
- System prompt e outros prompts;
- Dados: product feed, configurações, configs.
O problema é que o modelo “vive” em seu próprio “mundo mental”. O contexto do chat pode durar horas e dias. O manifesto e as descrições das tools são carregados e armazenados em cache pelo lado da OpenAI e não são atualizados instantaneamente em todos os diálogos existentes. Se você simplesmente trocar a assinatura de uma ferramenta (por exemplo, remover um campo do input‑schema), nos chats antigos o modelo continuará enviando o payload antigo, e seu backend novo irá rejeitá‑lo. Resultado — erros 400, respostas estranhas no chat e usuários muito frustrados.
Por isso, no mundo do ChatGPT App, “release” não é apenas “fazer deploy de um novo Docker”. É uma mudança coordenada de várias camadas, com gestão cuidadosa de versões, feature flags e possibilidade de rollback.
2. Matriz de versões: o que versionar afinal
É útil olhar não só para a “versão do App 1.3”, mas diretamente para uma matriz de versões por camada. Para o GiftGenius é algo assim.
| Camada | O que versionamos | Exemplo de valor | Onde armazenar |
|---|---|---|---|
| App / Next.js | Código e build | |
package.json, tag do Git |
| MCP / interface de API | Conjunto de tools e seus esquemas | |
constante no código, anotações |
| System / prompts | System prompt, helpers, exemplos | |
arquivos separados + metadados |
| Commerce / ACP / feed | Formato do product feed e contratos ACP | |
esquema no repositório de dados |
Note que são eixos diferentes. Você pode lançar a versão 1.4.2 do aplicativo em que o schema das tools permanece v1.7, enquanto o prompt vai para v3.2. Isso deve ficar visível nos logs; assim depois fica mais fácil entender por que, após o prompt v3.2, a conversão no checkout caiu de repente.
Para o código, é conveniente usar versionamento semântico (SemVer): MAJOR.MINOR.PATCH. MAJOR — mudança que quebra compatibilidade; MINOR — novas features sem quebrar; PATCH — correções de bugs. Para versões de interface (schema, prompts) a lógica é parecida: MAJOR sinaliza breaking change.
Vale destacar separadamente a versão da interface das tools. Para LLM isso é criticamente importante: se você muda o contrato de uma ferramenta enquanto o modelo “acha” que o contrato é antigo, começa a bagunça. Por isso, a política geralmente é: em releases MINOR, apenas adicionamos novos campos opcionais e não renomeamos/nem removemos os antigos; breaking changes — só via uma nova ferramenta, por exemplo suggest_gifts_v2.
Agora que separamos as camadas por versões, vamos ver como essas versões “vivem” no ciclo de release — do dev ao prod.
3. Fluxo básico de release para o GiftGenius
Primeiro vamos alinhar as etapas. É bem provável que você já tenha ambientes (do módulo sobre deploy), mas agora vamos olhá‑los pela ótica de releases.
Normalmente se separam:
- dev — desenvolvimento local, Dev Mode no ChatGPT, túneis;
- staging — o mais parecido possível com o prod: mesmo tipo de banco, mesmo tipo de MCP/ACP, mas dados e pagamentos de teste (sandbox);
- prod — ambiente de produção, aquele ao qual o ChatGPT App de produção / listagem na Store está conectado.
O processo pode ser assim:
flowchart TD A[Dev: branch feature/*] --> B[PR → main] B --> C[CI: unit + contract + lint] C --> D[Deploy to Staging] D --> E[Smoke/E2E + verificação manual] E --> F[Deploy to Prod] F --> G[Monitoramento por métricas e logs]
Em cada passo adicionamos “proteções”. No ambiente dev o desenvolvedor pode fazer o que quiser, mas cada merge em main aciona o CI, que executa testes unit/contract. Se tudo ok — fazemos deploy automaticamente para o staging. No staging executamos um conjunto curto de cenários E2E/smoke: por exemplo, um fluxo completo de escolha de presente e um checkout “fake” no gateway de teste.
Só depois apertamos o botão de deploy no prod. De preferência — com marcação de versão e link para o CHANGELOG. Já em produção continuamos de olho no p95, na taxa de erro e nas métricas de negócio (conversão de recomendação em checkout). Se algo cai após o release — precisamos ter um plano claro de rollback, do qual falaremos abaixo.
4. Release notes e changelog: o que exatamente registrar
Se você não tem notas de release, em um mês vai olhar para o gráfico: “por que há 3 semanas nosso p95 do checkout dobrou?” e responder “não faço ideia, mas tivemos um release grande”. Não é a melhor estratégia.
Normalmente há pelo menos dois tipos de notas.
Changelog interno — técnico. Ele é necessário para devs, SRE e todos que mexem no código. Ali se escreve quais features apareceram, quais bugs foram corrigidos, se houve breaking changes. O formato pode seguir o clássico Keep a Changelog: seções Added, Changed, Fixed, Removed.
Release notes externas — notas legíveis para usuários e para a Store. Não é necessário escrever “migrate MCP SDK 0.4 → 0.5”; é melhor escrever “Adicionamos recomendações para o feriado de Thanksgiving”, “Corrigimos um bug raro que impedia alguns presentes de serem adicionados ao carrinho”.
Exemplo de um trecho do CHANGELOG.md para o GiftGenius:
## [1.4.0] - 2025-11-20
### Added
- Nova ferramenta `suggest_gifts_v2` com suporte a tags de interesses.
- Teste A/B do novo system-prompt (flag: GG_PROMPT_V3).
### Changed
- Melhoramos o tratamento de erros do checkout ACP (mensagens mais amigáveis).
### Fixed
- Corrigimos um bug que fazia com que produtos sem imagem fossem ocultados das recomendações.
É útil manter por perto também a versão do prompt: mesmo que seja apenas o hash do commit do arquivo de system prompt, que depois permita lembrar: “ok, depois do prompt b3f9c2d os usuários passaram a clicar menos em “Comprar””.
5. Migrações de SDK e especificações: como viver em um ecossistema que muda rápido
O ecossistema em torno de Apps SDK, MCP e Agents evolui rapidamente: novas versões de SDK, mudanças no protocolo MCP, atualizações no ACP etc. Isso é bom (surgem novas possibilidades), mas também doloroso: pode quebrar rápido.
Fixar versões e “não atualizar no dia do release”
A primeira recomendação é simples: fixe as versões das dependências. Não use ^0.4.0, use 0.4.0. Para SDKs que quebram API com frequência (MCP/Agents/Apps SDK), isso é especialmente crítico. Pesquisas sobre o tema destacam o fenômeno do “SDK fatigue” — cansaço por atualizações incompatíveis constantes, sentido especialmente por quem deixou dependências com versões flutuantes (tipo ^0.4.0) e um dia, após um npm install, foi surpreendido por um monte de erros.
Mini‑exemplo:
// package.json (trecho)
{
"dependencies": {
"@modelcontextprotocol/sdk": "0.4.2",
"@openai/applications-sdk": "0.3.1"
}
}
A segunda recomendação: não junte no mesmo release features de negócio e migrações grandes de SDK. Se você precisa atualizar o MCP SDK de 0.3.x para 0.4.x, é melhor fazer um release técnico separado: primeiro a atualização do SDK, testes e estabilização, e só depois — o novo fluxo de checkout.
Estratégia de migração de SDK
Geralmente um plano sensato é assim:
No ambiente dev, crie um branch separado upgrade/mcp-sdk-0.4. Atualize a dependência, ajuste o código, rode todos os testes unit/contract e, localmente, execute o fluxo principal do GiftGenius via Dev Mode.
Depois faça deploy desse branch em uma URL de staging separada e rode nele os testes E2E/smoke. Dá até para fazer um pequeno teste de carga: 50–100 chamadas de suggest_gifts em sequência.
Se tudo estiver ok — faça merge em main, faça deploy no staging principal, rode novamente o smoke, e só então — vá para o prod.
Se não — você tem um rollback óbvio: basta não fazer merge desse branch ou revertê‑lo. Esse é o sentido de separar migrações de SDK de releases de produto.
Migrações de esquemas de tools e API
A parte mais desagradável são as mudanças de interface: o modelo não as descobre instantaneamente. Pesquisas sobre o tema destacam uma regra importante: “Expandir, mas não quebrar” (apenas aditivo). Se você precisa adicionar ao suggest_gifts um novo argumento interests: string[], torne‑o opcional, e não obrigatório; os cenários antigos continuarão funcionando.
Exemplo de evolução de um esquema Zod para dados de entrada:
// v1
const suggestGiftsInputV1 = z.object({
recipientName: z.string(),
budget: z.number()
});
// v1.1 (adicionamos campos opcionais)
const suggestGiftsInputV1_1 = suggestGiftsInputV1.extend({
interests: z.array(z.string()).optional(),
occasion: z.string().optional()
});
Repare: não tocamos nos campos existentes, apenas expandimos.
Se for realmente necessário quebrar o contrato (por exemplo, substituir budget por minBudget + maxBudget), é melhor criar uma nova ferramenta suggest_gifts_v2 e indicar na descrição que é uma versão melhorada. A API antiga pode ser mantida como deprecated e, gradualmente, desligada quando tiver certeza de que o modelo e os usuários migraram.
Migrações de dados: product feed e ACP
Já falamos de migrações de SDK e de esquemas das tools. O product feed também é um contrato. Se você muda o formato de SKU, moedas, localizações, isso precisa ser feito de forma coordenada: atualizar o esquema do feed, o processamento no MCP/ACP e quaisquer pré‑processadores. A documentação de commerce para ChatGPT App observa que erros no feed (campos quebrados, duplicatas, preços estranhos) podem arruinar a qualidade das recomendações mesmo com código perfeito.
Abordagem típica:
- Primeiro adicione os novos campos ao esquema do feed como opcionais e ensine o GiftGenius a usá‑los, se existirem.
- Depois atualize o pipeline que constrói o feed para que ele passe a preencher esses campos.
- Execute um validador do feed (testes de contrato para dados) e só então passe a depender desses campos na lógica.
6. Feature flags: separar deploy de release
As feature flags — um dos principais instrumentos de sobrevivência no mundo do ChatGPT App. A ideia central é simples: você faz deploy do código, mas não precisa ligar a nova funcionalidade imediatamente. Primeiro ela vive “atrás do flag” — habilitada apenas para desenvolvedores, ou para 1% dos usuários, ou completamente desligada.
Isso é especialmente importante quando:
- você lança um novo algoritmo de recomendações;
- você altera o system prompt (o que pode mudar radicalmente o comportamento do modelo);
- você conecta uma ferramenta cara ou lenta;
- você experimenta um novo fluxo de checkout.
Flag simples via variáveis de ambiente
No mínimo, uma feature flag pode ser feita via variável de ambiente:
// lib/features.ts
export const isNewRecoEnabled =
process.env.NEXT_PUBLIC_GG_NEW_RECO === "1";
Depois, no código da ferramenta do MCP, você pode usar assim:
if (isNewRecoEnabled) {
return runNewRecoAlgorithm(input);
}
return runOldRecoAlgorithm(input);
Vantagem dessa abordagem — simplicidade. Desvantagem — alternar flags em runtime é mais difícil: é preciso fazer deploy de um novo ambiente ou ao menos reinicializar.
Helper centralizado com contexto
Uma abordagem um pouco mais madura é ter um helper centralizado que considere não só flags globais, mas também o contexto do usuário (tenant, segmento, grupo de A/B).
// lib/featureFlags.ts
type Feature = "new-reco" | "checkout-v2";
type Context = { userId: string; tenantId?: string };
export function isFeatureEnabled(
feature: Feature,
ctx: Context
): boolean {
// aqui pode haver lógica: env, BD, serviço de flags externo
if (feature === "new-reco") {
return process.env.GG_NEW_RECO === "1";
}
return false;
}
No MCP handler:
const enabled = isFeatureEnabled("new-reco", { userId });
const result = enabled
? await runNewReco(input)
: await runOldReco(input);
Se algum dia você conectar um serviço externo de flags (LaunchDarkly, Statsig etc.), bastará mudar a implementação de isFeatureEnabled, e não todo o código.
Exemplos de cenários para o GiftGenius
Teste A/B de system prompt. Você cria o PROMPT_V2 e o liga apenas para 10% dos usuários com tenantId em uma lista específica. Os MCP tools e o widget não mudam, e você compara a conversão.
Kill‑switch para uma ferramenta cara. Suponha que você tenha criado uma ferramenta que faz uma chamada externa complexa (por exemplo, para algum modelo de ML de recomendações caro). Se esse serviço externo começar a cair ou encarecer de repente, você quer desativá‑lo em um segundo, sem parar o GiftGenius por completo. A feature flag é o jeito mais simples.
Rollout gradual de um novo fluxo de checkout. O checkout v2 é habilitado primeiro apenas para funcionários da empresa e alguns clientes de confiança. Se as métricas estiverem ok — você amplia a audiência até habilitar para todos.
7. Rollback: como reverter rápido quando tudo está pegando fogo
Mesmo com testes e flags impecáveis, algo vai quebrar. O importante é ter uma estratégia clara: o que você faz nos primeiros 5–15 minutos após ver um pico de erros ou queda em métricas.
Rollback rápido de código
Se o problema é um bug puramente técnico (NPE, variável errada, URL incorreto de serviço externo), geralmente basta reverter o deploy para a versão anterior. Por exemplo, no Vercel há rollback instantâneo para o deployment anterior.
Sua tarefa é sempre saber qual deployment corresponde a qual versão e como revertê‑lo. Idealmente isso está descrito no README para quem está de on‑call: “se depois do release 1.4.0 tudo pegar fogo, reverter para o deployment X”.
Outro gatilho rápido — as feature flags. Se quebrou apenas a nova feature (checkout-v2), é mais fácil desativá‑la via flag do que reverter todo o release.
Mudanças perigosas: manifestos e esquemas
Com manifestos e esquemas é mais complicado. Se você enviou para a Store um novo manifesto com esquema de tools incorreto, e ele já foi aprovado pela OpenAI, o rollback pode levar dias. O motivo é simples: cada mudança no manifesto também passa por revisão da OpenAI. Em análises de diferentes Stores, mudanças no manifesto e nos esquemas são consideradas releases “perigosos”, que exigem preparo e testes especialmente cuidadosos.
Portanto, separe:
- releases seguros: mudanças no código de MCP/Next.js, ajustes de prompts, novas features escondidas atrás de flags;
- releases perigosos: mudanças na lista de tools, nos esquemas de input/output, nos contratos ACP.
Releases “perigosos” devem ser feitos separadamente, com verificações adicionais e, possivelmente, primeiro só pelo Dev Mode e um app de staging (sem publicação na Store).
Rollback de dados e do feed
Com dados a situação é ainda mais difícil (e dolorosa). Se você migrou o product feed para um novo esquema e removeu os campos antigos, nem sempre é trivial voltar. Por isso, migrações de dados devem ser idempotentes e reversíveis: ou você mantém uma cópia antiga, ou faz a migração em duas etapas (primeiro duplica os dados, depois troca a leitura).
Uma abordagem simples — manter campos antigos e novos em paralelo por algum tempo e dar a si mesmo a possibilidade de alternar entre eles via feature flag. Se algo cair — você simplesmente retorna à leitura antiga.
8. Mini‑design do processo de release para o GiftGenius
Vamos juntar tudo o que falamos acima (versões, migrações de SDK, feature flags, rollback) em um cenário prático.
Imagine que você está preparando o release 1.4.0, em que:
- adiciona uma nova ferramenta suggest_gifts_v2 com input expandido;
- habilita um novo system prompt para parte dos usuários;
- atualiza o MCP SDK de 0.3 → 0.4;
- muda o formato do product feed (adiciona o campo tags).
Um plano sensato seria assim.
Primeiro, um release técnico separado 1.3.1: atualização do MCP SDK + ajustes mínimos de código, sem mudanças de esquemas e sem novas features. Rode o CI, staging e testes de smoke. Se tudo estiver estável — conviva com isso por alguns dias.
Depois, o branch feature/reco-v2. Nele você adiciona o suggest_gifts_v2 como nova ferramenta (o antigo suggest_gifts permanece). O esquema de input é expandido apenas com novos campos opcionais. Prepare o novo system prompt, mas envolva‑o pelo flag GG_PROMPT_V3. No ACP/feed, adicione o novo campo tags como opcional, e faça a leitura de modo que, se ele não existir, tudo continue funcionando.
No CI, adicione alguns novos testes de contrato: que o suggest_gifts_v2 aceite payload antigo e novo, que um feed com tags seja válido, mas que registros antigos sem tags também não quebrem o servidor.
Após o merge em main:
- o CI executa unit/contract;
- no staging são executados 1–2 cenários E2E via a nova ferramenta;
- habilite o novo prompt e a ferramenta apenas para o tenant de teste via feature flag.
Observe as métricas: p95 da ferramenta, taxa de erro, conversão para checkout. Se tudo ok — amplie o flag para mais usuários. E só depois, quando tiver certeza da estabilidade, atualize o manifesto para a Store (se necessário) e a descrição promocional do app.
Se algo quebrar pelo caminho — você sabe como voltar: ou desliga o flag manualmente, ou reverte o deployment, ou, em último caso, retrocede a versão do manifesto (mas esse é o caso que é melhor nem deixar acontecer).
9. Erros típicos no processo de release de um ChatGPT App
Erro nº 1: uma única “versão do App” abstrata em vez de uma matriz de versões.
Quando você tem apenas “GiftGenius v1.4”, mas em nenhum lugar estão fixadas as versões do esquema das tools, dos prompts e do product feed, você não conseguirá depois responder à pergunta: “após qual mudança exatamente nosso checkout caiu?” Separe as versões por camadas e registre‑as em logs estruturados.
Erro nº 2: breaking changes em tools sem novo nome/versão.
O mais doloroso: você renomeou um campo no schema de input ou o removeu sem mudar o nome da ferramenta. Nos chats antigos o modelo continua enviando o payload antigo, o backend retorna 400, o GPT começa a “alucinar” na resposta e os usuários não entendem nada. Qualquer mudança que quebre compatibilidade faça via uma nova ferramenta (foo_v2) ou uma nova versão de API, e mantenha a interface antiga por um período de transição.
Erro nº 3: atualizar o SDK “no caminho” para a feature.
Clássico: você adiciona uma nova feature de negócio e, no caminho, atualiza o @modelcontextprotocol/sdk de 0.3 para 0.5 “só para ficar tudo atualizadinho”. No fim, se algo quebra, não dá para saber se o culpado é o novo código, o novo schema ou o novo SDK. Migrações de SDK são melhores em releases técnicos separados, com plano de testes claro e possibilidade de rollback.
Erro nº 4: ausência de feature flags e kill‑switches instantâneos.
Lançar um novo algoritmo de recomendações direto para 100% dos usuários é divertido até ele começar a dar resultados estranhos ou derrubar um serviço externo. Sem feature flag, seu único recurso é reverter o release inteiro, o que pode afetar não só a nova feature, mas também uma dezena de melhorias inocentes. Faça ao menos flags simples via env ou um pequeno config.
Erro nº 5: confiar em “atualização instantânea” do manifesto.
É comum pensar que, assim que você muda as tools ou o openapi.yaml, o modelo imediatamente saberá do novo schema. Na prática, o manifesto e as descrições das tools são armazenados em cache, e em chats já abertos podem viver por muito tempo. Ignorar esse fato leva a bugs não óbvios: em chats novos tudo funciona, nos antigos — cai. Planeje mudanças de schemas considerando esse comportamento e teste via Dev Mode e staging antes de publicar na Store.
Erro nº 6: falta de um plano claro de rollback e de documentação de releases.
Se na sua equipe ninguém consegue responder às perguntas “como reverter um release em 5 minutos?”, “para qual versão vamos reverter?”, “como voltar ao schema antigo do feed?”, considere que você não tem rollback. Quem está de on‑call deve ter um roteiro curto, porém específico: quais botões apertar, quais variáveis mudar e onde verificar se o rollback funcionou.
Erro nº 7: releases “mudos”, sem release notes e sem ligação com métricas.
Lançar releases sem ao menos um changelog significa viver em modo adivinhação em alguns meses. Quando o p95 subir de repente e a conversão cair, você vai se perguntar: “o que mudou naquela época, afinal?” Criar o hábito de escrever ao menos notas mínimas de release e conectá‑las às datas de deploy e às versões facilita não só a auditoria de qualidade, mas a vida de toda a equipe.
GO TO FULL VERSION