Engenharia

O agent confirmou que definiu o lembrete. O lembrete nunca disparou.

Um job agendado tem duas pernas, ele dispara e ele entrega, e confirmar a primeira mente sobre a segunda.

ASR

Apollo Space Research

Apollo Space

· 11 min de leitura

“Pronto, vou te lembrar quinta às 9.” A mensagem aterrissa, o usuário fecha a aba, e o arranjo inteiro parece finalizado. Quinta às 9 chega. Nada chega. O usuário descobre às 9h40, num corredor, quando a pessoa que ele deveria pingar pergunta por que ele ficou em silêncio. O agent não estava mentindo quando disse pronto. Ele de fato escreveu o lembrete. Ele só nunca se responsabilizou pelo momento em que o lembrete deveria sair das suas mãos.

Esse gap, entre eu agendei e de fato chegou a você, é onde a maioria do software “proativo” silenciosamente falha.

Um job agendado tem duas pernas: ele dispara e ele entrega. Confirmar a primeira mente sobre a segunda.

Este post é sobre por que essas duas pernas se separam, por que uma confirmação animada piora a falha em vez de melhorá-la, e como fiamos um lembrete para que o agent fique responsável pela parte que de fato importa, a chegada.

A versão ingênua: um lembrete é uma linha que você escreve

A forma óbvia de construir um lembrete é a forma como parece de fora. Alguém pede um cutucão na quinta. O agent escreve uma linha em algum lugar, um horário, uma mensagem, um usuário, e responde que está definido. O trabalho, no que diz respeito à conversa, acabou.

Isso é satisfatório porque mapeia para como uma pessoa faz uma promessa. Você diz “vou lembrar”, e dizer isso parece fazê-lo.

Mas escrever a linha é só a primeira perna. Um job agendado tem duas pernas: ele dispara e ele entrega. A linha sentada numa tabela é um plano de agir, não um ato. Algo ainda tem que acordar no minuto certo, notar que a linha está vencida, e empurrar uma mensagem real por um canal real para um humano real que está, com sorte, olhando. O agent confirmou o plano. Ele não disse nada sobre a entrega, porque no momento em que falou, a entrega não tinha acontecido e não poderia ter.

Aqui está a armadilha silenciosa. A confirmação chega no exato lugar onde a falha será depois invisível. O usuário lê “pronto”, e desse segundo em diante, ele assume que o sistema está com isso. Ele para de segurar o lembrete na própria cabeça, que é o ponto inteiro de pedir um. Então quando a mensagem de quinta nunca dispara, não há atenção humana de backup para pegá-la, porque a confirmação já disse a ele para soltar.

Um lembrete que confirma a escrita mas não o envio não é um lembrete. É uma forma de fazer alguém parar de se preocupar com a exata coisa que está prestes a quebrar.

Duas pernas de um job agendado lado a lado: a perna esquerda é escrever a linha, que o agent confirma instantaneamente; a perna direita é a mensagem de fato disparando e alcançando um humano na quinta, que acontece depois e sem confirmação, e o gap entre elas é onde a falha se esconde.

Por que a segunda perna quebra tão frequentemente

A segunda perna falha por razões que não têm nada a ver com o agent ser esperto ou burro. São as razões sem glamour que todo time que já entregou um scheduler conhece de cor.

O acordador-de-coisas tem que de fato rodar. Algum background worker tem que pollar por jobs vencidos, no horário, para sempre, e background workers são a parte mais esquecível de qualquer sistema. Eles morrem em silêncio. Ficam para trás. Sobem num timezone diferente do que a linha foi escrita, então “quinta às 9” vira quinta às 9 em algum lugar onde ninguém mora. Nada disso aparece no chat onde a promessa foi feita. A conversa parece saudável até o exato momento da verdade.

Aí tem o canal. Disparar o job não é o mesmo que a mensagem aterrissar. O push pode ser enviado numa sessão que fechou. O email pode rotear para um lugar que ninguém checa. A notificação pode ser gerada perfeitamente e engolida por uma permissão que o usuário revogou três semanas atrás. O job disparou, um log em algum lugar até diz isso, e o humano ainda não ouviu nada.

