\n\n\n\n Como Fazemos Chamadas de Arquitetura no OpenClaw - ClawDev Como Fazemos Chamadas de Arquitetura no OpenClaw - ClawDev \n

Como Fazemos Chamadas de Arquitetura no OpenClaw

📖 9 min read1,611 wordsUpdated Apr 2, 2026


Por que as decisões de arquitetura parecem muito mais difíceis do que são

Há alguns anos, passei três noites tentando adicionar o que parecia ser um recurso “simples” ao OpenClaw: um limitador de taxa por projeto para webhooks. Três noites. Nada do que tentei se encaixou de forma limpa. Cada mudança afetou cinco arquivos. Cada “correção” que fiz quebrou alguma integração que havíamos quase esquecido de 2021.

Esse foi o momento em que percebi que nosso problema não eram testes ausentes ou refatorações preguiçosas. O problema era que não havíamos sido deliberados o suficiente sobre as decisões arquitetônicas. Tínhamos código que funcionava, mas não gostava de ser mudado.

Se você contribui para o OpenClaw (ou está pensando em contribuir), quero te mostrar como nós realmente tomamos decisões sobre arquitetura agora. Não a versão idealizada “nós desenhamos um diagrama de caixa”. As coisas reais: as compensações, o “vamos nos arrepender disso, mas vale a pena” e os lugares onde intentionally mantemos as coisas entediantes.

O verdadeiro trabalho da arquitetura: tornar a mudança barata

Não me importo quão bonitos são os diagramas. Se fazer uma mudança custa um fim de semana inteiro e uma dor de cabeça, sua arquitetura está te enganando.

No OpenClaw, começamos a usar um teste muito simples para decisões arquitetônicas:

  • Isso torna a próxima mudança mais barata?
  • Isso torna o depuração mais rápida do que é hoje?

É isso. Não “este padrão está correto” ou “isso vai escalar para 10 milhões de usuários.” Não temos 10 milhões de usuários. Temos mantenedores que se esgotam quando adicionar um pequeno recurso significa ler 2.000 linhas de código não relacionado.

