Módulo 4 · Launch Academy · Engenharia agêntica e de harness
Alembic Launch Academy · Módulo 4

Engenharia agêntica e de harness

Onde a IA realmente entra no Alembic — e por que o sistema trata todo modelo como I/O não confiável. Você vai seguir uma decisão atravessando as cinco camadas — adapterscouncilswarmharnessfactory — e aprender a pensar em evals, observabilidade e guardrails antes de soltar qualquer autonomia.

Cada seção tem uma camada Simples e uma camada Técnico — abra quando quiser o detalhe do código.
O que assumimos de você (muito pouco)
  • Você já viu um modelo de linguagem responder a um prompt — e às vezes errar.
  • Você não precisa saber TypeScript; mostramos o código, mas explicamos a ideia primeiro.
  • Você fez os módulos 1 a 3? Ótimo. Se não, este ainda fecha em si mesmo.
Ao fim desta lição você consegue
  • Explicar onde modelos entram no Alembic — e, principalmente, onde não entram.
  • Diferenciar as cinco camadas: adapters, council, swarm, harness e factory.
  • Descrever os guardrails reais: Result que nunca lança, park do T4, MCP read-only, budget.
  • Propor evals concretos para os pontos onde contrato encontra modelo.
  • Desenhar uma evolução agêntica sem quebrar os limites atuais do sistema.
01

A grande ideia

"Agêntico" não é soltar um agente e torcer. No Alembic é o oposto: contrato, budget, park, verifier e barramento de eventos vêm antes da autonomia. O modelo é a peça mais barata e mais substituível — o valor está no harness em volta dele.

A inversão que organiza o módulo inteiro
Visão ingênua: o agente é o produto. Eu dou um prompt esperto, ele decide, age e eu confio na saída.
Visão do Alembic: a saída do modelo é dado, não autoridade. Tudo passa por um adapter tipado, é validado, pontuado, registrado — e só então vira ação.
VISÃO INGÊNUA Prompt Modelo Ação ← confiança cega VISÃO ALEMBIC Prompt AdapterResult ValidarZod Gatefail-closed Ação ← provada
A mesma decisão, dois mundos: confiança cega vs. um caminho onde cada etapa é inspecionável.
Preveja antes de continuar

Se um modelo devolve um JSON malformado no meio de uma extração, o que o Alembic faz?

O adapter não lança exceção e não derruba o run. Ele devolve um Result de falha (um err) que o chamador trata explicitamente — e a etapa de parse (Zod) tenta recuperar o JSON antes de desistir. Errar é um estado de dado previsto, não um acidente.

Por que "I/O não confiável" é literal aqui

Um modelo é uma chamada de rede que pode dar timeout, devolver lixo, custar dinheiro ou mudar de comportamento entre versões. Tratá-lo como I/O significa: tipos na entrada e na saída, retry e circuit breaker no meio, e um Result<T, Error> em vez de throw. O @alembic/contracts é dono dos schemas; nenhuma biblioteca lança em código de produção.

02

O mapa agêntico

Modelos entram por adapters; o julgamento contestado passa pelo council; o trabalho autônomo é particionado pelo swarm; tudo é observado pelo harness; e o próprio Alembic é construído por agentes na factory.

Infográfico do mapa agêntico do Alembic: à esquerda os adapters como a cintura por onde modelos entram, ao centro o roteamento por tier T1/T2/T3 alimentando council (julgamento) e swarm (execução), e o harness como espinha de observabilidade emitindo eventos para HTTP/SSE/MCP; à direita a factory dos agentes de desenvolvimento.

Mapa agêntico: o modelo é a peça que entra por baixo; o harness é a espinha que observa tudo.

Adaptersa cintura do modelo T1extrair · barato T2refinar T3debater · caro Council5 eixos · GO/NO_GO Swarmtasks · park · resume Harnesseventos · SSE · MCP Factorycoding agents Verifiermaker-checker
O verifier (maker-checker) acompanha o council e o swarm; o harness é para onde toda a atividade flui como eventos.
03

As cinco camadas

Decore estas cinco e você entende 80% do módulo. Cada uma é um pacote real do monorepo, com uma responsabilidade única.