Um job que disparou e um humano que ouviu são dois fatos diferentes, e só o segundo é o lembrete.

Essa é a parte que vale sentar com. Num programa normal, você às vezes consegue escapar confundindo “eu emiti o evento” e “o evento foi recebido”, porque um sistema lá na frente vai tentar de novo ou reclamar. Um humano às 9 da manhã na quinta não é um sistema lá na frente. Ele não tenta de novo. Não lança um erro que você pode pegar. Ele simplesmente não é lembrado, e descobre do jeito lento e caro, no corredor, às 9h40, por outra pessoa.

A correção ingênua: fazer o agent checar duas vezes re-confirmando

O primeiro instinto, depois de você se queimar, é fazer o agent mais reconfortante. Faça-o confirmar com mais força. “Lembrete definido para quinta às 9, chequei duas vezes, está no sistema.” Talvez fazê-lo re-declarar o lembrete, ler o horário em voz alta, soletrar o timezone.

Isso parece rigor. É decoração.

Re-confirmar a escrita uma segunda vez não toca a segunda perna de jeito nenhum. O agent ainda está parado no momento do agendamento, narrando o plano com mais confiança, enquanto não diz exatamente nada sobre o momento da chegada que ainda não aconteceu. Você deixou a promessa mais alta. Você não deixou a entrega mais provável. Se algo, você deixou o eventual silêncio mais chocante, porque o usuário confiou na reafirmação extra e soltou ainda mais forte.

Um agent confiante descrevendo uma ação futura ainda está só descrevendo-a. A checagem que importa não pode ser feita no momento em que o lembrete é definido, ela só pode ser feita no momento em que o lembrete deveria disparar. Qualquer quantidade de checagem dupla no momento da escrita é checar a perna errada duas vezes.

Essa é a razão inteira pela qual esse problema é traiçoeiro. O lugar natural para adicionar reafirmação é a conversa, e a conversa acontece dias antes do único momento onde reafirmação poderia ser conquistada.

Nosso jeito: responsabilize-se pela chegada, não pela intenção

A correção é mover a responsabilidade do agent de quando ele fala para quando a mensagem deveria aterrissar. O lembrete não está pronto quando a linha é escrita. Está pronto quando um humano é confirmado como tendo sido alcançado, e se não foi, o sistema tem que saber, e tentar de novo, e avisar alguém que está com dificuldade.

Então construímos o lembrete como um loop com uma condição de fechamento, não uma linha com uma confirmação.

Um lembrete agendado como um loop fechado: o agent escreve o job, um worker acorda no minuto vencido e dispara, a mensagem sai por um canal, um sinal de entrega volta, e no sucesso o loop fecha, enquanto no sem-sinal ele tenta de novo e, se ainda não consegue alcançar a pessoa, escala para um canal de fallback e sinaliza a si mesmo em vez de ficar em silêncio.

Percorra as pernas em ordem. A primeira perna é a mesma da versão ingênua, o agent escreve o job: o horário, a mensagem, a pessoa, o timezone tornado explícito para que “9” signifique 9 onde o humano de fato está. A parte honesta é o que o agent diz de volta: não “pronto, você será lembrado”, mas “agendado, vou confirmar quando de fato sair”. Ele promete a coisa que pode cumprir, e adia a reivindicação que ainda não pode fazer.

A segunda perna é a que nos recusamos a deixar desatendida. Um worker acorda no minuto vencido, acha o job, e dispara a mensagem por um canal. Aí ele espera por um sinal de que a mensagem foi de fato recebida, um acknowledgment de entrega, uma sessão que estava aberta, uma leitura, algo que distingue “eu enviei” de “eles receberam”. Se esse sinal volta, o loop fecha e o agent pode finalmente fazer a reivindicação que adiou: isto chegou a você, aqui está quando. Essa segunda mensagem, a depois da chegada, é a única confirmação honesta na sequência inteira.