Exemplo: em agosto de 2024, introduzimos a abstração ExecutionPlan no executor de jobs. Antes disso, adicionar um novo passo de execução significava:

  • Editar o agendador central (má ideia #1)
  • Modificar 3 enums diferentes (má ideia #2)
  • Atualizar dois lugares que construíam consultas SQL manualmente (má ideia #3)

Encaramos a situação e criamos ExecutionPlan como um módulo separado. Sim, foi uma grande diferença (cerca de 1.200 linhas mudadas). Sim, isso quebrou uma série de scripts internos. Mas agora é um arquivo a ser compreendido, um lugar para conectar um novo passo, e o agendador não sabe nem se importa com os detalhes.

Foi “arquitetura perfeita”? Definitivamente não. Já reestruturamos partes dela duas vezes. Mas cada mudança desde então foi menor, mais segura e mais fácil de revisar. Essa é a única pontuação que realmente me interessa.

Como decidimos onde colocar uma funcionalidade (e quando dizer não)

A arquitetura em código aberto é especialmente estranha porque você não está apenas lutando contra a complexidade, mas também contra expectativas. Pedidos de funcionalidades chegam com opiniões fortes sobre onde as coisas “deveriam” estar.

Então, no OpenClaw, nos apoiamos em três perguntas simples ao decidir onde uma nova funcionalidade pertence:

  • Quem realmente possui os dados? (o código deve estar próximo dos seus dados)
  • Quem depura isso quando quebra? (mantenha em mente o modelo mental dessa pessoa)
  • Alguém pode excluir isso em um ano sem ler todo o repositório?

Deixe-me mostrar um exemplo concreto.

Em março de 2025, alguém abriu uma issue pedindo por “script Lua embutido dentro das definições de pipeline.” Uma ideia muito legal. Muito perigosa para a base de código. Havia três maneiras óbvias de fazê-lo:

  • Scripts embutidos dentro do parser YAML (tentador, mas amaldiçoado)
  • Adicionar uma camada de script dentro do núcleo do motor (muito amaldiçoado)
  • Tratar scripts como plugins com uma interface bem definida (mais chato, mais trabalho)

Se tivéssemos colado isso no parser YAML, teria sido mais rápido entregar, mas agora cada pequena mudança na sintaxe de configuração poderia quebrar scripts de clientes de maneiras estranhas. Isso é uma bomba-relógio para futuros mantenedores.

Escolhemos a interface no estilo plugin, sobreposta ao motor de execução de pipeline. Isso significou:

  • Um pequeno módulo de tempo de execução Lua, sem conhecimento sobre YAML
  • Um limite claro: Config → Engine → ScriptAdapter
  • Dois sinais de configuração para desativar o recurso em implantações que não o desejam

Isso demorou mais. O PR inicial foi o #1897, mesclado em 9 de abril de 2025, após quatro rodadas de revisão. Mas agora, se alguém quiser adicionar “JS embutido” ou “WASM embutido”, há um lugar muito claro para conectar. Pagamos uma vez por uma separação limpa; podemos reaproveitá-la repetidamente.

Dizer não também é uma decisão arquitetônica. Já fechamos issues com “isso pertence a um serviço auxiliar, não ao OpenClaw” mais de uma vez. Não é teimosia da nossa parte; é proteger o núcleo para que permaneça compreensível.

Padrões que usamos de propósito (e os que evitamos)

Há um museu de padrões que você pode arrastar para um projeto. A maioria deles não pertence ao OpenClaw.

Os padrões que realmente usamos, repetidamente:

  • Ports e adapters para integrações e IO
  • Internos orientados a eventos onde sabemos que adicionaremos mais ouvintes depois
  • “Configuração nas bordas” com código tipado no meio

Ports/adapters aparecem em toda a nossa base de código agora:

  • Armazenamento: StoragePort com adaptadores Postgres, S3 e sistema de arquivos
  • Mensageria: QueuePort com adaptadores Redis e NATS
  • Autenticação: AuthPort com adaptadores OIDC e de token estático

O benefício é simples: quando alguém apareceu no final de 2025 e queria suporte a MinIO, foi um adaptador de ~180 linhas em vez de “reescrever todos os locais de chamada que tocam armazenamento.” Essa é o tipo de compensação que estou feliz em fazer.

Coisas que evitamos na maioria das vezes:

  • Hierarquias de herança profundas. Preferimos dados + funções.
  • Abstrações excessivamente genéricas. Se o nome genérico é mais difícil de entender do que “PostgresStorage”, fazemos algo muito inteligente.
  • Singletons globais. Configurações e serviços são passados explicitamente na maioria das vezes. É um pouco irritante, mas a depuração é muito mais fácil.

Um exemplo específico de “demasiado inteligente” que removemos: o antigo “UniversalBackendManager” do início de 2023. Ele envolvia:

  • Armazenamento
  • Fila
  • Autenticação
  • Cache

Tudo por trás de uma mega-interface. Parecia bonito a princípio. Então tentamos mudar apenas a implementação de cache. Isso exigiu editar o gerenciador, a fiação de DI e metade dos testes. Em meados de 2024, o deletamos e o substituímos por quatro pequenas interfaces. Mais boilerplate, melhor vida.

Como registramos decisões (sem afogar em processos)

Documentos de arquitetura podem apodrecer mais rápido do que o código que descrevem. Portanto, mantemos deliberadamente leve. Você verá três coisas principais no repositório do OpenClaw:

  • ADRs (Registros de Decisão de Arquitetura) em docs/adr/
  • Comentários “Por quê” acima de caminhos de código estranhos
  • Descrições de PR que falam sobre compensações, não apenas “o que mudou”

Nossos ADRs são curtos. O para o novo agendador (ADR-0007, datado de 2024-11-02) é basicamente:

  • Contexto: agendador antigo muito atrelado à camada HTTP
  • Decisão: puxar o agendamento para um módulo de serviço separado
  • Alternativas: manter como está, ou mudar totalmente para uma fila externa
  • Consequências: um pouco mais de configuração, mas melhor isolamento e escalabilidade mais fácil

Isso dá cerca de uma página de texto. Você pode ler em menos de dois minutos. Mas quando um novo colaborador pergunta “por que o agendador é uma coisa própria?”, temos uma resposta que não se resume apenas a “porque Kai quis.”

O mesmo se aplica aos PRs: se você está mudando algo arquitetônico, realmente queremos ver:

  • O que você considerou, mas não fez
  • O que será mais fácil ou mais difícil depois que isso for implementado
  • Quaisquer escolhas “estranhas” que você fez de propósito

Você não precisa de um documento de design de 10 páginas. Alguns parágrafos honestos são suficientes.

FAQ

P: Sou um novo colaborador. Como evitar fazer uma mudança arquitetônica “ruim”?

Comece pequeno e comece alto. Abra um PR rascunho ou uma Discussão no GitHub com sua ideia antes de mexer em muitos arquivos. Mostre um pequeno protótipo, explique as compensações que vê e pergunte “onde isso deveria estar?” Você obterá feedback mais rápido, e não vai passar um fim de semana construindo algo que vamos sugerir mover de qualquer maneira.

P: Está tudo bem adicionar uma nova dependência ou serviço para suportar uma funcionalidade?

Sim, mas somos exigentes. Novas dependências devem tornar as coisas dramaticamente mais simples ou implementar algo que definitivamente não devemos fazer nós mesmos (cripografia, parsing sério, etc.). Novos serviços são aceitáveis se tiverem uma fronteira clara de API e não dependerem secretamente de acessar os internos do OpenClaw. Se parecer “apenas mais um helper”, provavelmente pertence aos módulos existentes.

P: Preciso escrever um ADR para cada mudança não trivial?

Não. ADRs são para decisões que mudam como as pessoas pensam sobre o código: novos módulos, novos padrões transversais, descontinuar abordagens antigas. Se você está reorganizando código interno, mas o modelo mental permanece o mesmo, uma descrição sólida de PR é suficiente. Quando tiver dúvidas, pergunte no canal #dev-architecture e nós diremos se merece um ADR.


🕒 Published:

👨‍💻
Written by Jake Chen

Developer advocate for the OpenClaw ecosystem. Writes tutorials, maintains SDKs, and helps developers ship AI agents faster.

Learn more →
Browse Topics: Architecture | Community | Contributing | Core Development | Customization

More AI Agent Resources

AgntkitAi7botClawseoBot-1
Scroll to Top