Headless, CI/CD e Claude Agent SDK
Objetivos de aprendizagem
- Rodar o Claude Code em modo não interativo com
claude -p(--print) em pipelines (task statement 3.6). - Produzir saída estruturada e parseável em CI com
--output-format jsone--json-schema. - Usar CLAUDE.md como contexto de projeto para o Claude Code invocado pelo CI (padrões de teste, fixtures, critérios de review).
- Explicar por que uma instância independente revisa melhor que a sessão que gerou o código, e como evitar comentários duplicados em re-reviews.
- Decidir entre Claude Agent SDK e API direta, e escrever um agente mínimo em Python com
claude-agent-sdk.
Modo headless: claude -p
Por padrão, claude abre uma sessão interativa — num job de CI isso trava o pipeline esperando input que nunca virá (é literalmente uma sample question do exame). A flag -p/--print roda em modo não interativo: processa o prompt, imprime o resultado no stdout e encerra.
# Autenticação em CI: chave via variável de ambiente / secret
export ANTHROPIC_API_KEY="${CI_ANTHROPIC_KEY}"
# Review não interativo com saída estruturada e validada por schema
claude -p "Revise o diff desta PR conforme os critérios do CLAUDE.md" \
--output-format json \
--json-schema '{
"type": "object",
"properties": {
"findings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"file": {"type": "string"},
"line": {"type": "integer"},
"severity": {"type": "string", "enum": ["high", "medium", "low"]},
"message": {"type": "string"}
},
"required": ["file", "line", "severity", "message"]
}
}
},
"required": ["findings"]
}'
--output-format:text(padrão),json(resultado + metadados, parseável),stream-json(eventos em tempo real, um JSON por linha).--json-schema: força o resultado a obedecer a um JSON Schema — essencial quando um script vai postar os achados como comentários inline na PR sem intervenção humana.
Cuidado com distratores da prova: não existem CLAUDE_HEADLESS=true nem flag --batch; redirecionar stdin de /dev/null não é o mecanismo documentado. A resposta é sempre -p/--print.
CLAUDE.md como contexto do CI
O job de CI roda no repositório clonado — portanto o Claude Code invocado por ele lê o mesmo CLAUDE.md e as mesmas .claude/rules/ que o time usa localmente. É esse o mecanismo para dar ao review automatizado os padrões de teste, convenções de fixtures e critérios de review do projeto: documente-os no CLAUDE.md e tanto humanos quanto o pipeline recebem as mesmas regras. Para geração de testes, inclua também os arquivos de teste existentes no contexto — evita que o Claude sugira cenários duplicados que a suíte já cobre.
Review por instância independente
Princípio cobrado no exame: a mesma sessão que gerou o código é pior revisora do próprio código. A sessão geradora carrega o contexto das decisões que tomou — tende a confirmar as próprias suposições e a "não ver" os defeitos que produziu. Uma instância nova (outro processo claude -p, sem o histórico da geração) examina o diff com olhos limpos, como um segundo revisor humano.
E em re-reviews após novos commits: inclua no contexto os achados do review anterior, instruindo a reportar apenas problemas novos ou ainda não resolvidos — senão o bot repete os mesmos comentários a cada push, e o time passa a ignorá-lo.
flowchart LR
PR[Pull request] --> G["Sessão A (gera código)"]
G --> D[Diff]
D --> R["Instância B independente
claude -p (sem histórico de A)"]
F0[Achados do review anterior] --> R
C[CLAUDE.md + rules
critérios do time] --> R
R --> J["JSON validado por --json-schema"]
J --> PC[Script posta comentários inline na PR]
GitHub Actions
A integração oficial com GitHub Actions usa a action do Claude Code com a chave em secrets. Um esqueleto típico de review de PR:
name: claude-review
on:
pull_request:
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: >
Revise o diff desta PR conforme os critérios de review
documentados no CLAUDE.md. Reporte apenas problemas novos
em relação aos achados anteriores fornecidos.
Claude Agent SDK: quando usar vs API direta
A API direta (SDK anthropic, Messages API) dá o bloco de construção: você envia mensagens e implementa por conta própria o loop agêntico, as ferramentas, o gerenciamento de contexto. O Claude Agent SDK (claude-agent-sdk) entrega o harness completo que move o próprio Claude Code: loop agêntico pronto, ferramentas built-in (Read, Write, Edit, Bash, Grep, Glob), subagentes, hooks, permissões, sessões e gerenciamento de contexto — programável em Python/TypeScript.
| Use API direta quando... | Use Agent SDK quando... |
|---|---|
| Chamada única ou pipeline simples (classificar, extrair, resumir) | O agente precisa operar sobre arquivos/shell com as ferramentas built-in |
| Você precisa de controle total sobre cada request e o loop | Você quer loop agêntico, subagentes, hooks e sessões prontos |
| Sem necessidade de ferramentas de sistema | Automação estilo "Claude Code programável" (CI, bots de review, agentes de codebase) |
Exemplo mínimo em Python — tudo abaixo é do Claude Agent SDK (pip install claude-agent-sdk), não do SDK anthropic da API direta:
"""Agente de review com o Claude Agent SDK (pacote: claude-agent-sdk).
ATENCAO: `query` e `ClaudeAgentOptions` sao do Agent SDK — o harness
completo do Claude Code (ferramentas built-in, permissoes, sessoes).
Nao confundir com `anthropic.Anthropic().messages.create(...)` da API direta.
"""
import anyio
from claude_agent_sdk import ClaudeAgentOptions, query
async def main():
options = ClaudeAgentOptions(
model="claude-opus-5",
system_prompt="Voce e um revisor de codigo rigoroso e objetivo.",
allowed_tools=["Read", "Grep", "Glob", "Bash(git diff*)"],
permission_mode="default",
max_turns=15,
cwd="/repo/checkout",
)
async for message in query(
prompt="Revise o diff da branch atual conforme o CLAUDE.md.",
options=options,
):
print(message)
anyio.run(main)
Autenticação e ambientes
ANTHROPIC_API_KEY— variável de ambiente padrão para autenticar tanto o CLI headless quanto o Agent SDK (em CI, injete via secret).- Ambientes gerenciados: variáveis como
CLAUDE_CODE_USE_BEDROCK(Amazon Bedrock) eCLAUDE_CODE_USE_VERTEX(Google Vertex AI) direcionam a autenticação para as credenciais nativas da nuvem, em vez da chave da Anthropic. - Nunca hardcode a chave em workflow/script versionado — sempre secret do CI.
Pegadinhas da prova
- Distrator típico:
CLAUDE_HEADLESS=true,--batchou< /dev/nullpara CI — inexistentes/gambiarras; o mecanismo é-p/--print. - Distrator típico: parsear a saída de texto livre com regex quando
--output-format json+--json-schemaexistem exatamente para isso. - Distrator típico: pedir que a mesma sessão que implementou "agora revise o que você fez" — auto-review herda os vieses da geração; use instância independente.
- Distrator típico: re-rodar o review a cada commit sem os achados anteriores no contexto — comentários duplicados e o time silencia o bot.
- Distrator típico: reimplementar loop agêntico + ferramentas de arquivo na API direta quando o requisito descreve o harness do Agent SDK; ou o inverso, adotar o Agent SDK para uma única chamada de classificação.
- Distrator típico: confundir o Message Batches API (custo −50%, janela de até 24h, sem SLA) com o modo headless — batch serve a jobs tolerantes a latência (relatório noturno), nunca a checks bloqueantes de merge.
Resumo em 5 linhas
claude -p(--print) roda não interativo em CI; sem ele o job trava esperando input.--output-format json(+stream-json) e--json-schemaproduzem saída estruturada e validada para scripts postarem achados em PRs.- CLAUDE.md/rules do repositório são o contexto do CI: padrões de teste, fixtures e critérios de review valem para humanos e pipeline.
- Review melhor em instância independente da que gerou o código; em re-reviews, inclua achados anteriores e peça só o que é novo/pendente.
- Agent SDK (
claude-agent-sdk:query+ClaudeAgentOptions) = harness completo (ferramentas built-in, subagentes, hooks, sessões); API direta = requests sob seu controle. Auth:ANTHROPIC_API_KEY(ou Bedrock/Vertex via variáveis próprias).
Documentação oficial
- Claude Code headless mode
- Claude Code GitHub Actions
- Claude Agent SDK — overview
- Claude Agent SDK — Python
Questões de fixação
1. O step de CI executa claude "Gere os casos de teste faltantes" e o job fica pendurado até o timeout. Qual é a correção?
Gabarito: B. -p/--print é o modo não interativo documentado: processa, imprime e encerra. A e C referenciam recursos que não existem. D não resolve — a sessão interativa continuaria esperando input que nunca chega, apenas por mais tempo.
2. Um script pós-processa o review do Claude para postar comentários inline na PR, mas quebra com frequência porque o formato da resposta varia. Qual é a solução robusta?
Gabarito: C. Enforcement no harness: a saída chega estruturada e validada contra o schema, pronta para o script. A trata sintoma — regex sobre texto livre sempre quebrará de novo. B é enforcement por prompt, probabilístico (pode vir com texto extra, chaves diferentes). D abandona o requisito de comentários inline em vez de resolvê-lo.
3. O bot de review reposta os mesmos comentários a cada novo commit da PR, e os desenvolvedores começaram a ignorá-lo. Qual mudança o exame recomenda?
Gabarito: A. É a prática do task statement 3.6: dar ao review o histórico de achados e pedir só o delta. B perde feedback cedo, quando é mais barato corrigir. C só remove repetições textualmente idênticas — o mesmo problema reformulado passa. D sacrifica a independência da instância revisora (e sessões de CI são efêmeras por natureza).
4. Você vai construir um bot interno que clona repositórios, explora o código com Grep/Read, edita arquivos e abre PRs de manutenção — orquestrado por um script Python. Qual base é a mais adequada?
Gabarito: B. O requisito descreve exatamente o harness do Agent SDK: agente operando sobre arquivos/shell com as ferramentas built-in do Claude Code, programável em Python. A reimplementa (mal) o que o SDK já entrega — meses de trabalho em loop, ferramentas e permissões. C é um mecanismo de custo/latência para lotes tolerantes a atraso, não um harness de agente (e não suporta o tool calling multi-turno necessário). D resolve integração de dados/ferramentas para clientes MCP, não a orquestração programática do agente.