Camada 1
Adapters
modeloadapterResult<T>
clique para virar
O selo do modelo. Toda chamada de modelo passa por aqui: retry, circuit breaker, validação e um wrapper que nunca lança. packages/adapters
Camada 2
Council
notaGO
clique para virar
O julgamento contestado. Debate multi-perspectiva + pontuação de 5 eixos → GO/NO_GO inspecionável. packages/council
Camada 3
Swarm
park
clique para virar
A autonomia com limites. Tasks com id, dependência, profundidade máxima, park do T4 e journal durável. packages/swarm
Camada 4
Harness
coreHTTPSSEMCP (RO)
clique para virar
A espinha operacional. Conduz, observa e emite eventos. Vira status, frames SSE e tools MCP. packages/harness
Camada 5
Factory
agentagentAlembic(dev-time)
clique para virar
Quem constrói o Alembic. Agentes de codificação em sandbox no tempo de desenvolvimento — não é o runtime do produto. packages/factory
Guarde istoFactory ≠ Swarm. A factory usa agentes para construir o próprio Alembic (dev-time). O swarm é o runtime do produto que roda o trabalho do usuário. Confundir os dois é o erro mais comum do módulo.
04

Adapters: todo modelo é I/O

Imagine que cada modelo é um fornecedor terceirizado meio instável. Você não deixa um fornecedor assim falar direto com o cliente: você coloca um balcão de atendimento na frente, que valida o pedido, tenta de novo se cair, corta o fornecedor se ele começar a falhar em série, e nunca repassa um erro cru. Esse balcão é o adapter.

É a diferença entre "o modelo disse X, então fazemos X" e "o modelo propôs X; o balcão conferiu o formato, o custo e a saúde da conexão antes de qualquer coisa virar ação".

Três comportamentos do adapter que sustentam tudo o que vem depois:

Nunca lança. Exceções viram Result de falha. O run continua de pé e decide o que fazer com o erro.
Retry + circuit breaker. Falha transitória? Tenta de novo. Falha em série? Abre o circuito e para de insistir.
Validação na fronteira. Entrada e saída são checadas contra schema antes de cruzar a cintura.
Roteamento por tier. A faixa de risco escolhe o modelo mais barato que serve — não o mais caro por padrão.

O roteador por tier, ao vivo

O Alembic não fixa um modelo gigante para tudo. Ele escolhe por tier (faixa de risco/qualidade) e, dentro do tier, pega o mais barato com pickCheapestForTier. Clique em uma faixa e veja para onde a decisão vai:

T1

Extração barata e de alto volume

T1 o mais barato que extrai T2 qualidade média · refino T3 o mais forte · debate caro
CuidadoO Alembic se recusa a trocar um modelo silenciosamente. Se o modelo pedido não existe ou não responde, ele devolve err em vez de cair num substituto. "Falhar barulhento" é uma decisão de segurança, não um bug.

Onde isto vive

O wrapper que nunca lança está em packages/adapters/src/adapter-core.ts (retry, circuit, validação). O registro de modelos — tier, custo por 1k tokens de entrada/saída e capacidade — está em packages/contracts/src/registry.ts, junto com pickCheapestForTier. O gateway real é o cliproxyapi (um proxy puro); modelos locais MLX rodam por baixo.

# o caminho offline / $0: nenhum token sai, nenhuma rede é tocada
alembic distill <corpus> --offline
# quando o gateway está fora do ar, é exatamente este o fallback honesto

Custou caro ou o gateway está indisponível? O caminho --offline usa um adapter determinístico que entrega o resultado por US$ 0, sem fingir que chamou um modelo.

05

Council: julgamento contestado

Quando a decisão é ambígua — vale a pena lançar isto? este escopo é viável? — uma única chamada de modelo não basta. O council roda um debate multi-perspectiva e pontua o resultado em cinco eixos fixos, transformando o julgamento em algo inspecionável.

Os cinco eixos (e a armadilha do risco)

A nota é calculada sobre cinco eixos, cada um de 0 a 10, combinados por pesos fixos:

