Quase todo fabricante de software de gestão tem na lista uma integração que ninguém quer pegar: um sistema que está na operação de boa parte dos clientes, não publica API para parceiro e volta todo trimestre no motivo das vendas perdidas.
Ela costuma ficar parada pelo mesmo motivo. Ninguém sabe ao certo como esse sistema conversa com o próprio servidor, e descobrir isso lendo código decompilado e tráfego na mão toma semanas de um time que já está ocupado com o produto. O REA, projeto de engenharia reversa com agentes de IA que passou de 390 mil estrelas no GitHub, encurta bastante essa parte: o agente faz a pergunta, o REA lê o sistema e devolve cada conclusão junto com a prova de onde ela saiu.
Neste texto eu levo o REA para uma integração com um WMS sem API, na ordem em que ela acontece de verdade. Primeiro vem o que o REA lê e como ele marca o que viu, o que deduziu e o que não conseguiu responder. Depois, a leitura do app Android que roda nos coletores do armazém, a captura do tráfego desse app e a comparação entre duas versões dele, para saber o que mudou quando o fornecedor atualizar.
A descoberta é a parte que o REA deixa mais leve, e quem já fez integração assim sabe que o problema costuma aparecer depois, em produção. A segunda metade mostra onde a primeira versão de uma integração dessas quebra e como cada etiqueta de evidência vira uma regra de código: consulta pela referência antes de criar, conferência do que só estava no código, revisão humana com prazo e polling com limite. No fim, você sai com uma tabela de decisão para levar ao próximo sistema sem API que o comercial pedir.
Prefere conteúdo em vídeo? Abaixo nosso vídeo completo sobre o tema:
01
O que é o REA e o que ele lê
O REA (Reverse Engineer Anything) é um servidor MCP com uma CLI, publicado em github.com/morluto/rea com licença MIT. A análise roda na sua máquina, e ele conversa com o agente que você já usa: o npx rea-agents setup registra o servidor MCP no Claude Code, no Codex, no Cursor, no Gemini CLI e em outros agentes, e instala as instruções de uso que o agente segue. Para usar a CLI direto no terminal, o pacote também instala com npm.
$ npx rea-agents setup # reinicie o agente depois do setup $ npm install --global rea-agents $ rea --help
Em outubro de 2026 o repositório tinha 393,8 mil estrelas, e a maior parte do que circula sobre ele mostra como clonar um app ou abrir um jogo. O uso deste texto é outro: integrar com um sistema que o seu cliente já usa e do qual tem licença.
O trabalho com o REA segue um ciclo de quatro passos. O agente faz uma pergunta sobre um sistema, o REA escolhe a ferramenta certa, inspeciona o alvo e traça o código que interessa, e devolve o achado junto com a evidência que o sustenta. Com isso em mãos, o agente explica o comportamento ou escreve e testa uma implementação.
A lista do que o REA lê é longa: binário nativo, com Ghidra, Hopper ou IDA, app em JavaScript e Electron, assembly .NET, executável PyInstaller, APK de Android, firmware, site, banco SQLite, captura de tráfego e de pacotes, e ainda GPU, modelo de IA e formatos de jogo. Para quem faz software de gestão, o que interessa é o grupo que mostra o que um sistema faz por dentro e o que ele troca com outros sistemas, porque é com isso que se integra.
Para APK, o REA usa o JADX, que devolve as declarações do manifesto, as classes e os métodos decompilados, e o Apktool, para os recursos do app. Para tráfego, ele lê arquivos HAR, capturas SAZ do Fiddler Everywhere e, no Linux, o mitmdump.
O próprio projeto diz para que serve: pesquisa legítima, educação, interoperabilidade, preservação de software e análise de software que você tem ou está autorizado a examinar. Integração entra em interoperabilidade, e tudo o que vem a seguir parte de um app licenciado pelo próprio cliente.
02
Observado, inferido e sem resposta
Antes de apontar o REA para qualquer sistema, vale entender o formato do que ele devolve, porque é desse formato que saem as regras de código da segunda metade do texto. Todo resultado guarda a identidade do artefato lido e o lugar de onde saiu a conclusão, e separa o que foi observado, o que foi inferido e o que ficou sem resposta.
app.apk · sha256 7c1e…a90bApiClient.java · linha 142POST /pedidos com 6 camposobservado- observadoO que o REA viu acontecer, no tráfego ou no código que ele conseguiu traçar. É a informação em que você mais pode confiar.
- inferidoO que está escrito no código e que ninguém viu rodar. Provavelmente funciona do jeito que o código diz, mas ainda não foi exercitado.
- sem respostaO que nem o código nem o tráfego responderam.
Os nomes das etiquetas são os que eu uso no vídeo e aqui; no registro de evidência do REA elas aparecem como observações, inferências e pontos sem resposta. Guarde as três, porque cada uma vira uma decisão diferente na hora de escrever a integração.
03
O cenário: um WMS sem API que decide a venda
Para acompanhar a integração do começo ao fim, o texto segue um processo de negócio só. A Rota é uma software house de ERP para distribuidoras, com nove devs e sem SRE, e boa parte dos clientes dela controla o armazém no Cargo WMS. O Cargo não publica API para parceiro e roda um app Android nos coletores, os aparelhos que os separadores carregam pelo armazém.
No último trimestre, a Rota perdeu dois negócios pelo mesmo motivo: o cliente usava o Cargo WMS e a Rota não integrava com ele. Agora a Serra Azul Distribuidora, com dois centros de distribuição e 18 coletores, está na mesa e só assina se a integração existir.
A integração tem quatro partes, e o pedido 58.214 da Serra Azul, com 12 itens e R$ 9.870,00, passa por todas. O ERP manda o pedido para separação, o WMS separa em ondas, o ERP fatura quando a separação termina e, por fim, avisa a expedição. Uma onda é o lote de pedidos que o WMS manda os separadores buscarem nas prateleiras, e o Cargo processa esses lotes a cada dez minutos.
Se o sistema sem API do seu cliente for outro, como um ERP desktop, um portal de fornecedor ou um app de força de vendas, dá para trocar o WMS por ele em qualquer ponto do texto, porque a descoberta e as regras de código são as mesmas.
04
O REA lê o app do coletor
O primeiro alvo é o app que roda nos coletores, o cargo-coletor 8.3. O arquivo sai de um coletor da própria Serra Azul, que tem a licença do Cargo WMS, sem baixar o APK de fonte nenhuma de fora e sem contornar proteção.
Na prática, o APK instalado sai do aparelho pelo adb, a ferramenta de linha de comando do Android, com o coletor ligado no computador e a depuração USB ativa. Em coletor corporativo, essa liberação costuma passar pela TI do cliente.
$ adb shell pm path com.cargo.coletor package:/data/app/~~Qe1x/com.cargo.coletor-2/base.apk $ adb pull /data/app/~~Qe1x/com.cargo.coletor-2/base.apk cargo-coletor-8.3.apk
O pm path devolve onde o app está instalado, e o adb pull copia o arquivo para a máquina do REA. Para o JADX funcionar, essa máquina precisa de um JDK completo.
Com o APK em mãos, o agente faz a pergunta direto, e o REA aciona o JADX para decompilar o app. Resumindo a resposta:
› como o app cria e consulta uma onda de separação? rea · JADX em cargo-coletor-8.3.apk classe OndaApiClient · ev-0140 12 operações com caminho e campos status: SEPARANDO, SEPARADO, PARC, CANC nada visto rodando: tudo inferido
Dentro do pacote com.cargo.coletor, o REA acha a classe que fala com o servidor, a OndaApiClient, e dela saem doze operações, cada uma com o caminho e os campos que manda: criar onda, consultar onda, consultar pela referência do pedido, cancelar onda, reabrir separação, confirmar expedição e outras seis. O REA também encontra os quatro status que uma onda pode ter no Cargo:
SEPARANDO é a onda em andamento e SEPARADO, a separação completa. PARC é a separação parcial, que acontece quando falta item no estoque, e CANC é a onda cancelada. O PARC vai dar trabalho mais para a frente.
Por enquanto, as doze operações estão marcadas como inferidas. O REA leu o código do app, mas não viu nenhuma dessas chamadas acontecer, e para isso ele precisa do tráfego.
05
O tráfego confirma o contrato
Para ver as chamadas acontecerem, a Serra Azul separa três pedidos de teste num coletor de homologação, com o mitmdump no meio do caminho entre o app e o servidor do Cargo. O mitmdump é a versão de linha de comando do mitmproxy, um proxy que registra cada requisição e cada resposta que passam por ele, e desde a versão 10.1 ele grava a captura direto em HAR.
$ mitmdump --set hardump=homologacao-3-pedidos.har # o arquivo HAR é gravado quando o mitmdump encerra
O coletor precisa usar esse proxy e confiar no certificado do mitmproxy, instalado no aparelho de homologação. Se o app fixar o certificado do servidor, o que se chama de certificate pinning, a captura não abre o conteúdo das chamadas, e aí sobra conversar com o fornecedor ou seguir só com o que o código mostrou.
O REA lê o HAR, e cada requisição vira uma entrada com o método, o caminho, o corpo enviado e a resposta que voltou. Com essa prova, nove das doze operações passam de inferidas para observadas.
| # | OPERAÇÃO | CAMINHO | EVIDÊNCIA |
|---|---|---|---|
| 01 | criar onda | POST /v2/ondas | observado |
| 02 | consultar onda | GET /v2/ondas/{id} | observado |
| 03 | consultar pela referência | GET /v2/ondas?ref={pedido} | observado |
| 04 | listar itens da onda | GET /v2/ondas/{id}/itens | observado |
| 05 | iniciar separação | POST /v2/ondas/{id}/inicio | observado |
| 06 | registrar item separado | POST /v2/ondas/{id}/itens/{i} | observado |
| 07 | registrar falta de item | POST /v2/ondas/{id}/faltas | observado |
| 08 | finalizar separação | POST /v2/ondas/{id}/fim | observado |
| 09 | saldo do endereço | GET /v2/enderecos/{cod}/saldo | observado |
| 10 | cancelar onda | DELETE /v2/ondas/{id} | inferido |
| 11 | reabrir separação | POST /v2/ondas/{id}/reabrir | inferido |
| 12 | confirmar expedição | POST /v2/expedicoes | inferido |
As três que continuam inferidas não apareceram nos testes de homologação: cancelar onda, reabrir separação e confirmar expedição. Elas estão no código e ninguém as viu rodar. Também ficaram três perguntas que nem o código nem o tráfego responderam:
- sem respostaO POST que cria a onda aceita chave de idempotência?
- sem respostaExiste algum webhook que avise quando a onda termina?
- sem respostaO que o status PARC devolve nas quantidades?
Um achado da tabela segura a integração inteira: a consulta de onda pela referência do pedido foi observada. Se o POST de criar onda não aceita chave de idempotência, é essa consulta que permite saber se a onda de um pedido já existe antes de criar outra, e ela volta na seção 8.
O contrato todo fica num pacote de evidência. O rea evidence-export grava a forma canônica desse pacote num JSON, que a Rota versiona no repositório junto com o código da integração. Se o arquivo de destino já existir, ele é mantido, a menos que você passe --overwrite.
$ rea evidence-export /srv/rota/rea/cargo-coletor-8.3.json \
/srv/rota/integracao-cargo/contrato/contrato-8.3.json
06
Quando o WMS atualiza
Um sistema fechado muda sem avisar ninguém: semanas depois da descoberta, o Cargo publica a versão 8.4 do app do coletor, e a Rota roda a mesma análise no APK novo e exporta a evidência dele. O rea compare põe as duas evidências lado a lado, com a saída em TOON por padrão ou em JSON com --json, que dá para guardar ou ler num script.
$ rea compare /srv/rota/integracao-cargo/contrato/contrato-8.3.json \
/srv/rota/integracao-cargo/contrato/contrato-8.4.json
Se a integração mandasse o campo prioridade no POST de criar onda, ela quebraria sem erro aparente na primeira separação de um cliente que atualizasse o coletor. A rotina que isso cria é simples: a cada versão nova do app, a Rota roda a análise e a comparação antes de o cliente atualizar, e descobre a mudança no ritmo dela, sem esperar o chamado no suporte.
07
A primeira versão da integração e onde ela quebra
Com o contrato em mãos, dá para escrever a integração, e é nesse ponto que muito time monta uma versão parecida com esta. O ERP chama o Cargo WMS dentro da própria requisição e, como a chamada pode falhar, entra uma fila para segurar os retries. O WMS separa em lote e demora, então entra um job que consulta o status a cada cinco minutos e uma tabela de controle para lembrar em que passo cada pedido está e quantas vezes já tentou. Quando a separação termina, um segundo job fatura e avisa a expedição.
São cinco peças, cada uma com um jeito próprio de falhar, e as quatro falhas que aparecem em produção voltam, uma por uma, para uma etiqueta da descoberta.
1. O timeout que cria uma segunda onda sem resposta
O POST que cria a onda estoura o timeout de 30 segundos, e a fila manda de novo. Como ninguém sabe se esse POST aceita chave de idempotência, a integração não manda chave nenhuma, e o WMS cria a onda 3392 para o mesmo pedido que já estava na onda 3391. No armazém, dois separadores saem atrás dos mesmos 12 itens.
2. O status parcial tratado como erro inferido
O PARC estava no código do app e nunca apareceu nos testes. Quando a separação do pedido volta parcial, o job de polling não tem um caso para esse status, trata como erro, e o pedido fica parado até alguém perceber.
3. A consulta que não sabe quando parar sem resposta
Como não existe webhook, o job consulta o WMS a cada cinco minutos, só que o WMS processa o lote a cada dez. Metade das consultas não tem novidade para trazer, e nada no job diz quando ele deve desistir de um pedido que travou.
4. A expedição confirmada que não saiu inferido
Confirmar expedição era outra operação que só existia no código. A chamada falha de um jeito que ninguém previu, ninguém confere o resultado, e o pedido fica marcado como enviado sem ter saído do armazém.
As quatro falhas vêm do que a descoberta não conseguiu garantir, e trocar a fila por outra não resolve nenhuma delas. A correção começa pelas etiquetas.
08
Uma regra de código para cada etiqueta
Daqui em diante entra o skail, e eu faço parte da skail, então leia esta parte sabendo disso. O skail é uma plataforma de execução durável: o processo de negócio vira uma função escrita de cima para baixo, e a plataforma guarda o estado da execução e retoma de onde parou quando a aplicação cai, é reiniciada ou passa horas esperando alguma coisa.
Dois tipos de método fazem esse trabalho. A function orquestra os passos e decide o que vem em seguida. Os commands fazem as operações de I/O, como chamar o WMS, gravar no banco ou emitir a nota, e o resultado de cada command fica gravado no histórico da execução. Um command que falha é retentado até o retryCount dele, que é 5 por padrão, e um command que já gravou resultado não roda de novo quando a execução é retomada. A página Functions e commands explica as regras de cada um.
A integração com o Cargo WMS vira a function SepararNoWms, que recebe o id do pedido. A Rota dispara cada execução com um POST no endereço da function, como /trigger/integracao/v1.0.0/SepararNoWms/58214, usando o id do pedido como id da execução, do jeito que mostra Disparar uma função pela API. A fila, os dois jobs e a tabela de controle saem, e cada etiqueta da descoberta vira uma decisão escrita no código:
[SkailFunction]
public async SkailTask SepararNoWms(string pedidoId)
{
var pedido = await CarregarPedido(pedidoId);
var onda = await CriarOndaNoWms(pedidoId, pedido.Itens);
// sem webhook: consulta com intervalo crescente e limite
var intervalo = TimeSpan.FromSeconds(30);
StatusOnda status;
for (var tentativa = 1; ; tentativa++)
{
await SkailTask.Delay(intervalo);
status = await ConsultarOnda(onda.Referencia);
if (status != StatusOnda.Separando) break;
if (tentativa == 20)
{
await MarcarAnaliseManual(pedidoId);
return;
}
intervalo = intervalo * 2 < TimeSpan.FromMinutes(10)
? intervalo * 2 : TimeSpan.FromMinutes(10);
}
if (status == StatusOnda.Cancelada)
{
await MarcarAnaliseManual(pedidoId);
return;
}
// status parcial: uma pessoa decide, com prazo
if (status == StatusOnda.Parcial)
{
await AtualizarStatus(pedidoId, "aguardando decisão");
var decisao = SkailTask.WaitForEvent<DecisaoParcial>(
"DECISAO_PARCIAL", pedidoId);
var prazo = SkailTask.Delay(TimeSpan.FromHours(4));
if (await SkailTask.WhenAny(decisao, prazo) == prazo)
{
await MarcarAnaliseManual(pedidoId);
return;
}
if (!(await decisao).Faturar)
{
await AtualizarStatus(pedidoId, "aguardando reposição");
return;
}
}
var nota = await EmitirNota(pedidoId);
await AvisarExpedicao(pedidoId, nota.Numero);
// operação inferida: lê de volta no WMS e confere
try
{
await ConferirExpedicao(pedidoId);
}
catch (ExpedicaoNaoConfirmada)
{
await MarcarAnaliseManual(pedidoId);
}
}
Observado, mas sem chave de idempotência
Criar onda foi observado no tráfego, mas a pergunta sobre chave de idempotência ficou sem resposta. O command CriarOndaNoWms usa o achado que segurava a integração: antes de criar, ele consulta a onda pela referência do pedido e, se ela já existe, devolve a que existe. O timeout de 30 segundos é o do cliente HTTP dentro do command, e quando ele estoura, o runtime tenta o command de novo sozinho.
A página Escrever commands idempotentes trata desse caso no terceiro exemplo, o do sistema externo que não aceita chave, e recomenda usar a consulta por referência externa quando o sistema oferece uma.
Sem webhook: polling com limite
Não apareceu webhook, então a function consulta. O laço começa com 30 segundos de espera e dobra até o teto de 10 minutos, com limite de 20 consultas, o que cobre perto de 2 h 45 min. Entre uma consulta e outra, a execução hiberna sem ocupar a aplicação. Quando o limite estoura, o pedido vai para análise manual num command, que fica registrado e aparece no Monitor. O padrão é o da página Polling de sistema externo. A onda que volta cancelada também vai para análise manual.
Inferido: o status parcial vai para uma pessoa, com prazo
Quando a onda volta PARC, a function grava “aguardando decisão” e espera o evento DECISAO_PARCIAL com o id do pedido ou o prazo de 4 horas, o que vier primeiro, com WaitForEvent, Delay e WhenAny. Quem decide é uma pessoa, na tela de separação parcial da Rota, e o clique dispara um POST /api/v1/fire/DECISAO_PARCIAL/58214 que acorda a execução. Se ninguém decidir em 4 horas, o pedido vai para análise manual. O padrão está em Esperar um evento com prazo, e o disparo, em Disparar um evento pela API.
Inferido: o que só estava no código é conferido
Confirmar expedição nunca foi visto rodando. Depois de avisar a expedição, o command ConferirExpedicao lê o status de volta no WMS. Se a expedição não aparece confirmada, ele lança exceção e tenta de novo até três vezes, porque o WMS pode levar um instante para refletir a mudança. Se as tentativas acabam, a exceção chega à function, que marca o pedido para análise manual em vez de seguir como se ele tivesse saído. Essa regra é deste exemplo: a doc não tem uma página só para ela, e o ConferirExpedicao é um command escrito do mesmo jeito que os outros.
[SkailCommand]
public async SkailTask<Onda> CriarOndaNoWms(string pedidoId, List<ItemPedido> itens)
{
// achado observado: a consulta pela referência do pedido
var existente = await _wms.ConsultarOndaPorReferencia(pedidoId);
if (existente is not null) return existente; // já criada: devolve a mesma
return await _wms.CriarOnda(pedidoId, itens);
}
[SkailCommand(retryCount: 3)]
public async SkailTask<StatusOnda> ConsultarOnda(string referencia)
=> await _wms.ConsultarStatus(referencia);
[SkailCommand(retryCount: 3)]
public async SkailTask ConferirExpedicao(string pedidoId)
{
// operação inferida: o WMS pode levar um instante para refletir
var status = await _wms.ConsultarExpedicao(pedidoId);
if (status != "confirmada") throw new ExpedicaoNaoConfirmada(pedidoId);
}
[SkailCommand]
public async SkailTask<Pedido> CarregarPedido(string pedidoId)
=> await _rota.Carregar(pedidoId);
O corpo dos commands não está na documentação, e eu completei no mesmo estilo dela. AtualizarStatus, EmitirNota, AvisarExpedicao e MarcarAnaliseManual chamam a Rota do mesmo jeito que o CarregarPedido.
09
O pedido 58.214 no Monitor
Na quinta-feira, 12 de novembro, às 09:14:05, a Rota dispara a SepararNoWms para o pedido 58.214, e o Monitor mostra cada passo da execução sem nenhuma instrumentação no código: argumentos, resultados, duração e tentativas de cada command.
O CarregarPedido conclui, e o CriarOndaNoWms estoura os 30 segundos na primeira tentativa. O runtime tenta de novo sozinho, a execução continua com um passo só, e o número de tentativas desse passo sobe para 2. Na segunda tentativa, às 09:14:36, a consulta pela referência acha a onda 3391, que a primeira tentativa já tinha criado no WMS, e o passo devolve essa onda sem criar outra.
Em seguida vêm as consultas de status, com intervalos de 30 segundos, 1, 2, 4, 8 e 10 minutos. As cinco primeiras voltam SEPARANDO, e entre elas a execução hiberna. Às 09:40:08, a sexta consulta volta PARC, com 11 dos 12 itens, porque faltou um item no estoque.
O fluxo grava “aguardando decisão” às 09:40:09 e entra na espera: o evento DECISAO_PARCIAL do pedido 58214 ou o prazo de 4 horas, que venceria às 13:40. Enquanto isso, a execução aparece no Monitor como aguardando evento, com o nome e o id esperados, e nada da aplicação fica preso a esse pedido.
Às 10:22, a Juliana Reis, coordenadora comercial da Serra Azul, abre a tela de separação parcial da Rota e escolhe faturar os 11 itens que saíram. O clique dispara o fire, a execução acorda, a nota 104.387 sai, a expedição é avisada e conferida, e a execução termina às 10:22:05.
Dos 68 minutos da execução, 26 foram de separação no armazém e 42 de espera pela decisão da Juliana, sem nenhum job rodando no vazio nesse tempo.
10
O que muda na arquitetura
Comparando com a primeira versão, saíram a fila, o job de polling, a tabela de controle e o job de faturamento. Ficaram a Rota disparando a execução, a function SepararNoWms e o Cargo WMS, e o que estava espalhado em cinco peças, com o estado numa tabela, passou a estar num método que se lê de cima para baixo.
O Cargo WMS continua sem API oficial, e isso nenhuma plataforma muda. O que muda é que a integração ficou num código que dá para ler e acompanhar, e o rea compare avisa quando o WMS mudar por baixo.
A tabela abaixo resume o que fazer com cada etiqueta quando você levantar o contrato do próximo sistema sem API:
| ETIQUETA | NO CÓDIGO | ONDE ESTÁ O PADRÃO |
|---|---|---|
| observado | Chave de idempotência quando o sistema aceita, ou consulta pela referência antes de criar quando não aceita. | Escrever commands idempotentes |
| inferido | Um command que lê o resultado de volta e confere, com análise manual se não bater. | Um command a mais, no mesmo padrão dos outros |
| sem resposta | Revisão humana com prazo, nunca uma espera sem fim. | Esperar um evento com prazo |
| sem webhook | Polling com intervalo crescente, teto e limite de consultas. | Polling de sistema externo |
FAQ
Perguntas frequentes
O que é o REA (Reverse Engineer Anything)?
É um servidor MCP com uma CLI, de licença MIT, que faz engenharia reversa com agentes de IA. O agente pergunta sobre um sistema, o REA escolhe a ferramenta certa, analisa o alvo na sua máquina e devolve cada achado com a evidência de onde ele saiu. A instalação é pelo npx rea-agents setup, que registra o servidor no Claude Code, no Codex, no Cursor e em outros agentes.
O REA consegue ler um APK de Android?
Sim: para APK, ele usa o JADX, que devolve o manifesto, as classes e os métodos decompilados, e o Apktool, para os recursos do app. O JADX precisa de um JDK completo na máquina onde o REA roda. O tráfego do app entra por arquivo HAR, que o mitmdump grava com --set hardump.
Como integrar com um sistema que não tem API?
Comece levantando o contrato que o próprio sistema usa, a partir de um artefato licenciado pelo cliente, como o app do coletor, e de uma captura do tráfego em homologação. Separe cada operação em observada, inferida ou sem resposta e escreva a integração com uma regra para cada etiqueta: idempotência para o observado, conferência para o inferido e revisão humana com prazo para o que ficou sem resposta. Antes de prometer a integração, passe pelo jurídico, porque cada contrato de licença tem as próprias regras.
Como evitar pedido duplicado quando a API não aceita chave de idempotência?
Consulte pela referência do pedido antes de criar e, se o registro já existir, devolva o que existe. Quando o sistema não oferece nem essa consulta, a saída é guardar no seu banco os efeitos já aplicados e consultar antes de chamar. Os dois casos estão na página Escrever commands idempotentes, da documentação do skail.
O que o rea compare faz?
Compara dois pacotes de evidência do REA, como os contratos de duas versões do mesmo app, e mostra o que mudou, o que apareceu e o que ficou igual. O resultado vem em TOON por padrão e em JSON com --json. Rodar a comparação a cada versão nova do sistema fechado mostra a mudança antes de o cliente atualizar.
PRÓXIMO PASSO
Por onde começar
Escolha o sistema sem API que o seu comercial mais pede e comece pela descoberta: um artefato licenciado pelo cliente, como o APK do coletor ou o client desktop, uma captura em homologação e o pacote de evidência exportado e versionado junto com o código. Com as etiquetas em mãos, a tabela da seção 10 diz como escrever cada operação.
Se fizer sentido levar a integração para execução durável, o caso de uso Modernizar um sistema legado mostra o fluxo de um ERP antigo numa função linear, e o guia Migrar código existente mostra como tirar um fluxo de jobs, fila e tabela de controle sem reescrever o sistema. São exemplos para adaptar ao seu caso.
Para ver a descoberta e a execução no Monitor passo a passo, assista ao vídeo REA na prática.
