Mapa Geral Mercado Livre
Mapa Geral — Mercado Livre
Mapa de referência: como a venda acontece no Mercado Livre de ponta a ponta, e onde o Bunker entra em cada etapa.
1. A jornada de venda, em 6 etapas
Tudo começa com a conta do vendedor conectada ao Bunker e termina no relacionamento pós-venda. São 6 etapas, nessa ordem:
- Conectar: o vendedor autoriza a conta uma única vez (OAuth). A partir daí o Mercado Livre passa a falar com o sistema.
- Produto & Anúncio: o que o vendedor vende e como aparece pro comprador. Existem três coisas diferentes aqui: o Catálogo do ML (a ficha oficial, igual pra todo mundo), o Meu Produto (o estoque que o vendedor tem) e o Meu Anúncio (a vitrine: preço, fotos, condições). No catálogo, vários vendedores competem pela mesma página, a buy box; num anúncio próprio, a página é só do vendedor.
- Vender → Pedido: o cliente compra e isso vira um pedido, com itens, valor e status (pago, cancelado, em mediação). Pode vir agrupado em um "pacote".
- Receber $: o dinheiro entra através do Mercado Pago, já descontando comissão e tarifas. Não cai na hora: existe um prazo de retenção até a Liberação de Pagamentos, o processo do Mercado Pago que libera o valor pro vendedor.
- Enviar: o produto vai pro cliente via Full, Flex ou Correios, cada um com seu prazo e rastreio. Pra envios via drop_off, xd_drop_off, cross_docking e xd_same_day, a nota fiscal (ou DC-e, pra quem não emite NF) é obrigatória: sem ela o envio fica travado no substatus
invoice_pending. - Pós-venda & Relacionamento: cuidar do cliente e da reputação da loja. Inclui perguntas (antes da compra), mensagens (depois da venda), reclamações/mediações, a reputação geral do vendedor e moderações por infrações.
drop_off / xd_drop_off / cross_docking / xd_same_day são modalidades de envio em que o vendedor leva o pacote pra uma agência ou ponto de coleta (em vez do Mercado Livre buscar). DC-e (Declaração de Conteúdo Eletrônica) é um documento alternativo à nota fiscal, pra quem não emite NF (pessoa física ou MEI não-contribuinte). invoice_pending é o status do envio que fica "travado" até a nota fiscal (ou DC-e) ser enviada. Liberação de Pagamentos é o processo do Mercado Pago que libera, pro vendedor, o dinheiro de uma venda depois de um período de retenção.
Em paralelo, duas coisas se conectam a essas etapas:
- Marketing (opcional): ofertas/promoções e Mercado Ads, que aumentam a visibilidade do anúncio (etapa 2) e impulsionam vendas.
- Conciliação Financeira: o extrato que fecha a conta no fim, vendas menos taxas menos reembolsos igual repasse, o que sobra pro vendedor.
Diagrama 1 — A jornada de venda
2. Webhooks e a camada de plataforma
Por baixo das 6 etapas existe uma camada que avisa o sistema sobre toda mudança em tempo real: os webhooks do Mercado Livre.
O padrão notify-then-fetch
A regra do ML é simples: o webhook nunca traz o dado completo, ele só avisa que "o recurso X mudou" (um id mais um tópico). Não existe "webhook completo". A partir desse aviso, o sistema precisa fazer um GET na API pra buscar o recurso atualizado.
Duas regras operacionais importantes vêm junto:
- O sistema precisa responder 200 em até ~500ms, senão o ML desativa o tópico.
- Notificações perdidas ficam guardadas só 2 dias em
/missed_feeds, e o ML faz retry do webhook por até 1h.
Webhook é um aviso automático que o Mercado Livre manda assim que algo muda do lado dele (por exemplo: "o pedido 123 mudou de status"). GET é o pedido que fazemos de volta pra API do Mercado Livre pra buscar a informação completa e atualizada (por exemplo: "me dá os detalhes do pedido 123"). API é a porta de entrada que o Mercado Livre disponibiliza pra sistemas conversarem com ele.
O pipeline: fila, worker e handler
- Receiver: recebe o webhook, responde 200 imediatamente (sem processar nada ainda) e salva o evento numa fila (
MeliNotificationEvent). - Worker (
meli-webhook-worker): drena essa fila continuamente e roteia cada evento pro handler certo, de acordo com o tópico. - Handler: faz o GET do recurso na API do ML pra buscar o dado completo e salva no banco (
MeliOrder,MeliItem,MeliQuestion, etc).
Esse pipeline separa "receber o aviso" de "processar o aviso": o sistema não trava esperando a resposta da API do ML, e o ML não desativa o tópico por demora na resposta.
Receiver é a primeira parte do sistema que recebe o aviso do ML, ele só confirma "recebi" e guarda o aviso pra tratar depois. Fila é uma lista de avisos pendentes esperando a vez, em ordem. Worker é um processo que roda o tempo todo em segundo plano, pegando avisos da fila um por um. Handler é a função que sabe o que fazer com cada tipo específico de aviso. E MeliOrder, MeliItem, MeliQuestion são as "tabelas" do nosso banco, cada uma guarda uma cópia local e atualizada de uma informação do Mercado Livre (pedidos, anúncios, perguntas...).
Tópicos monitorados hoje
| Categoria | Tópico | Status |
|---|---|---|
| 💰 Vendas | orders_v2 (vendas) |
✅ |
| 💰 Vendas | payments (pagamento) |
✅ |
| 💰 Vendas | shipments (envio) |
✅ |
| 💰 Vendas | orders_feedback |
⬜ |
| 📦 Produto/Estoque | items (mudança no anúncio) |
✅ |
| 📦 Produto/Estoque | stock-location (estoque) |
✅ |
| 📦 Produto/Estoque | price_suggestion |
⬜ |
| 📦 Produto/Estoque | user_products_families |
⬜ |
| 📖 Catálogo | catalog_item_competition_status |
✅ |
| 📖 Catálogo | catalog_suggestions |
⬜ |
| 💬 Pós-venda | questions (perguntas) |
✅ |
| 💬 Pós-venda | messages (mensagens) |
✅ |
| 💬 Pós-venda | post_purchase/claims |
✅ |
| 🧾 Fiscal | invoices |
⬜ |
| 🏷️ Promo/Logística | public_offers |
✅ |
| 🏷️ Promo/Logística | public_candidates |
✅ |
| 🏷️ Promo/Logística | flex-handshakes |
⬜ |
| 🏷️ Promo/Logística | fbm_stock_operations |
⬜ |
✅ já temos handler · ⬜ gap, ainda não tratamos.
O gap mais importante: invoices está ligado ao gap de nota fiscal/DC-e (Seção 1).
Detalhamento completo de cada tópico (recurso consultado, categoria de permissão, o que cada agente pode ler e escrever hoje): Capacidades por Tópico de Notificação.
Três notas sobre a tabela acima: o tópico items também cobre mudança de preço, nesse caso o handler consulta /items/$ITEM_ID/sale_price em vez de /items/$ITEM_ID; messages e post_purchase têm subtópicos extras (read e claims_actions) que já chegam junto mas não têm linha própria; e vis_leads/leads-credits ficam de fora de propósito, são exclusivos das verticais de imóveis, veículos e serviços, fora do escopo de e-commerce geral do Bunker.
Priorização dos gaps pelo priority stack do Gestor
Os 7 tópicos ⬜ encaixam no priority stack do Gestor (#1 Reputação > #2 Dinheiro > #3 Crescer, ver Seção 9):
| Tópico ⬜ | O que destrava | Prioridade |
|---|---|---|
orders_feedback |
Feedback de venda confirmada | #1 |
flex-handshakes |
Handoff de transportadora Flex (rastreio/atraso) | #1 |
invoices |
NF gerada pelo Faturador ML (gap fiscal/DC-e, Seção 1) | #2 |
fbm_stock_operations |
Operações de estoque Full (ruptura) | #2 |
price_suggestion |
Sugestão de preço do ML (/suggestions/items/.../details) |
#2 / #3 |
user_products_families |
Mudança em famílias/variações do produto | #3 |
catalog_suggestions |
Sugestões de produto pro catálogo (Brand Central) | #3 |
Diagrama 2 - O pipeline de webhooks
3. Arquitetura dos 6 agentes de IA
O Bunker tem 6 agentes de IA, cada um especialista em uma parte da jornada. O Gestor é o diretor: orquestra os outros 5 e tem como prioridade #1 cuidar da reputação da conta.
- Gestor: diretor, orquestra os 5 agentes, prioridade #1 é a reputação da conta e a competição (buy box).
- Anúncios: cuida do título, atributos e tags do anúncio, focado em conversão.
- Criativo: cuida das imagens (hero + 7 slots), responsável por cerca de 80% do CTR.
- Analista: cuida do preço e do listing type, focado em ganhar a buy box e aparecer como "Mais Relevante".
- Ads: cuida das campanhas pagas (PPC). Hoje ainda é um stub, só lê dados de ACOS/ROAS, escrita travada pela ADR-08.
- SAC: cuida do atendimento (perguntas, mensagens, reclamações), resolve em 1 toque pra evitar virar claim.
Diagrama 3 — Os 6 agentes e quem orquestra quem
Onde cada agente atua no ML × o que consome no banco
| Agente | Onde atua no Mercado Livre | O que consome no banco |
|---|---|---|
| Gestor | Toda a jornada (coordena) Conta / Reputação Competição (buy box) |
MeliSellerMetrics / Profile MeliOrder (margem real) MeliCatalogCompetition MeliStockLocation 🆕 (ruptura) + saída dos outros 5 agentes |
| Analista | Anúncio (preço, listing type) Buy box / Competição Vender (sales velocity) |
MeliCatalogCompetition (price_to_win) MeliItem (price/listingType) MeliStockLocation 🆕 MeliOrder (velocity) MeliSellerMetrics |
| Anúncios | Anúncio (título, attributes, tags) Catálogo (ficha técnica) |
MeliItem (title/attrs/healthScore) MeliCatalogProduct 🆕 (ficha) MeliVariation 🆕 |
| Criativo | Anúncio (imagens / pictures) Catálogo (imagens de referência) |
MeliItem (pictures, category) MeliCatalogProduct 🆕 (ref) |
| Ads | Mercado Ads (Product/Brand) Buy box (só anuncia GANHANDO) Vender (conversão) |
MeliCatalogCompetition (gate) MeliItem MeliOrder (conversão) |
| SAC | Pós-venda (perguntas, mensagens) Reclamações / Mediações Pedido · Envio (status) |
MeliQuestion / Message / Claim MeliItem (info p/ responder) MeliOrder MeliShipment |
- 🆕 = schema que ainda não existe no banco, precisa ser criado.
- Buy box = a "vitrine" do Mercado Livre quando vários vendedores vendem o mesmo produto. Só 1 aparece em destaque (ganha a venda e a visibilidade), os outros ficam escondidos.
- "Mais Relevante" = um critério de ordenação da busca do ML, não é só preço, envolve reputação, conversão etc.
- Listing type = o "plano" do anúncio no ML (ex: clássico, premium), afeta taxa e exposição.
- Health score = uma nota que o ML dá pro anúncio com base na qualidade do cadastro (título, fotos, ficha técnica completa).
- CTR = taxa de cliques, quantas pessoas clicam no anúncio em relação a quantas veem.
- Sales velocity = a velocidade de vendas de um produto, quantas unidades por dia/semana.
- ACOS / ROAS = métricas de anúncio pago: ACOS é quanto você gasta em ads pra cada R$1 de venda, ROAS é o inverso, quanto você fatura pra cada R$1 investido em ads.
- ADR-08 / read-only = uma decisão técnica registrada que hoje trava o agente Ads em modo leitura: ele lê os dados dos anúncios pagos, mas ainda não pode alterar campanhas sozinho.
- price_to_win = o preço que, segundo o ML, faria o vendedor ganhar a buy box agora.
4. Como o SAC decide, gatilho a gatilho
O SAC cuida do atendimento: perguntas, mensagens e reclamações. A missão é resolver em 1 toque (uma resposta só resolve o problema) sem nunca quebrar o compliance do Mercado Livre. Por trás disso existe um fluxo bem definido, do webhook que avisa "chegou uma dúvida" até a resposta (ou a escalada pra um humano).
O gatilho: do webhook ao evento
Existem 3 áreas que disparam o SAC, e todas têm a mesma natureza: alguém tem uma dúvida sobre o produto.
- Perguntas: feitas antes da compra, via webhook
questions. - Mensagens: feitas depois da compra, via webhook
messages. - Reclamações: dúvidas que viram claim, via webhook
post_purchase.
O caminho até virar um evento de decisão segue o pipeline da seção 2: o Receiver responde 200 e guarda o aviso na fila, o Worker drena a fila e roteia pro handler certo, e o Handler salva o registro no banco (MeliQuestion, MeliMessage ou MeliClaim).
Aqui entra o passo que faz a diferença: o sistema resolve o produto. A pergunta, mensagem ou claim chega com um itemId, mas isso sozinho não é suficiente pra responder. O sistema busca o MeliItem correspondente e monta o productContext, com título, atributos e condições do anúncio. É esse contexto que alimenta a resposta; sem ele, o SAC não sabe do que está falando.
Com o productContext em mãos, o sistema emite o evento CUSTOMER_QUESTION, que vira o gatilho do fluxo de decisão.
productContext é um "resumo" do anúncio (título, atributos, condições) montado na hora a partir do MeliItem, pra dar à IA a informação que ela precisa pra responder. Evento (CUSTOMER_QUESTION) é um sinal interno que diz "chegou uma dúvida, aqui está o contexto, decida o que fazer". MeliQuestion, MeliMessage e MeliClaim são as tabelas que guardam, respectivamente, perguntas, mensagens e reclamações vindas do Mercado Livre.
Status atual: os 3 gatilhos estão ligados ponta a ponta (PRs BUN-122/123/129/131). questions é o único que pode responder sozinho (quando confiante e compliant); messages e claims sempre passam por humano.
O fluxo de decisão
Com o evento CUSTOMER_QUESTION em mãos, o SAC segue 4 perguntas antes de agir:
- A LLM gera uma resposta:
{ answer, confident, detectedPattern }. - A resposta veio válida? (a LLM respondeu e o JSON bateu com o schema esperado)
- A resposta passa no compliance? (sem palavrão, sem URL, sem CPF/CNPJ/e-mail)
- A IA está confiante na resposta?
Dependendo de onde a resposta passa ou falha nesses 4 pontos, o sistema cai em um dos 3 sinais abaixo.
LLM é o modelo de IA que gera a resposta, o "cérebro" do agente. JSON/schema é o formato estruturado que a resposta da LLM precisa seguir pro sistema conseguir ler os campos answer, confident e detectedPattern; se vier fora do formato, a resposta é descartada (llm_parse_failed). Compliance aqui são as regras do Mercado Livre pra mensagens entre vendedor e comprador: nada de palavrão, link ou dado pessoal (CPF, CNPJ, e-mail), chamados de PII. needsHuman é o estado que tira a decisão da IA e coloca na fila de um humano; draftAnswer é o rascunho que a IA deixa pronto pra esse humano só revisar. applied é o estado que indica que a IA já respondeu sozinha. Gate de tier (R7 / Tier 3) é uma trava de aprovação por nível de risco: ações de alto impacto (como reembolso) não são executadas pela IA, o fluxo para e espera aprovação humana.
Os sinais
- Verde,
applied = true: a IA está confiante e passou no compliance. Responde sozinha no Mercado Livre (meli.answerQuestion). Resolução em 1 toque, baixo risco, sem humano. - Amarelo,
needsHumancomreason = low_confidence: a resposta é plausível e está dentro do compliance, mas a IA não tem certeza. Gera umdraftAnswere espera um humano aprovar. - Vermelho,
needsHuman(nunca sozinho): dispara em qualquer um destes casos:compliance_block(palavrão, URL ou PII), falha técnica (llm_parse_failedoumeli_answer_failed), ou ação crítica de alto impacto (reembolso, cancelamento), que interrompe o fluxo pro gate de aprovação (R7 / Tier 3).
O princípio por trás dos sinais: quanto maior o impacto da ação, mais "vermelho" ela fica. Responder uma pergunta é leve (verde); reembolsar ou cancelar um pedido sobe pro gate de aprovação, e a IA nunca executa sozinha.
Essa escala de sinais vale pro gatilho de pergunta (CUSTOMER_QUESTION). Os outros 2 gatilhos têm regra própria, mais restritiva, e nunca chegam ao verde:
POST_SALE_MESSAGEnunca envia sozinho (decisão de design D1): toda mensagem pós-venda cai direto em amarelo, vira rascunho (SAC_POST_SALE_DRAFT) na inbox pro humano revisar e enviar.CLAIM_OPENEDé sempre vermelho (TIER_3): a IA só gera uma sugestão (recommendedAction+rationale, viareviewClaim/generateClaimSuggestion), nunca responde; o humano resolve direto no Mercado Livre pelos endpoints de claim (BUN-122), sem passar pela inbox de rascunho.
A inbox de aprovação
Os rascunhos amarelos (SAC_QUESTION_DRAFT e SAC_POST_SALE_DRAFT) caem numa inbox de aprovação (ExecuteSacDraftUseCase): o humano revisa, edita se quiser, e decide SEND ou DISMISS. SEND dispara o envio real ao Mercado Livre primeiro (answerQuestion ou sendMessage) e só depois grava audit; DISMISS só marca como rejeitado, nada é enviado ao ML. Claims não passam por essa inbox: não existe "enviar texto" pra um claim, o humano age direto no Mercado Livre pelos endpoints de claim.
Handoff: corrigindo a causa
Se o detectedPattern revela que a dúvida vem de um problema no próprio anúncio (ex: muita gente pergunta a medida do produto), o SAC roteia esse sinal pro Anúncios ou pro Criativo, em paralelo e de forma opcional. Anúncios pode adicionar o atributo que falta; Criativo pode gerar um infográfico explicando a medida. A resposta ao cliente resolve o sintoma; o handoff corrige a causa.
Diagrama 4 — O fluxo completo do SAC
4a · O gatilho completo
4b · O fluxo de decisão
4c · Regras em paralelo (handoff, compliance, responsabilidades)
4d · Os sinais
Detalhe das 3 ramificações do sacNode (o que o código faz hoje em cada ramo, lado a lado): SAC — As 3 Ramificações do sacNode.
5. Como o Analista decide preço e buy box, por tier de autorização
O Analista cuida da precificação: monitora os itens, compara com a concorrência e ajusta o preço pra ganhar a buy box (o destaque "Mais Relevante" do Mercado Livre), sem nunca vender abaixo do custo. A diferença em relação ao SAC é que aqui a IA pode agir sozinha em mais situações, e tudo é organizado por tiers de autorização (1, 2 e 3), de acordo com o tamanho da mudança de preço.
O gatilho: do monitor ao evento PRICE_CHANGE
Existem 2 fontes que disparam uma reavaliação de preço:
- price-monitor (CRON): varre periodicamente os itens monitorados e detecta mudança de preço ou de posição. É o gatilho principal.
- webhook
catalog_item_competition_status: avisa que um concorrente mexeu na buy box (você perdeu a posição ou mudou de lugar), o que também dispara uma reavaliação.
As duas fontes convergem pra "Detecta alerta", que identifica o diff de preço/posição no item monitorado, e emite o evento PRICE_CHANGE, com { itemId, diffPct, newPrice, competitor }.
Pra decidir o que fazer, o fluxo lê o MeliItem (preço, listing type, custo, de onde sai a margem) e o price_to_win / MeliCatalogCompetition (o preço necessário pra ganhar a buy box e o status da disputa).
Status atual: as 2 fontes já estão implementadas e mergeadas (PRs #76 + #77). O price-monitor.job roda de hora em hora, varre o catálogo ativo do seller e emite PRICE_CHANGE quando o item está disputando a buy box (competing/listed/sharing_first_place) e o price_to_win difere do preço atual; item já winning nunca dispara, porque já é dono da buy box. O webhook catalog_item_competition_status emite só quando o seller perdeu a posição (status ≠ winning) e há price_to_win disponível. As duas fontes chamam getPriceToWin e gravam um snapshot na tabela MeliCatalogCompetition, que já existe e está populada.
Buy box (também chamada de "Comprar" ou "Mais Relevante") é o destaque que o Mercado Livre dá ao melhor vendedor de um anúncio com vários sellers; ganhar a buy box significa aparecer em destaque pra maioria dos compradores. price_to_win é o preço calculado como o necessário pra ganhar essa disputa. MeliCatalogCompetition é a tabela que guarda o status dessa disputa de preço (snapshot atualizado a cada gatilho). Listing type é o tipo de anúncio (clássico, premium etc.), que entra no cálculo do algoritmo "Mais Relevante".
O fluxo de decisão
Com o evento PRICE_CHANGE em mãos, o Analista segue esta sequência:
- O evento
PRICE_CHANGEchega com{ itemId, diffPct, newPrice, competitor }. - O sistema busca o contexto de preço:
getItem+getItemPricesContext(price_to_win e dados de concorrência). - A LLM recomenda:
{ recommendation, newPrice, reason, marginFloorRespected }. - A margem foi respeitada? (
marginFloorRespected) - Se sim, classifica a mudança por magnitude (
|diffPct|) em 3 faixas de tier.
Margem primeiro, magnitude depois: se a margem não foi respeitada, não importa o tamanho da mudança, o sistema força o TIER_3 (aprovação obrigatória), sempre. Só quando a margem está ok é que o |diffPct| decide entre os 3 tiers.
marginFloorRespected indica se o preço sugerido respeita o piso de margem (não vende abaixo do custo). diffPct é a diferença percentual entre o preço atual e o preço recomendado. TIER_1/2/3 são os níveis de autorização: quanto maior o tier, maior o risco e mais aprovação humana é exigida. createPendingApproval é a função que cria um pedido de aprovação pendente pra um humano revisar.
Os sinais
- Verde,
TIER_1(auto):|diffPct| < 5%e margem respeitada. O Analista atualiza o preço sozinho no Mercado Livre (updatePrice) e não notifica ninguém, mudança pequena e de baixo risco. Audit:PRICE_CHANGE_AUTO. - Amarelo,
TIER_2(notify):|diffPct|entre 5% e 10% e margem ok. O Analista atualiza o preço e notifica um humano: executa, mas avisa, o humano acompanha e pode reagir. Audit:PRICE_CHANGE_NOTIFY. - Vermelho,
TIER_3(aprovação): dispara se|diffPct| > 10%(mudança grande) ou semarginFloorRespected = false(fura o custo). O Analista não executa, cria umaapprovalpendente e espera um humano decidir. Falhas técnicas (busca, LLM, parse, update) também caem aqui, como erro/noop.
A diferença-chave em relação ao SAC: aqui o amarelo (TIER_2) já executa e só notifica depois; somente o vermelho (TIER_3) espera aprovação antes de agir. A trava de margem é o "sempre-vermelho" do Analista, equivalente ao compliance_block do SAC.
Regras do Analista
Como ele decide o preço (do prompt): o "Mais Relevante" do Mercado Livre não é só preço, ele pesa o preço final (item + frete), o listing type (clássico/premium), a reputação do vendedor e o uso do Envio Full. O Analista mira o price_to_win pra ganhar a buy box, sem furar o piso de margem.
A trava de margem (regra-mãe): se a IA diz que marginFloorRespected = false, o sistema força TIER_3 automaticamente, não importa o tamanho do |diffPct|. Essa regra protege contra vender abaixo do custo, e tem prioridade sobre a classificação por magnitude.
Responsabilidades: achar o preço que ganha a buy box ou melhora a posição; respeitar o piso de margem; agir sozinho em mudanças pequenas; pedir aprovação em mudanças grandes ou fora da margem; registrar tudo em audit log.
Diagrama 5 — O fluxo completo do Analista
5a · O gatilho completo
5b · O fluxo de decisão
5c · Regras em paralelo (como decide o preço, trava de margem, responsabilidades)
5d · Os sinais, por tier
Detalhe do analistaNode e do desfecho implementado por TIER (o que o código faz hoje, com nomes de função e audit): Analista — analistaNode e Desfecho por TIER.
6. Como o Ads otimiza campanhas por ROAS/ACOS, sem escrever no Mercado Livre
O Ads (Product Ads) cuida das campanhas de publicidade do vendedor: lê as métricas reais que o Mercado Livre expõe, analisa o desempenho de cada campanha e recomenda ajustes pra melhorar o retorno. A lógica de decisão é o "harvest flywheel", ele olha pra ROAS e pra impression_share e decide a próxima ação a partir disso. A diferença mais importante em relação aos outros agentes é que hoje ele nasce read-only: a API de escrita do Mercado Livre pra anúncios não está disponível, então tudo que ele faz é ler, analisar e recomendar, quem aplica é sempre o humano.
O gatilho: do CRON ads-sync ao evento ADS_REVIEW
Não existe webhook de ads. O gatilho é um CRON (ads-sync) que roda diariamente, recalcula às 10h GMT-3, olhando uma janela rolling de 90 dias com granularidade diária.
O primeiro passo é um pré-requisito com risco: descobrir o advertiser_id via GET /advertising/advertisers. Esse endpoint exige reputação amarela ou melhor, pelo menos 15 dias de conta e vendas mínimas, sem fatura vencida, se algum desses requisitos não for atendido, o Mercado Livre retorna 404.
Com o advertiser_id em mãos, o pipeline segue: busca campanhas, anúncios e métricas (campaigns/search + ads/search), salva no banco em 3 tabelas novas (MeliAdsCampaign, MeliAdsAd, MeliAdsMetricsDaily), junta esses dados com MeliItem e MeliCatalogCompetition (buy_box, preço, custo) e, por fim, emite o evento ADS_REVIEW, um por anunciante, todo dia.
advertiser_id é o identificador da conta de anúncios dentro do Mercado Ads, diferente do ID do vendedor. ROAS (Return on Ad Spend) é quanto retorno em vendas cada real investido em anúncio gerou. ACOS (Advertising Cost of Sale) é o inverso: quanto da venda foi gasto em anúncio. impression_share é a fatia das vezes que seu anúncio podia aparecer e de fato apareceu. CRON é uma tarefa que roda automaticamente em horários fixos, aqui, todo dia às 10h.
O fluxo de decisão
Com o evento ADS_REVIEW em mãos:
- O evento
ADS_REVIEWchega (cron diário, por anunciante). - O sistema lê campanhas, anúncios e métricas dos últimos 90 dias do banco.
- A LLM analisa:
roasvsroas_target,acosvsacos_benchmarkesov(share of voice). - Decide a AÇÃO, usando a matriz de decisão do flywheel (ver Diagrama 6c).
- Classifica o IMPACTO dessa ação, o que define o sinal.
A matriz de decisão (o "flywheel")
A matriz é o coração do agente: ela traduz métricas reais do Mercado Livre em ações.
lost_impression_share_by_BUDGETalto: está perdendo espaço por orçamento baixo, há demanda, vale subir o budget.lost_impression_share_by_AD_RANKalto: está perdendo por ranking, subir budget não resolve, isso vira handoff pro Anúncios (ajustar o anúncio) ou pro Analista (ajustar o preço).roas < roas_target: anúncio fraco, otimizar ou pausar.roasmuito acima do alvo (folga): escalar o budget.recommended = trueestatus = idle: o Mercado Livre está dizendo que vale a pena anunciar esse item, e ele está parado, ativar.status = hold(pausado ou sem estoque): não adianta anunciar, avisa sobre estoque/anúncio.acosvsacos_benchmarkfunciona como régua de referência geral.
Pra alimentar essa matriz, o agente lê (verbatim) acos, roas, sov, cpc, ctr, cvr, cost, clicks, prints, impression_share, top_impression_share, lost_impression_share_by_budget/_by_ad_rank, acos_benchmark, recommended, buy_box_winner e as vendas direct/indirect/organic. E o que ele controlaria, se pudesse escrever: o modo (Automático ou Personalizado), a strategy (PROFITABILITY, INCREASE ou VISIBILITY), o budget diário, o roas_target (de 1x a 35x) e o status (active/paused).
lost_impression_share é a fatia de exibições perdidas, dividida entre "por orçamento" (o budget acabou) e "por ranking" (o anúncio não é bom o suficiente, mesmo com budget sobrando). recommended é um sinalizador que o próprio Mercado Livre calcula, indicando que aquele item tem potencial pra anúncio. strategy é a estratégia de otimização da campanha: priorizar lucro (PROFITABILITY), vendas (INCREASE) ou alcance (VISIBILITY).
Os sinais
- Verde, leitura/dashboard: mostra e analisa ROAS, ACOS, SOV, impression_share, lost_share e os itens recomendados. Só leitura, risco zero, sempre automático, é o que a API realmente permite hoje.
- Amarelo, ajuste pequeno: por exemplo subir o budget ±10-20% dentro do alvo, ou ativar um item recommended que está idle. O agente recomenda, o humano confirma e aplica, é uma mudança pequena, que mexe pouco em dinheiro.
- Vermelho, escrita de impacto: budget grande, pausar campanha, mudar strategy ou roas_target. Alto impacto financeiro vai pra aprovação (tier 3), e hoje, além disso, a write API do Mercado Livre está indisponível, então fica bloqueado de qualquer forma.
A página de documentação "product-ads-leitura-e-escritura" não tem conteúdo público, a escrita não está documentada, e os endpoints legados foram desativados em 26/02/2026. Por isso o agente nasce read-only: ele recomenda, quem executa é sempre o humano.
Diagrama 6 — O fluxo completo do Ads
6a · O gatilho completo
6b · O fluxo de decisão
6c · Contexto em paralelo (matriz de decisão, métricas, config)
6d · Os sinais
7. Como o Anúncios otimiza título, atributos e imagens, em 2 passadas com o Criativo
O Anúncios cuida da ficha do produto: título, atributos e imagens, otimizando pra conversão, que é o #1 fator de ranking no Mercado Livre (não keyword stuffing). Ele trabalha em 2 passadas: na primeira, propõe mudanças (título, atributos, quantos slots de imagem precisam ser preenchidos); aciona o Criativo pra gerar as imagens que faltam; e na segunda passada, aplica tudo de fato no anúncio. O "freio" desse agente é o title-validator, que garante que o título final respeita o limite de caracteres da categoria (em geral 60) e não usa palavras proibidas.
O gatilho: 2 fontes convergem em LOW_SEO
Existem 2 caminhos que disparam uma otimização de anúncio:
O primeiro é o CRON seo-audit, a fonte principal: ele varre os anúncios, calcula o seoScore de cada um (via scoreListing) e, se o score for baixo, emite o evento LOW_SEO. Hoje esse job ainda é um stub.
O segundo é um handoff do SAC: quando o agente de atendimento detecta uma dúvida recorrente sobre o mesmo assunto (detectedPattern, routeTo: anuncios), normalmente porque o anúncio está com algum atributo faltando, ele aciona o Anúncios.
Em ambos os casos, o evento final é o mesmo: LOW_SEO { itemId, score, issues }. Pra otimizar, o agente lê o MeliItem (título, atributos, imagens, healthScore/performance) e o MeliCatalogProduct, a ficha oficial do catálogo, que diz quais atributos o Mercado Livre espera pra aquele tipo de produto. É contra essa ficha que ele preenche atributos faltantes e melhora o título.
O fluxo de decisão: 2 passadas, com o Criativo no meio
- O evento
LOW_SEOchega (por item); o agente busca o item e a ficha do catálogo (getItem). - 1ª passada (
runAudit): a LLM analisa e propõerecommendedTitle,recommendedAttributese classificaimageIssues(0-7 problemas de imagem) e oseoScore. Tudo fica marcado comoapplied: false, é só uma proposta. - Se houver problemas de imagem (
imageIssues > 0), o agente aciona o Criativo, que gera as imagens necessárias e marcaimageIssuesResolved = true. - 2ª passada (
applyUpdate): o agente reentra no fluxo, o título passa pelo title-validator (ver Diagrama 7c) e, se aprovado, chamaupdateListing(title, attributes, pictureUrls), marcandoapplied: true(LISTING_UPDATE_AUTO). - O anúncio sai atualizado: novo título, atributos preenchidos e fotos completas, tudo registrado em audit log.
seoScore é uma nota que o sistema calcula pra cada anúncio, indicando o quão bem otimizado ele está pra busca e conversão. 2 passadas significa que o agente roda o fluxo duas vezes: na primeira só planeja (propõe), na segunda executa de fato (aplica), o que dá tempo pro Criativo gerar as imagens entre uma passada e outra. title-validator é uma checagem automática que revisa o título antes dele ser publicado.
O freio: title-validator e as regras do ML
O title-validator é a "guarda" do título: ele valida se o título respeita o limite de caracteres da categoria (em geral 60) e se não contém nenhuma palavra proibida. Se a LLM insistir numa palavra proibida, o sistema tenta de novo uma vez (retry); se mesmo assim falhar, ele recua e mantém o título atual (fallback_to_current_title, com warning). É o equivalente, pro Anúncios, ao que o compliance é pro SAC.
Por trás da proposta da LLM existe um conjunto de regras do Mercado Livre, vindas direto do prompt: conversão é o fator #1 de ranking, não keyword; o título tem um limite de caracteres que varia por categoria (em geral 60), com as palavras-chave na frente e sem enrolação; como o Mercado Livre não tem "backend keywords" (campo invisível de busca), o agente usa atributos estruturados e tags pra isso, e usa subtítulo + atributos no lugar de bullet points; preenche os atributos faltantes contra a ficha do catálogo; e cuida dos 7 slots de imagem possíveis, delegando a geração ao Criativo.
Palavra proibida aqui é qualquer termo que o Mercado Livre não permite em títulos de anúncio (por exemplo, termos de outras marcas, promessas exageradas etc.). Backend keywords é um recurso que existe em outros marketplaces (um campo de busca invisível pro comprador), mas não no Mercado Livre, por isso a estratégia muda pra atributos e tags visíveis.
Os sinais
- Verde, aplica auto: título válido e imagens prontas na 2ª passada, o
updateListingroda automático (LISTING_UPDATE_AUTO). É baixo impacto (título, atributos, fotos), não precisa de aprovação, e tudo fica no audit log. - Amarelo, em progresso ou degradado: ou (a) a proposta está pronta mas esperando o Criativo gerar as imagens (
applied: false, ainda na 1ª passada), ou (b) o title-validator caiu no fallback, manteve o título atual por causa de uma palavra proibida (warning). Em ambos os casos o agente aplica o que dá, mas sinaliza que ficou incompleto ou não ideal. - Vermelho, bloqueio ou falha: o title-validator bloqueou de vez (não trocou o título), ou houve falha técnica (
meli_fetch,llm_call,parse,meli_update, vira noop ou erro). Pela doutrina, um rewrite de alto impacto deveria pedir aprovação, mas hoje, na prática, ele é aplicado automaticamente, esse gate ainda não existe.
O ponto-chave: o Anúncios não age sozinho de ponta a ponta. Ele propõe na 1ª passada, o Criativo entra no meio pra preencher as imagens, e só então ele aplica na 2ª passada. Mexer em anúncio é considerado leve (verde, automático); o freio real é o title-validator, que vira vermelho só se uma palavra proibida travar o processo.
Diagrama 7 — O fluxo completo do Anúncios
7a · O gatilho completo
7b · O fluxo de decisão (2 passadas)
7c · Contexto em paralelo (title-validator e regras do ML)
7d · Os sinais
8. Como o Criativo gera as imagens do anúncio
O Criativo cuida das imagens do anúncio, hero (slot 1) mais até 7 slots adicionais. A imagem principal sozinha responde por cerca de 80% do CTR, é a peça mais importante do anúncio depois do título. Hoje o agente está com o fluxo inteiro ligado (briefing por LLM, upload, audit, loop guard), mas a geração da imagem em si ainda é um placeholder, o provider real (DALL-E, Stable Diffusion ou Replicate) está deferido pela ADR-09.
O gatilho: 2 fontes decidem quantos slots gerar
Existem 2 caminhos que acionam o Criativo:
O primeiro é o próprio Anúncios, na 1ª passada do fluxo dele (ver Parte 7): quando ele detecta imageIssues > 0, o Criativo lê state.outputs.anuncios.imageIssues pra saber quantos slots de imagem precisam ser gerados.
O segundo é um evento direto, IMAGE_ISSUE, com payload { itemId, slot, reason }, que pede pra corrigir um slot específico.
A função inferSlotsNeeded decide quais slots gerar a partir disso: se veio um IMAGE_ISSUE, gera só aquele slot; se veio do LOW_SEO, gera de 1 até imageIssues (no máximo 7); e se imageIssues = 0, cai num fallback que gera os slots 1, 2 e 3.
Pra gerar as imagens, o agente usa como contexto o item e o que o Anúncios apontou (imageIssues), além do sellerId e threadId, que servem de chave no storage. No fim, a saída volta pro Anúncios fechar a 2ª passada dele com as pictureUrls.
Slot é cada posição de imagem do anúncio (o limite varia por categoria, geralmente até 12, ou até 10 em produtos com variações, o agente trabalha com 7). Hero é a imagem principal, a primeira que o comprador vê. CTR (Click-Through Rate) é a taxa de cliques, quantas pessoas que viram o anúncio clicaram nele. Briefing é a instrução que a LLM gera descrevendo o que cada imagem deveria mostrar.
O fluxo: briefing real, imagem placeholder, upload, retorno
- O gatilho chega (
LOW_SEOouIMAGE_ISSUE), os slots já estão definidos. - A LLM gera o briefing (
criativoTaskPrompt→{ briefings[] }), descrevendo o que cada imagem deveria conter. Essa parte já roda de verdade (prova o prompt); se falhar, o sistema usa um briefing default. - O agente gera a imagem, mas hoje isso é um placeholder (stub da ADR-09): o mesmo PNG genérico é devolvido pra qualquer slot. O provider real de geração de imagem ainda está por plugar.
- As imagens (placeholders, por enquanto) sobem pro storage R2, com a chave
criativo/{seller}/{thread}/slot-N.png, gerando asgeneratedUrls[]. - O agente retorna
{ generatedUrls, briefings, imageIssuesResolved: true }pro Anúncios, com um registro de auditoriaIMAGE_UPLOAD. É aqui que entra o loop guard (ver Diagrama 8c): o Anúncios usa esse retorno pra fazer a 2ª passada dele.
Placeholder é um conteúdo genérico que ocupa o lugar do conteúdo final, até que ele seja implementado de verdade, aqui, uma imagem padrão no lugar da imagem real do produto. Stub é uma versão simplificada de uma função, que existe só pra não quebrar o fluxo, mas ainda não faz o trabalho completo. R2 é o serviço de armazenamento de arquivos (similar a um "HD na nuvem") onde as imagens geradas ficam guardadas.
O contexto: o loop guard e a estratégia de 7 slots
O loop guard é a decisão de design mais importante do agente: imageIssuesResolved é sempre true, mesmo quando o upload falha (nesse caso, generatedUrls vem vazio). O motivo é garantir que a 2ª passada do Anúncios sempre termine, sem travar a orquestração. O trade-off é que o anúncio pode fechar sem imagem nova, mas o erro fica registrado no audit/log, sem bloquear o fluxo.
A estratégia de 7 slots, que vem do prompt, prioriza a imagem principal (hero, slot 1), responsável por ~80% do CTR: fundo branco, produto ocupando ~85% do quadro. O slot 2 é tipicamente lifestyle (produto em uso), o slot 3 um infográfico (specs, dimensões), e assim por diante (o limite de slots varia por categoria, geralmente até 12, ou até 10 em produtos com variações). A doutrina aqui é clara: um hero excelente vale mais que 10 imagens medianas.
Os sinais
- Verde, entrega as imagens: briefing ok e upload ok, o agente devolve
generatedUrlseimageIssuesResolved, e o Anúncios aplica. É baixo risco, quem publica de fato é o Anúncios. A ressalva é que, hoje, a imagem entregue ainda é um placeholder, funciona mecanicamente, mas não é arte real. - Amarelo, degradado: ou (a) a LLM do briefing falhou e o agente seguiu com briefings default, sem travar, ou (b) é a própria realidade do placeholder, uma imagem genérica no lugar da peça final. Em ambos os casos o fluxo funciona, mas o resultado não é o ideal.
- Vermelho, falha ou não implementado: o upload pro storage falhou, e mesmo assim o loop é liberado (
imageIssuesResolved: true, sem URLs). O grande vermelho aqui é estrutural: o provider de geração de imagem real está deferido (ADR-09 / STORY-024), então nenhuma imagem real é gerada hoje. O briefing existe, mas a arte de verdade ainda falta plugar.
Estado honesto: o Criativo está ligado de ponta a ponta (briefing por LLM, upload, audit, loop guard), só a geração de imagem é placeholder. Quando o provider real (DALL-E, Stable Diffusion ou Replicate) for plugado, só o passo 3 muda, o resto do fluxo já está pronto.
Diagrama 8 — O fluxo completo do Criativo
8a · O gatilho completo
8b · O fluxo de geração
8c · Contexto em paralelo (loop guard e estratégia de 7 slots)
8d · Os sinais
9. Como o Gestor orquestra os outros 5
O Gestor não age no Mercado Livre diretamente, ele distribui o trabalho entre os outros 5 agentes e faz o "standup" do time. A prioridade #1 dele é sempre a Reputação na conta.
O gatilho: 2 entradas, 2 modos
Existem 2 caminhos que acionam o Gestor:
O primeiro é o daily-standup, um CRON que dispara todo dia e gera o evento STANDUP_TRIGGER, isso aciona o modo STANDUP (relatório do time).
O segundo é o evento PATTERN_DETECTED, que vem do SAC (sac.detectedPattern): um padrão foi identificado (por exemplo, o SAC percebeu uma dúvida recorrente dos compradores), e isso aciona o modo ROUTE.
O Gestor é o único agente que "olha pra dentro": ele lê os outputs dos outros 5 agentes (sac.detectedPattern, anuncios.imageIssues, etc.) e os traces de execução (agente, tokens, custo, duração de cada chamada). Se nenhum dos 2 gatilhos disparar, ele não faz nada (noop).
Standup é uma reunião curta e diária, emprestada do método ágil, em que o time reporta o que foi feito, o que vai ser feito e o que está travando. Trace é o registro técnico de uma execução (quanto custou, quanto tempo levou, qual agente rodou). Padrão (pattern), aqui, é um comportamento recorrente detectado nas conversas com clientes, por exemplo, várias pessoas perguntando a mesma coisa.
O fluxo: os 2 modos
No modo ROUTE, que distribui o trabalho, o SAC detecta um padrão (PATTERN_DETECTED), o Gestor (LLM) decide quem deve corrigir aquilo, define um routeTo (anuncios ou criativo), e o especialista escolhido corrige a causa, não o sintoma. Por exemplo: se muita gente pergunta a medida de um produto, o Gestor manda pro Anúncios, que adiciona o atributo faltante no anúncio, em vez de o SAC ficar respondendo a mesma pergunta repetidamente.
No modo STANDUP, que é o relatório do time, o STANDUP_TRIGGER dispara diariamente, o Gestor lê os últimos 10 traces (agente, tokens, custo, duração), uma LLM gera { summary, insights[] }, e esse resumo do dia é entregue ao humano. Esse modo é puramente de observabilidade: o Gestor vê custo, tokens, agentes falhando e padrões, mas não age sozinho, ele reporta.
A doutrina: por que ele é o diretor
O Gestor segue um priority stack inegociável: #1 é a Reputação na conta (cancelamentos, claims, atraso no handling, se isso está em risco, tudo para); #2 é resolver problemas que sangram dinheiro (ruptura de estoque, preço fora da margem); #3 é crescer (otimizar anúncios, escalar). Sempre nessa ordem.
Por trás disso está o flywheel, a tese central do Bunker: anúncios melhores geram mais conversão, que melhora o ranking, que reduz o custo de aquisição, que aumenta o lucro, que financia anúncios ainda melhores, fechando o ciclo. O papel do Gestor é fazer os 5 agentes trabalharem como um time (não como 6 bots soltos) girando esse ciclo.
Os sinais
- Verde, coordena ok: um
routeTofoi decidido, ou um standup foi gerado (summary+insights[]). É baixo risco, o Gestor só distribui e relata, não executa nenhuma ação no Mercado Livre, então pode ser totalmente automático. - Amarelo, insight pede atenção: no standup, o Gestor aponta algo pro humano olhar, custo ou tokens subindo, um agente falhando, ou um padrão recorrente ainda não resolvido. Ele sinaliza, mas é o humano quem decide a prioridade.
- Vermelho, reputação em risco: a regra #1 do priority stack, reputação ameaçada, dispara "tudo para", prioridade máxima, ação imediata. Falhas técnicas (
llm_call/parse/wrong_kind) também caem aqui, viramnoopou erro.
Estado honesto: hoje o gestorNode faz 2 coisas no código, ROUTE (decide entre anúncios e criativo) e STANDUP (resumo dos traces). O priority stack e a regra "reputação = tudo para" são a doutrina do prompt, a inteligência de priorização ainda não é um gate executável no código.
Diagrama 9 — O fluxo completo do Gestor
9a · O gatilho completo
9b · O fluxo dos 2 modos
9c · A doutrina (priority stack e flywheel)
9d · Os sinais