EixoO que medePeso
feasibilityConseguimos construir isto de fato?0,25
revenueHá receita plausível do outro lado?0,25
cxA experiência do cliente melhora?0,20
ttmTime-to-market: chega rápido o bastante?0,15
riskRisco — pontuado ao contrário: 10 = risco baixo0,15
A regra de ouro do scoring
Todos os cinco eixos somam na mesma direção: maior é melhor, inclusive risk (onde 10 = risco baixo). Não existe inversão GO/NO_GO. Aplicar um 1 - risk em qualquer lugar é justamente o que quebra o veredito — por isso os pesos somam 1 e a nota fica entre 0 e 10.
EIXOS (0–10, maior é melhor) feasibility8,0 ×0,25 revenue7,0 ×0,25 cx8,0 ×0,20 ttm6,0 ×0,15 risk (10=baixo)7,5 ×0,15 nota agregada7,4 GO
Eixos ponderados → nota agregada → limiar → veredito. Nada escondido em prompt: tudo é número auditável.

Onde isto vive

Os eixos, os pesos e o computeAggregateScore (puro) estão em packages/council/src/scoring.ts — a fonte única da verdade da ordem canônica dos eixos. O input do modelo é montado em context-pack.ts a partir do contexto e das fases anteriores. O debate com sequenciamento contrário (contrarian) é real, não só um adjetivo no prompt.

# sequência típica de gates num run
1. Scope Gate     # copia GOAL.md + plano + contrato para o run-dir
2. Council Gate   # GO/NO_GO opcional de pré-flight
3. Proof Gate     # roda unit.proof[]; falha fecha o run
4. Validator Gate # escrutínio independente por milestone
06

Swarm: autonomia com limites

O swarm é onde o trabalho autônomo de verdade acontece — e é exatamente por isso que ele é o mais cercado. Autonomia segura precisa de identidade, dependência, profundidade máxima, park e journal durável antes de uma única task rodar.

3
invariantes de profundidade, dependência e park
T4
a faixa que vai para o ledger, nunca roda sozinha
4
motivos de park: irreversible · legal · security · T4

O park do T4: o freio de mão

Nem toda task pode rodar sozinha. Tarefas irreversíveis, com implicação legal ou de segurança, ou marcadas T4, são roteadas para um ledger (o "park") e nunca executam sem um humano. O swarm registra cada uma num journal durável; depois você usa alembic approve, reject ou propose.

Infográfico do park do swarm: uma fila de tasks passa por um classificador classifyPark; tasks comuns drenam por dependência para execução com journal e checkpoint, enquanto tasks irreversíveis, legais, de segurança ou T4 são desviadas para o ledger do park onde aguardam aprovação humana via approve, reject ou propose.

O freio de mão do swarm: o que é perigoso demais não roda — espera um humano no ledger.

Fila de tasksclassifyPark ready? comum → roda Executar (dep. ok)journal + checkpoint irreversible · legal · security · T4 Park (ledger)espera humano alembic approvereject · propose
O classificador desvia o que é perigoso para o park; o resto drena por dependência. Resume e park são reais — não maquetes.
Preveja antes de continuar

Uma task "apagar a tabela de produção de billing" chega ao swarm. Para onde ela vai?

Para o park. É irreversível (e provavelmente também marcada de segurança). O classifyPark a desvia para o ledger e ela só prossegue depois de alembic approve por um humano. O swarm nunca executa esse tipo de task por conta própria.

Onde isto vive

O orquestrador está em packages/swarm/src/orchestrator.ts: ele monta a fila, parka o que precisa ser parkado e drena as tasks ready por dependência. A classificação e a entrada de ledger ficam em park.ts (classifyPark, makeParkEntry). O comentário do próprio arquivo é explícito: "irreversible/legal/security/T4 tasks are routed to the ledger and never run". A contagem de profundidade e as semânticas de resume/park são de verdade nesta fatia.

07

Harness: a espinha de observabilidade

O HarnessCore é o maestro, e ele é neutro em transporte. Ele faz start, poll, fanout e report, e empurra cada acontecimento para um barramento de eventos. Quem assiste — uma página HTTP, um stream SSE, um host MCP, uma futura tela de console — é só uma casca por cima. A lógica de negócio mora num lugar só.

Pense numa torre de controle: ela não pilota os aviões, ela todos e fala uma linguagem só (eventos). Cada painel na sala é uma vista diferente do mesmo fluxo.

A consequência prática: observabilidade não é UI. A UI é descartável; o que importa é o fluxo de eventos com sequência, lane e snapshots.