E quando o sinal não volta, o sistema faz a coisa que a versão ingênua estruturalmente não pode. Ele trata o silêncio como um problema a resolver, não um job a marcar como completo. Ele tenta de novo. Se o primeiro canal continua escuro, ele escala para um diferente, o push não aterrissou, então tente o email; o email bounceou, então tente o lugar onde o usuário está de fato ao vivo agora mesmo. E se cada canal vem vazio, ele não silenciosamente arquiva o job como “disparado” e segue em frente. Ele levanta a mão. Um lembrete que não conseguiu alcançar seu humano é uma pequena falha que se anuncia em voz alta, enquanto ainda é pequena, em vez de ser descoberta no corredor às 9h40.

Um job agendado tem duas pernas: ele dispara e ele entrega. Não deixamos o agent confirmar a primeira até ter observado a segunda.

O que isso custa, e o que compra

Isso é mais caro que uma linha e um joinha, e a troca vale ser nomeada claramente.

Custa um loop permanente. O job não pode ser fire-and-forget; algo tem que esperar pelo sinal de entrega, segurar o budget de retry e se responsabilizar pelo caminho de escalação. Isso são mais partes móveis que “insira uma linha, responda pronto”. Pagamos isso de propósito, porque a versão barata não é mais barata, ela só move o custo lá para frente para um humano que descobre tarde, e um lembrete tardio em operações reais raramente é uma coisa pequena. A razão inteira pela qual alguém delega um cutucão é que o momento que ele guarda importa mais do que a pessoa pode se dar ao luxo de acompanhar sozinha.

O que isso compra é que a confirmação finalmente significa algo. Quando esse sistema diz lembrado, um humano foi alcançado, essa palavra agora é um fato sobre uma chegada, não uma esperança sobre uma escrita. E as falhas que costumavam se esconder até o pior minuto possível agora aparecem no momento em que acontecem, endereçadas a alguém que pode fazer algo a respeito, com o contexto completo de qual job, qual canal, qual pessoa. A promessa e a prova vivem na mesma perna.

A virada

Pergunte-se o que você de fato está comprando quando pede a uma pessoa para te lembrar de algo.

Não é o caderno. Não é o post-it ou a entrada de calendário, esses são a perna um, a escrita, e qualquer ferramenta pode fazer a perna um. O que você está comprando é a perna dois: uma segunda mente que vai carregar a coisa através do gap de dias e garantir que ela de fato te alcance, e que vai te procurar se não conseguir. O valor inteiro de “estou com isso” é a parte onde, se algo dá errado às 8h55 na quinta, a pessoa que disse isso se esforça para te alcançar de qualquer jeito, em vez de apontar para uma linha numa tabela e dizer bem, tecnicamente eu agendei.

Essa segunda perna é do que a confiança é feita, e é a perna que nenhuma mensagem de confirmação consegue fingir. Você não confia num colega porque ele escreveu seu lembrete. Você confia nele porque, na única vez em que o canal usual falhou, ele mandou mensagem, depois ligou, depois te pegou pessoalmente, porque te alcançar era o trabalho, e enviar nunca foi o suficiente. Um sistema ganha a mesma confiança do mesmo jeito: sendo responsável pela chegada, não pela intenção.

Um job agendado tem duas pernas: ele dispara e ele entrega. O agent que só confirma a primeira é um colega que promete lembrar e depois, na manhã que conta, está em lugar nenhum.


É isso que estamos construindo na Apollo Space: software que é responsável pelo momento em que a mensagem aterrissa, não pelo momento em que foi prometida, que observa seus próprios lembretes todo o caminho até um humano e levanta a mão quando não consegue. Se você já foi decepcionado por um “pronto” que se revelou só metade de um trabalho, você já sabe em qual perna você estava confiando.

A Apollo cuida da operação repetitiva da sua empresa pro seu time não precisar.

Entre na lista de espera: acesso antecipado, preço de usuário fundador e um lugar na primeira fila enquanto a gente constrói.

Entrar na lista de espera