Por muito tempo, venho construindo um sistema de IA complexo.
Ele começou como um produto bastante específico. Com o tempo, cresceu para incluir execução, ferramentas, memória, permissões, tarefas de longa duração, capacidades externas e múltiplas formas de produto. À medida que se tornou maior, passei menos tempo perguntando como adicionar outra funcionalidade e mais tempo fazendo um tipo diferente de perguntas: Onde uma capacidade deveria pertencer? Quem tem a autoridade final para interpretá-la? Quais decisões devem ser deixadas ao modelo, e quais garantias devem vir do software? O mecanismo que nos ajuda a entregar hoje se tornará uma fronteira da qual não conseguiremos escapar amanhã?
Essas perguntas parecem perguntas de arquitetura. Na prática, elas mudaram como eu penso sobre o próprio software.
O software tradicional é construído em torno de instruções. Um programador define o caminho antecipadamente, e a máquina o segue com precisão: se A acontece, faça B; se a entrada for C, retorne D. Muito do valor do software veio de transformar o julgamento humano em etapas estáveis e repetíveis.
A IA muda esse arranjo. Pela primeira vez, as máquinas podem decidir o que fazer em seguida em uma gama significativa de situações. Não precisamos mais enumerar cada caminho. Podemos descrever um objetivo, fornecer um ambiente e feedback, e deixar um modelo formar um plano, escolher ferramentas, observar o resultado e se ajustar.
Isso pode criar a impressão de que, à medida que os modelos se tornam mais capazes, o software se torna menos importante.
Minha experiência me levou à conclusão oposta. O software não está desaparecendo. O objeto de sua responsabilidade está mudando.
No passado, o software dizia à máquina o que fazer em seguida. Agora um modelo pode escolher o próximo passo, mas o software ainda precisa responder a um conjunto diferente de perguntas: O que é verdadeiro? O que é permitido? O que conta como completo? Quem é responsável quando algo dá errado? Como uma ação inteligente se torna um resultado em que as pessoas podem confiar?
Cheguei a acreditar nisto:
Os modelos geram possibilidades. O software transforma possibilidade em ordem.
O software não é mais apenas o conjunto de instruções em torno da IA. Ele está se tornando a camada institucional do mundo que a IA habita.
Os princípios abaixo surgiram gradualmente enquanto eu construía, descartava, reconstruía e verificava diferentes partes deste sistema. Eles não são um guia de arquitetura para um produto específico, nem uma metodologia universal. São simplesmente as ideias que agora considero dignas de levar para qualquer coisa que eu construa a seguir.
1. Defina o Que Você Está Construindo Antes Que a Interface de Hoje Defina o Destino
A deriva mais perigosa em um projeto de longa duração não é errar uma funcionalidade. É esquecer gradualmente o que você se propôs a construir.
Os produtos sempre começam por um ponto de entrada concreto. Pode ser uma interface de chat, um utilitário de desktop, um editor, um navegador ou uma bancada de trabalho. Como essas coisas são visíveis e utilizáveis, elas facilmente começam a definir o projeto inteiro ao contrário: o projeto se torna tudo o que existe hoje em telas, e seu futuro se torna uma expansão da funcionalidade atualmente mais madura.
Mas o produto atual é frequentemente um veículo para validar o destino, não o destino em si.
Aprendi a separar deliberadamente três coisas: o que eu quero, em última análise, construir, a fundação comum necessária para apoiar esse objetivo, e o que os usuários podem genuinamente usar hoje.
Os três devem se conectar, mas nunca devem se passar uns pelos outros.
Se você fala apenas sobre o destino, o projeto se torna uma visão sem entrega. Se você fala apenas sobre o presente, o projeto fica preso à sua interface atual e à implementação temporária. Se não há uma fundação comum, cada nova forma de produto precisa reinventar execução, estado, permissões e memória.
Essa distinção mudou muitas das minhas decisões. Parei de decidir onde uma funcionalidade pertencia apenas perguntando onde ela poderia ser implementada mais rapidamente. Comecei a perguntar se era uma experiência exclusiva do produto atual ou uma capacidade do sistema que produtos futuros também precisariam. Uma implementação temporária pode ser imperfeita, mas não se deve permitir que ela redefina o objetivo de longo prazo.
A primeira coisa de que um sistema de longa duração precisa não é um roteiro. É um senso de camadas: qual é a direção, qual é a fundação, e o que é meramente a forma como o sistema chega aos usuários hoje.
2. Pergunte “Quem É o Dono Disto?” Antes de “Como Construímos Isto?”
Muita da complexidade no software não é causada por código demais. É causada por responsabilidade que não tem lar.
Quando um conceito não tem um dono claro, ele naturalmente começa a se replicar. A interface mantém uma versão do estado, o backend mantém outra, e um arquivo de configuração mantém uma terceira. Nenhuma está obviamente errada, mas nenhuma pode dar a resposta final quando discordam.
O sistema então começa a crescer lógica de sincronização. Uma mudança em um lugar tem que notificar os outros dois. Uma notificação ocasionalmente se perde, então se adiciona recuperação. A ordem de recuperação se mostra instável, então se adiciona compensação. A compensação cria outro estado, então se adiciona reconciliação. O código trabalha cada vez mais enquanto o sistema se torna mais difícil de explicar.
Eu costumava ser atraído imediatamente pela questão de como conectar tudo. Agora faço perguntas diferentes primeiro:
- A quem este conceito pertence verdadeiramente?
- Quem o cria, o interpreta e o encerra?
- Se ele for desativado, migrado ou excluído, qual parte do sistema entende o significado completo dessa mudança?
- Os outros componentes recebem a verdade, ou meramente uma visão projetada a partir dela?
Somente depois que essas perguntas têm respostas é que a estratégia de conexão importa.
“Propriedade” soa como um termo de organização de código, mas acho que expressa um princípio muito mais amplo: qualquer coisa que persiste precisa de uma parte responsável por todo o seu ciclo de vida. Caso contrário, todos podem mudá-la, mas ninguém a entende verdadeiramente.
Isso também me deu uma forte preferência por um único interpretador final de cada fato. Outros componentes podem observar, armazenar em cache, apresentar e usar esse fato, mas não devem inventar versões igualmente autoritativas dele.
Sistemas complexos não têm medo de ter muito estado. Eles têm medo de ter autoridades demais.
3. Consolide Mecanismos, Não Experiências do Usuário
À medida que um sistema cresce, criar um novo mecanismo para cada novo requisito é tanto a escolha mais natural quanto a mais perigosa.
Uma capacidade é ligeiramente diferente, então ganha um novo caminho de registro. Um caso de uso é um tanto incomum, então ganha um novo modo. Uma peça de estado ainda não tem um lar óbvio, então ganha um armazenamento separado. Um novo caminho de execução é inconveniente de integrar, então contorna o caminho existente e cria outro.
Cada decisão parece razoável isoladamente. Juntas, elas produzem sistemas paralelos para descoberta, permissões, carregamento, atualizações, desativação e recuperação. O custo real não são algumas classes extras. É que cada capacidade futura tem que responder às mesmas perguntas novamente em todos esses mecanismos paralelos.
Aprendi gradualmente a distinguir entre dois tipos de diversidade: a diversidade que os usuários experimentam e a diversidade que o sistema deve manter internamente.
Os usuários podem e devem encontrar produtos, pontos de entrada e interações muito diferentes. Contextos diferentes merecem sua própria linguagem e modelos mentais. Mas por baixo dessas experiências, as capacidades podem entrar no sistema, receber permissões e adquirir ciclos de vida através de um pequeno número de mecanismos estáveis.
Consolide o mecanismo, não a experiência.
A parte difícil deste princípio é resistir à tentação de criar algo novo porque é mais fácil de conectar. Antes de introduzir outro mecanismo, agora pergunto se o atual verdadeiramente não consegue expressar a necessidade, ou se um novo é simplesmente mais conveniente no curto prazo.
“Parece um pouco diferente” geralmente não é motivo suficiente para criar um novo eixo no sistema.
Mecanismos estáveis não existem para fazer diagramas de arquitetura parecerem mais limpos. Eles reduzem o custo cognitivo futuro: modelos, desenvolvedores e produtos não precisam mais adivinhar entre várias maneiras quase equivalentes de fazer a mesma coisa.
4. O Software Deve Restringir Consequências, Não Prescrever o Processo de Pensamento do Modelo
É aqui que meu pensamento mudou mais.
Quando o comportamento do modelo é inconsistente, o impulso natural é codificar o fluxo de trabalho ideal no software. Exigir pesquisa antes do planejamento, planejamento antes da execução, e uma etapa concluída antes que a próxima possa começar. Executar verificação após cada mudança. Adicionar outro portão de execução sempre que o modelo parecer propenso a tomar o caminho errado.
Esses sistemas costumam ser projetados com boas intenções. Mas muitas vezes se transformam em pipelines rígidos. Um modelo que poderia adaptar sua abordagem ao tamanho e à forma da tarefa é forçado a completar todas as etapas, mesmo para uma solicitação simples. Múltiplas barreiras de proteção também podem interagir e criar um impasse do qual o modelo não tem como escapar.
Comecei a usar um teste mais simples para decidir o que pertence ao software e o que deve permanecer com o modelo: a regra restringe ummétodo ou umaconsequência?
“Ler antes de editar”, “apresentar uma proposta antes da implementação” e “lembrar de verificar ao final” são métodos. Eles pertencem aos prompts, às habilidades e ao contexto, onde o modelo pode compreendê-los e aplicá-los com flexibilidade.
“Não acessar dados sem autorização”, “não causar perda irreversível sem confirmação” e “não contornar uma permissão que o usuário desativou explicitamente” são limites sobre consequências. Eles não podem depender de o modelo se lembrar deles. O software deve aplicá-los.
Barreiras mecânicas de proteção contra repetição, inatividade e loops também devem ser usadas com parcimônia. Uma primeira tentativa deve ser permitida. Quando o sistema bloqueia uma ação, ele deve explicar o motivo. E deve oferecer um caminho claro de recuperação em vez de prender o modelo atrás da barreira.
Isso mudou como entendo a divisão de trabalho entre modelos e software:
Dê objetivos e métodos ao modelo. Dê limites inegociáveis ao software.
Se o software prescreve cada passo do processo de raciocínio, apenas reconstruímos um motor de fluxo de trabalho com IA dentro dele. Se cada limite vive apenas em um prompt, entregamos a responsabilidade real à probabilidade.
Um bom sistema evita ambos os extremos.
5. Mantenha a realidade inequívoca em vez de fazer o modelo soar seguro
O raciocínio de um modelo pode permanecer aberto. Sua linguagem pode variar. Seus planos podem ser revisados. Mas, uma vez que ele começa a agir sobre o mundo real, alguns fatos não podem ser ambíguos.
Uma tarefa realmente começou? Uma mudança realmente ocorreu? Uma permissão está habilitada? Qual sessão é dona de um resultado? A resposta a essas perguntas não deve mudar dependendo de qual tela as está observando.
Penso cada vez mais no software como a camada de realidade de um sistema de IA. Um modelo pode oferecer interpretações do mundo, mas o software registra o que realmente aconteceu nele.
Isso significa que uma interface pode expressar estado, mas não pode se tornar o próprio estado. Parâmetros anexados a uma solicitação podem expressar intenção, mas não podem substituir temporariamente uma autoridade durável. Um cache pode melhorar o desempenho, mas não pode adquirir o mesmo status de sua fonte. Quando o sistema não consegue estabelecer um fato, ele deve parar honestamente em vez de adivinhar a resposta mais conveniente para preservar uma sensação de fluidez.
O software tradicional também precisa de consistência, mas a IA torna isso ainda mais importante. Os modelos são excepcionalmente bons em continuar a partir de informações incompletas e produzir explicações que soam plausíveis. Quando os fatos subjacentes já divergiram, a inteligência no topo pode fazer a contradição parecer mais coerente e permitir que o problema permaneça oculto por mais tempo.
Meu princípio, portanto, é simples: permita que o modelo seja incerto, mas não permita que os fatos do sistema se tornem ambíguos.
Quando o sistema não sabe, ele deve dizer que não sabe. Quando dados autoritativos estão danificados, ele deve se recusar a agir. Quando duas fontes entram em conflito, ele deve exigir que o conflito seja resolvido em vez de escolher silenciosamente o mais fácil.
A inteligência pode trabalhar com ambiguidade. As instituições devem preservar a realidade.
6. A reversibilidade é um pré-requisito para a autonomia
Costumamos definir a autonomia da IA como fazer menos perguntas ao usuário. Mas o que determina se um usuário está disposto a abrir mão do controle não é o número de diálogos de confirmação. É se o sistema permite que ele veja, pare, corrija e se recupere.
Se cada passo exige confirmação, a IA se torna uma ferramenta semiautomática que exige cliques constantes. Se nada exige confirmação e não há registro nem caminho de volta, a autonomia se torna perda de controle.
Comecei a prestar mais atenção a um conjunto diferente de qualidades: O processo é visível? A ação pode ser interrompida? As mudanças podem ser revisadas? O histórico é rastreável? Após uma falha, o sistema consegue se recuperar para um estado cujo significado seja claro?
A reversibilidade não é uma camada extra de seguro para quando algo dá errado. É uma precondição para conceder autoridade em primeiro lugar.
Quando uma ação é fácil de desfazer, o sistema pode dar ao modelo mais espaço para tentar. Quando uma ação é irreversível, o sistema deve apertar as permissões e devolver a decisão ao usuário. O grau de autonomia não deve ser determinado por quão otimistas nos sentimos em relação a um modelo. Deve ser determinado por se é possível se recuperar das consequências.
Isso também mudou minha definição de “concluído”. Conclusão não é um status verde na interface. Significa que o sistema deixou claros o resultado, o risco remanescente e o caminho para a recuperação. Quando uma tarefa de longa duração é interrompida, a animação não pode simplesmente desaparecer. Quando uma mudança é rejeitada, metade do estado de execução não pode ficar para trás. Quando uma capacidade é desativada, a lógica de recuperação não pode silenciosamente trazê-la de volta na próxima vez que o aplicativo iniciar.
Quanto mais independentemente quisermos que a IA aja, mais cuidadosamente devemos projetar a forma como ela para e retorna.
7. Não apenas corrija bugs. Faça cada falha deixar um princípio
Qualquer projeto de longa duração encontrará muitas falhas. O que separa os projetos não é se as falhas ocorrem, mas a forma na qual elas permanecem depois.
A resposta mais fraca é fazer o sintoma imediato desaparecer. Uma resposta melhor é identificar e corrigir a causa raiz. A resposta mais valiosa vai um passo além: Que classe de falha foi essa? Por quais outros caminhos a mesma falha poderia retornar? O sistema está faltando uma regra, um único responsável ou uma estrutura que possa impedir o problema de voltar a crescer?
Desenvolvi o hábito de registrar mais do que o sintoma e a correção. Também registro a causa raiz, o responsável e a evidência que impediria uma regressão. Um problema descrito apenas por seus sintomas, sem um limite responsável e sem evidência, ainda não se tornou conhecimento.
Um patch corrige uma falha. Um princípio reduz uma classe inteira de falhas.
Se um bug de sincronização é corrigido adicionando mais uma notificação, ele pode retornar depois sob uma ordem de eventos diferente. Se a falha, em vez disso, estabelece o princípio de que cada peça de estado tem um único dono, o design futuro naturalmente conterá menos cadeias de sincronização. Se um antigo ponto de entrada cria ambiguidade de permissão, outro caso especial apenas adicionará outro ramo. Estabelecer que uma intenção tem um ponto de entrada canônico dá ao sistema uma regra de decisão durável.
Acho que isso importa ainda mais agora que a IA está participando do desenvolvimento de software. O código está sendo produzido mais rápido, e as correções locais estão se tornando mais baratas. Sem princípios, um sistema pode acumular implementações duplicadas plausíveis em uma velocidade sem precedentes.
A IA pode nos ajudar a escrever patches mais rápido. Os humanos ainda precisam decidir o que cada falha deve ensinar ao sistema.
O verdadeiro acúmulo de valor em um projeto não é seu volume de código ou o número de tickets que ele fechou. É se o custo das falhas passadas foi convertido em princípios que impedem que o mesmo custo seja pago novamente.
8. Não confunda a aparência de conclusão com evidência
A IA é muito boa em criar uma sensação de completude. Ela produz explicações bem estruturadas, código sintaticamente válido e resumos tranquilizadores. Mas as partes mais difíceis da engenharia muitas vezes vivem fora dessa superfície.
Uma interface que não mostra erro não prova que nada continua rodando em segundo plano. Uma capacidade funcionando em um ambiente de desenvolvimento não prova que ela existe no artefato entregue aos usuários. A validação em uma plataforma não prova comportamento idêntico em outra. Código passando por um verificador de tipos não prova que um antigo caminho autoritativo desapareceu do resto do sistema.
Com o tempo, passei a perguntar menos “Está pronto?” e mais “Qual evidência seria suficiente para provar que está pronto?”.
Evidência não é um indicador verde universal. Camadas diferentes respondem a perguntas diferentes. Verificações de código estabelecem a estrutura local. A validação em tempo de execução estabelece o caminho real de execução. A inspeção do artefato estabelece o que os usuários realmente receberão. Os testes de recuperação estabelecem se o sistema preserva o significado em condições não ideais.
Na era da IA, a validação não serve apenas para impedir que os modelos escrevam código incorreto. Ela também combate um risco mais sutil: um resultado pode ser tão logicamente convincente que todos passam a querer acreditar que ele já existe na realidade.
Uma das minhas regras mais importantes é não inferir fatos subjacentes a partir do estado da superfície, não inferir a correção de todo o sistema a partir de uma aprovação local e não apresentar um futuro não verificado como uma capacidade entregue hoje.
Respeitar a realidade às vezes significa admitir: “Isto ainda não está terminado.” Essa honestidade não enfraquece um produto. Ela dá ao sistema um ponto confiável a partir do qual continuar evoluindo.
O software está mudando de instruções para instituições
Olhando para trás, o que levei deste trabalho não foi uma arquitetura específica. Foi uma visão diferente do software de IA.
No passado, o software tentava enumerar caminhos. No futuro, mais desses caminhos serão gerados por modelos no momento. O software não precisa mais prescrever cada ação para a inteligência, mas precisa fornecer um mundo estável: identidades e propriedade claras, limites que não podem ser contornados, estado que preserva a realidade, formas de sair e se recuperar, e evidências que estabelecem se um resultado é real.
Isso é semelhante à relação entre instituições e indivíduos.
As instituições não pensam em nome de cada pessoa, nem deveriam transformar cada ação em um procedimento fixo. Elas definem a realidade compartilhada, os direitos, as responsabilidades e o que acontece quando algo dá errado. Boas instituições abrem espaço para a ação, ao mesmo tempo que impedem que a liberdade venha às custas da ordem.
O software está começando a desempenhar um papel semelhante na era da IA.
Não é o cérebro do modelo, e não deve competir pelo trabalho do modelo. É a lei, o registro, a fronteira e a memória do mundo que o modelo habita. Transforma uma ação inteligente improvisada no momento em uma capacidade estável. Transforma um sucesso acidental em um produto repetível. Permite que os usuários confiem trabalhos mais importantes à IA sem trocar a confiança cega pela conveniência.
Não acredito que a IA tornará o software menos importante. Pelo contrário, quanto mais capazes os modelos se tornam, mais o software deve responder às perguntas que os modelos não deveriam decidir por si mesmos.
O que é verdadeiro?
O que é permitido?
A quem pertence?
Como retornamos após uma falha?
Que evidências provam a conclusão?
Os modelos exploram as respostas. O software protege as perguntas.
Estamos passando de uma era em que as pessoas escreviam cada passo para as máquinas para outra em que as pessoas estabelecem princípios e as máquinas exploram caminhos. O papel do software muda junto: de descrever ações para estabelecer ordem.
Os modelos geram possibilidades.
O software torna essas possibilidades dignas de confiança.