HTTP + SSE. alembic serve sobe um servidor com estado; POST /runs aceita goal/plan/contract e os eventos saem como frames.
MCP read-only. A superfície MCP é deliberadamente só leitura: não há tool de start nem fanout. Um host pode observar, não disparar.
CLI de observação. alembic runs list, tui <run-id>, tail -f — tudo lê o mesmo events.jsonl.
Replay. alembic replay <run-id> reconstrói o run a partir dos eventos + cache. O histórico é a fonte da verdade.
DicaA escolha de deixar o MCP só leitura é um guardrail de autoridade: clientes pouco confiáveis (um host MCP qualquer) podem inspecionar o estado, mas não podem iniciar trabalho. Para disparar um run você usa a CLI ou o POST /runs — superfícies sob seu controle.

Onde isto vive

O condutor é packages/harness/src/core.ts (start, poll, fanout, report, event bus). O servidor e os frames SSE estão em server.ts e http.ts; a superfície de tools em mcp.ts, cujo cabeçalho diz: "The MCP READ-ONLY tool surface… there is deliberately no start/fanout tool here". Cada tool valida os args por Zod antes de rodar e devolve um ToolResult tipado; nenhuma lança.

08

Os gates do veredito

Uma decisão não vira ação porque o modelo disse que sim. Ela atravessa um pipeline de gates, e o Proof Gate falha fechado: comando com saída diferente de zero derruba o run. É aqui que "agêntico com disciplina" deixa de ser slogan.

Gate 1

Scope

Copia GOAL.md, o módulo de plano e o contrato para o diretório do run.

Gate 2

Council

GO/NO_GO de pré-flight, opcional. Julgamento contestado antes de gastar.

Gate 3

Proof

Roda cada unit.proof[] como comando. Exit ≠ 0 → run falha. Sem perdão.

Gate 4

Validator

Escrutínio independente por milestone. O validador nunca é quem construiu.

Gate 5

Publish

Gera o curso visual-teach e publica gist/Pages. Só ao convergir.

Maker-checker
O padrão que costura o módulo: quem faz nunca é quem verifica. O verifier acompanha council e swarm fazendo a checagem independente; o Validator Gate repete isso por milestone. É retrieval de confiança, não cortesia.
Makerproduz o artefato artefato Checker (independente)verifica com evidência passa? sim Ship não → volta ao maker
Maker-checker em uma figura: o que não passa não segue — volta para quem fez, e quem verifica é sempre outro.

Cada string em unit.proof[] vira uma task bash -c que depende da unidade, e os resultados são persistidos em units/<id>/proof-results.jsonl. A prova é um artefato, não uma promessa.

09

Evals onde contrato encontra modelo

Onde colocar evals? Exatamente nas costuras onde um contrato tipado encontra a saída imprevisível de um modelo. Esses são os pontos onde o sistema pode mentir para si mesmo — e onde um teste paga sozinho.

Alvo do evalO que ele protegeModo de falha que pega
Recuperação de JSON na extraçãoO parser conserta JSON malformado em vez de quebrar.Modelo devolve JSON quase válido e o run cai.
Redação de PIIDados sensíveis são removidos antes de sair.Vazamento de PII num log ou numa resposta.
Limiares de scoringA nota agregada cruza o limiar certo.Inversão de risk flipando GO/NO_GO.
Claims do verifierO checker afirma só o que pode provar.Verifier aprova sem evidência.
Retry do adapterFalha transitória é re-tentada; em série, o circuito abre.Retry infinito ou desistência cedo demais.
Bloqueio por budgetGasto além do teto é barrado.Run estoura o orçamento sem ninguém ver.
Resume do swarmRetomar um run não duplica nem perde tasks.Task roda duas vezes após um resume.
Nota técnicaO caminho --offline torna evals herméticos e $0: o adapter determinístico dá saídas estáveis, então você testa o harness (parse, gate, score, park, resume) sem depender de um modelo de verdade. É assim que a suíte fica rápida e reproduzível.
10

Exemplo guiado: desenhar um eval

Vamos desenhar, do zero, um eval para o ponto mais escorregadio do council — a inversão do eixo de risco.

