Capstone project: build the linear task-orchestration agent at the heart of Brandon's SDLC harness — spec in, steps planned and executed sequentially with shared context, status report out.
Cada módulo neste caminho foi construindo em direção a uma pergunta: como é um sistema agêntico confiável quando você o executa de verdade? Este capstone responde com o mesmo padrão que uso no meu harness do SDLC — um agente linear de orquestração de tarefas que roda no meu Mac Mini, acionado por um arquivo de especificação simples em Markdown.
O agente faz quatro coisas, em ordem estrita:
claude-sonnet-4-6 que decompõe a especificação em etapas
numeradas.Sem subtarefas paralelas, sem handoff entre agentes especializados, sem framework de orquestração. A simplicidade é o ponto. O módulo 06 dá a teoria de por que isso funciona; este módulo dá o código funcionando.
Pense no agente como um empreiteiro que lê um briefing de projeto, escreve uma lista numerada de tarefas, trabalha do topo para baixo enquanto mantém notas sobre cada item concluído, e então arquiva um relatório de conclusão. As notas se acumulam — cada item na lista é informado por tudo que foi feito antes. Esse é o princípio de contexto compartilhado tornado concreto.
Por que "agente de pesquisa"? O título do módulo é herdado do caminho original. O build que você completará aqui é mais precisamente um agente de orquestração de tarefas — o mesmo padrão sustenta automação de pesquisa, pipelines de geração de código e qualquer coisa que precise de um plano executado passo a passo com um log em andamento.
O agente começa com um arquivo de especificação em texto simples. No harness do SDLC, isso é uma descrição de tarefa em Markdown; para este módulo qualquer arquivo de texto descrevendo uma tarefa funcionará.
Copie este bloco, crie um task-spec.md com qualquer descrição de tarefa e execute. O objeto
client é tudo que você precisa — sem wrapping adicional do SDK. Este é seu primeiro passo
executável, e verifica sua ANTHROPIC_API_KEY antes de você escrever mais código.
O tamanho da especificação importa. Se a especificação tiver milhares de tokens, a lista de etapas do Claude pode derivar ou se repetir. Mantenha as especificações focadas em uma tarefa. Divida projetos grandes em múltiplas especificações mais curtas em vez de um documento enorme.
Uma vez que a especificação é carregada, o agente pede ao Claude que a decomponha em uma lista numerada de etapas. O prompt é deliberadamente mínimo — queremos uma lista limpa de etapas, não explicação em prosa.
O analisador é simples: qualquer linha que começa com um dígito é uma etapa. Harnesses de produção frequentemente pedem saída JSON estruturada e analisam isso em vez disso, mas texto simples é mais fácil de inspecionar quando você está colocando o sistema em funcionamento pela primeira vez.
Antes de continuar, preveja: o que response.content[0].text contém após a chamada plan_steps
acima? A lista numerada de etapas gerada pelo modelo — não uma contagem de tokens, não o prompt
de sistema, não a resposta HTTP bruta. Adicione print(raw) antes da compreensão de lista e execute
contra uma especificação real para confirmar.
Planejamento é apenas uma chamada ao Claude. Não há nenhum planejador mágico aqui — apenas um modelo de linguagem lendo uma especificação e listando etapas. A confiabilidade vem de passar o plano completo e todos os resultados de etapas anteriores adiante para cada estágio subsequente.
O agente precisa fazer coisas — ler arquivos, escrever arquivos, executar comandos. No SDK da Anthropic, as ferramentas são definidas como schemas JSON que descrevem o que cada ferramenta aceita. Pense em uma definição de ferramenta como uma descrição de cargo que você entrega a um novo empreiteiro: um nome, o que a função faz e quais informações eles precisam para começar.
As descrições das ferramentas fazem trabalho real. Uma descrição clara permite que o modelo selecione a ferramenta certa sem nenhuma lógica de roteamento sua. Se o modelo continua escolhendo a ferramenta errada para uma etapa, melhore a descrição antes de recorrer a lógica condicional.
Agora adicione a função de despacho que roteia um bloco de chamada de ferramenta para sua implementação real:
Duas ferramentas, uma função de despacho, onze linhas. O módulo 03 mostrou como estender isso
incrementalmente — adicionar uma ferramenta run_command segue exatamente o mesmo padrão. Comece
com as ferramentas mínimas que a tarefa requer e adicione mais apenas quando tiver evidências de
que uma capacidade está faltando.
O loop de execução é onde a tese central do caminho se torna código. Cada etapa recebe o histórico completo de cada etapa concluída antes dela — não um resumo, não uma visão filtrada — para que as decisões do modelo sejam sempre ancoradas no que realmente aconteceu.
Observe que context["history"] cresce com cada chamada. A etapa 3 pode ver as etapas 1 e 2 em
pleno detalhe. É isso que torna as saídas coerentes — nenhuma etapa está trabalhando às cegas.
Quando nenhum bloco tool_use aparece, a resposta de texto do modelo é tratada como o resultado
da etapa e acrescentada ao histórico para que etapas posteriores ainda a vejam.
O que quebraria se você executasse todas as etapas em paralelo em vez de sequencialmente?
Cada etapa começaria com um histórico vazio. A etapa 3 não poderia saber que a etapa 1 já criou o arquivo que ela deveria ler. As etapas entrariam em conflito ou duplicariam trabalho, e o relatório final seria incoerente — exatamente o modo de falha que o módulo 06 descreve na armadilha multi-agente. Execução sequencial com contexto compartilhado produz melhor saída, mesmo quando paralelo parece mais rápido no papel.
Resista ao impulso de paralelizar. Cada etapa que você paraleliza é uma etapa que não pode ver o que as outras estão fazendo. Execução sequencial com contexto compartilhado quase sempre produz resultados mais coerentes do que execução paralela com contextos isolados.
Quando todas as etapas terminam, o agente pede ao Claude que transforme o histórico acumulado em um relatório de status legível por humanos, depois o escreve no disco.
O relatório resume o que o agente realmente fez, não o que planejou fazer. Se a etapa 2 falhou em encontrar um arquivo, o histórico capturou essa falha e o relatório reflete a realidade. Essa trilha de auditoria honesta é o que torna o sistema confiável o suficiente para usar em trabalho real.
Agora monte os quatro estágios em uma única função run_task_agent. Cada estágio chama uma função
que você já viu — sem nova lógica, apenas composição em ordem.
Este é o agente completo. Quatro estágios, seis funções, uma passagem linear pela especificação.
O harness do SDLC que rodo no meu Mac Mini segue exatamente essa forma — a versão de produção
adiciona um wrapper de retry em torno de execute_step e escreve logs estruturados, mas o loop
central é idêntico.
O que você acabou de construir é a coisa real. Uma especificação aciona uma chamada à API do Claude para gerar um plano; cada etapa do plano chama uma ferramenta real da Anthropic; o histórico completo passa por cada iteração; uma chamada final ao Claude escreve o relatório. Copie isso para um projeto e aponte para uma especificação real — ele funciona.
O módulo 06 explicará por que essa arquitetura é confiável: o princípio da corrida de revezamento (cada etapa passa o bastão — o contexto completo — para o próximo corredor), e por que sistemas multi-agentes falham quando essa passagem é quebrada. O que você construiu aqui é a demonstração prática da teoria.
O exercício abaixo estende o capstone com um gate de confirmação humana antes de o relatório ser escrito — o mesmo padrão de checkpoint do módulo 04, aplicado no momento exato em que um erro seria mais difícil de desfazer.
Application-level questions on the task-orchestration agent, shared context, and tool dispatching.
1. After `plan_steps(spec)` returns, what does the list contain?
Correct Answer: B
plan_steps filters the response for lines starting with a digit and returns a list of those step strings. The list comprehension discards blank lines and non-step prose, leaving only the numbered step content.
2. In `execute_step`, why is `context['history']` passed to Claude on every call?
Correct Answer: B
Shared context is the core reliability mechanism. Each step's prompt includes the full history of prior steps so the model's decisions are grounded in what actually happened — not assumptions about what might have happened.
3. What does `execute_step` do when the response contains no `tool_use` block?
Correct Answer: C
The loop exits without calling dispatch_tool. The model's text response is treated as the step result, appended to context['history'], and returned. This handles steps that are better answered with prose than a tool call.
4. You run all steps in parallel, each starting with an empty `context['history']`. Which failure is most likely?
Correct Answer: C
With an empty history, step 3 cannot know that step 1 already created a file it is supposed to read. Steps make incompatible assumptions, produce conflicting output, and the final report is incoherent — the multi-agent trap applied to a single-agent context.
5. The `read_file` description is changed to 'A file utility'. The model starts choosing `write_file` for read-only steps. What is the most likely cause?
Correct Answer: B
The model reads tool descriptions to select the right tool. 'A file utility' gives no signal about what the tool does or when to use it. Clear, specific descriptions are the first lever for fixing tool-selection problems.
6. The exercise adds the human gate BEFORE `write_status_report`. Why not after?
Correct Answer: B
Once write_status_report writes to disk, the artifact exists and may propagate to other systems. A gate before the write is a true checkpoint. A gate after the write arrives too late to prevent the file from being committed.
7. If the model requests a tool named `run_command` and `dispatch_tool` has no case for it, what happens?
Correct Answer: D
The final `return f'Unknown tool: {name}'` handles the fallback. The agent logs this string in context['history'] and continues — a safe default that produces an error message rather than an exception that would abort the entire run.
8. Which argument to `client.messages.create` enables the model to issue tool calls?
Correct Answer: C
The Anthropic SDK uses `tools=[...]`. `functions` is an OpenAI convention. `capabilities` and `tool_definitions` are not valid Anthropic parameters. Passing the wrong key means the model never sees the tools and will not issue any tool_use blocks.