Eval: o risco não pode flipar o veredito
1
Fixture de entrada. Cinco eixos com risk = 9 (risco baixo) e os demais altos. Esperado: nota alta → GO.
2
Saída esperada. computeAggregateScore ≥ limiar; veredito = GO. Documente o número exato.
3
Modo de falha a pegar. Se alguém aplicar 1 - risk, o risco baixo viraria penalidade e o GO viraria NO_GO. O teste tem que vermelhar nesse caso.
4
Arquivo a testar. packages/council/src/scoring.ts — a fonte única da ordem dos eixos e dos pesos.
5
Prova. pnpm --filter @alembic/council test roda verde. Sem verde, sem mérito.
Agora você. Pegue uma linha da tabela de evals da seção 9 — digamos "bloqueio por budget" — e escreva os mesmos cinco itens: fixture de entrada, saída esperada, modo de falha, arquivo a testar e o comando de prova. Se você não consegue nomear o modo de falha, o eval ainda não está pronto.
11

Confusões comuns

"Agêntico é soltar agentes." Não. O repo mostra o contrário: contract, budget, park, verifier, event bus e stores vêm antes da autonomia.
"Harness é só a UI." Não. O HarnessCore é o condutor neutro em transporte. UI, HTTP e MCP são cascas por cima dele.
"Factory substitui swarm." Não. A factory constrói o próprio Alembic com coding agents (dev-time); o swarm é o runtime do produto.
"Risco alto baixa a nota." Cuidado: aqui risk = 10 é risco baixo e soma. Inverter é o que quebra o veredito.
Qual superfície é deliberadamente somente leitura para reduzir a autoridade de clientes pouco confiáveis?
A superfície MCP (packages/harness/src/mcp.ts) não tem tool de start nem fanout — um host pode observar, nunca disparar. Já a CLI e o POST /runs são superfícies sob seu controle e podem iniciar trabalho.
12

Recapitulando

Passe pelos cinco cartões — é a lição inteira em síntese. Use as setas do teclado.

A inversão

O modelo é I/O, não autoridade

Toda saída de modelo é dado: passa por adapter tipado, validação e gate antes de virar ação. O valor está no harness, não no prompt.

saída (dado)validargateação provada
1

As cinco camadas

adapters · council · swarm · harness · factory

Modelos entram por adapters; julgamento contestado pelo council; autonomia limitada no swarm; observabilidade no harness; o produto é construído na factory.

adapterscouncilswarmharnessfactory
2

Guardrails reais

Result, park, MCP read-only, budget

Nunca lança; T4 e o que é irreversível/legal/seguro vão para o park; o MCP só lê; o gasto é barrado por budget. Limites antes da autonomia.

ResultparkMCPread-onlybudget
3

Scoring

Cinco eixos somam na mesma direção

feasibility, revenue, cx, ttm, risk — todos "maior é melhor", inclusive risk (10 = baixo). Aplicar 1 - risk é o que flipa o veredito.

feasibilityrevenuecxttmrisk (10=baixo)soma →
4

Onde provar

Evals na costura contrato × modelo

JSON recovery, PII, limiares, claims do verifier, retry, budget, resume. O Proof Gate falha fechado e a prova é um artefato.

contrato (tipado)modelo (incerto)EVAL
5
Slide 1 / 5 Use
As cinco perguntas que todo design agêntico tem que responder
  1. Onde a saída do modelo é validada antes de virar ação?
  2. O que acontece quando o modelo falha — lança ou devolve um Result?
  3. Quais tasks são perigosas demais para rodar sozinhas (park)?
  4. Quem verifica — e é diferente de quem construiu?
  5. Como eu observo o run sem acoplar a uma UI específica?
13

Verifique seu entendimento

Três perguntas. Cada uma tem uma evidência no código que você pode conferir depois.

Quiz cumulativo
Por que o adapter devolve um Result de falha em vez de lançar uma exceção?
O modelo é I/O não confiável. Tratar a falha como Result mantém o run vivo e o erro explícito — em vez de derrubar tudo. Veja adapter-core.ts.
No scoring do council, o que significa risk = 10?
Todos os cinco eixos são "maior é melhor", inclusive risk (10 = baixo). Não há inversão; aplicar 1 - risk é o bug clássico. Veja scoring.ts.
Uma task irreversível chega ao swarm. O comportamento correto é:
classifyPark roteia irreversible/legal/security/T4 para o ledger; nada é descartado nem roda sozinho. Depois vem alembic approve/reject/propose. Veja orchestrator.ts + park.ts.
Acertos: 0/3
Se você consegue explicar, sem olhar, por que o MCP é read-only e por que o risco soma "ao contrário", você fechou o módulo 4.