Preparação para entrevista
PadrãoContexto e conhecimento

Isolamento de Contexto

Context Isolation

Isolamento de Contexto (Context Isolation) é um padrão de projeto de IA para apps com LLM e agentes, do grupo Contexto e conhecimento. Rodar subtarefas em contextos separados e trazer de volta só o resultado.

Elemento
19/70
Nível
Avançado
Leitura
8 min
Atualizado
Nesta página 18
  1. 01Intenção
  2. 02Problema
  3. 03Solução
  4. 04Estrutura
  5. 05Pseudocódigo
  6. 06Cenários reais
  7. 07Aplicabilidade
  8. 08Quando não usar
  9. 09Como implementar
  10. 10Variações
  11. 11Custo, latência e falhas
  12. 12Como avaliar
  13. 13Em produção
  14. 14Segurança
  15. 15Prós e contras
  16. 16Relações
  17. 17Código
  18. 18Teste seu entendimento
  19. ··Perguntas rápidas

Intenção

Rodar subtarefas em contextos separados e trazer de volta só o resultado. Serve para sistemas em que o material lido, o raciocínio intermediário ou as instruções de uma etapa atrapalhariam as outras se ficassem no mesmo contexto.

Em uma frase
Salas separadas numa redação: quem apura não escreve na mesa de quem edita, e só a matéria apurada atravessa a porta.

Problema

Sofia mantém um revisor automático de pull requests. Para revisar bem, ele precisa ler o diff, os arquivos tocados, os testes relacionados e o histórico de commits do arquivo. Tudo isso entrava no mesmo contexto da revisão.

Dois efeitos apareceram. O primeiro, previsível: o contexto passava de 100 mil tokens em PRs médios, e a revisão ficava cara e lenta. O segundo, menos óbvio: o revisor passou a comentar código que não estava no diff. Ele tinha lido o arquivo inteiro e apontava problemas antigos, que não eram assunto do PR. Os comentários úteis se perdiam entre os fora de escopo.

Resumir o material não resolvia. O revisor precisava, sim, olhar arquivos e testes, mas só para responder perguntas específicas (“esta função tem teste?”, “quem mais chama este método?”), não para carregar tudo enquanto escrevia a revisão.

Isso é irmão do Contexto Podre, com uma diferença: o material pesado nem deveria ter entrado no contexto que escreve. Compactar depois é limpar o que já contaminou. Isolar é não deixar entrar.

A pergunta que este padrão responde: como uma etapa usa muito material sem que esse material contamine o resto do trabalho?

Solução

Dê a cada subtarefa um contexto próprio, criado do zero, com só o que ela precisa: uma instrução autocontida, as ferramentas de leitura e, quando necessário, um pedaço do material. Quando a subtarefa termina, o contexto é descartado. Volta só um resultado curto, num formato combinado.

O contexto principal nunca vê o material bruto. Ele vê perguntas e respostas: “a função apply_discount tem testes?” e “sim, em tests/test_pricing.py, linhas 40 a 88, cobrindo desconto zero e desconto maior que o total”.

Isolamento é o princípio; Delegação a Subagentes é a forma mais comum de aplicá-lo, mas ele também vale para chamadas simples sem loop e para etapas de um workflow.

Exemplo trabalhado

O PR de Sofia muda só pricing.py. O revisor precisa saber se apply_discount tem teste, não precisa do arquivo de testes inteiro na mesa.

O contexto principal manda uma pergunta autocontida:

Pergunta: a função apply_discount em src/pricing.py, alterada neste PR, tem testes?
Escopo: responda só sobre cobertura desta função. Ignore falhas antigas em outras funções.
Formato: { "answer": string, "evidence": [{ "path": string, "lines": string }] }

O contexto isolado lê o que precisar e devolve:

{
  "answer": "Sim. tests/test_pricing.py cobre desconto zero e desconto maior que o total. Não vi caso de desconto negativo.",
  "evidence": [{ "path": "tests/test_pricing.py", "lines": "40-88" }]
}

O principal recebe umas 80 palavras e cita as linhas. Os milhares de tokens do arquivo de teste morreram no contexto isolado.

A conta, ilustrativa. Sem isolamento, um PR médio carrega diff (3 mil tokens) mais três arquivos (45 mil) em cada uma de 8 voltas: uns 384 mil tokens de entrada. Com isolamento, o principal fica com o diff e as respostas curtas (digamos 8 mil por volta, 64 mil no total) e os contextos isolados pagam a leitura uma vez. O custo total pode até subir, se houver muitas perguntas. O que cai, e isso é o ponto, é o contexto que escreve a revisão, e com ele os comentários fora de escopo.

A instrução tem que carregar as restrições. O contexto isolado não viu o diff. Se a pergunta omite “ignore falhas antigas”, ele reporta o teste que falta há dois anos.

Checagem +20 XP de primeiraO revisor comenta código antigo que não está no diff, porque os arquivos inteiros foram parar no contexto da revisão. Qual mudança ataca a causa?

Estrutura

flowchart TD
  M(["1. Contexto principal: revisão"]):::llm --> Q1["2. Pergunta autocontida"]:::tool
  Q1 --> C1(["3. Contexto isolado A"]):::llm
  C1 --> F[("4. Arquivos, testes, histórico")]:::store
  C1 -->|"5. resposta curta"| M
  M --> Q2["2. Outra pergunta"]:::tool
  Q2 --> C2(["3. Contexto isolado B"]):::llm
  C2 --> F
  C2 -->|"5. resposta curta"| M
  M --> OUT(["6. Resultado focado"]):::io
  1. O contexto principal cuida do objetivo (a revisão do diff) e decide o que precisa saber.
  2. Cada necessidade vira uma pergunta autocontida, que não depende do histórico do principal.
  3. Um contexto novo é criado para responder.
  4. Esse contexto lê o que precisar, quanto precisar.
  5. Volta uma resposta curta, com evidência; o contexto isolado é descartado.
  6. O principal termina o trabalho com um contexto pequeno e focado.

Pseudocódigo

schema Answer { answer: string, evidence: list[{ path: string, lines: string }] }

function isolated(question, tools, budget):
    # 3. contexto novo: nada do histórico do principal entra aqui
    ctx = new_context(system=READER_PROMPT, messages=[question])
    result = run_agent(ctx, tools=tools, budget=budget, output=Answer)    # 4
    trace.span("isolated", question, tokens=ctx.tokens)
    return result                                                         # 5. ctx é descartado

function review(diff):
    state.messages = [diff]
    while budget.check():
        reply = llm_with_tools(REVIEW_PROMPT, [ask_codebase], state)      # 1
        if reply.is_final:
            return reply.text                                             # 6
        for call in reply.tool_calls:                                     # 2
            answer = isolated(call.args.question, READ_TOOLS, budget.share(10))
            state.add(tool_result(call, answer))

Cenários reais

  • Agente de código. A exploração do repositório roda em contextos isolados. O agente principal recebe arquivos e linhas, não o conteúdo de dezenas de arquivos.
  • Pesquisa profunda com citações. Cada subpergunta é pesquisada num contexto próprio. As páginas lidas morrem ali; voltam afirmações com fonte.
  • Revisor automático de PR. A revisão olha só o diff; perguntas sobre o resto do código são respondidas em contextos isolados.

Aplicabilidade

  • Uma etapa precisa ler muito material e usar pouco dele.
  • O material lido distrai ou contamina o raciocínio da etapa principal.
  • Partes do trabalho precisam de instruções ou ferramentas diferentes que não devem se misturar.
  • Conteúdo não confiável precisa ser lido longe do contexto que tem ferramentas.

Quando não usar

  • O material é pequeno e todo relevante. Ler direto é mais simples e barato.
  • A etapa principal precisa raciocinar sobre todo o material ao mesmo tempo (comparar duas versões de um contrato cláusula por cláusula).
  • O problema é só o crescimento do histórico numa conversa. Compactação de Contexto resolve sem criar contextos novos.
Checagem +20 XP de primeiraVocê precisa comparar duas versões de um contrato, cláusula por cláusula. Um colega quer isolar cada cláusula num subagente. O que você faz?

Como implementar

  1. Identifique nos traces o material que entra no contexto principal e é usado só uma vez.
  2. Defina as perguntas que o principal precisa responder sobre esse material.
  3. Crie uma ferramenta que recebe a pergunta e roda num contexto novo, com ferramentas de leitura.
  4. Defina o formato da resposta, com evidência.
  5. Garanta em código que o contexto isolado não recebe o histórico do principal.
  6. Dê orçamento ao contexto isolado, descontado do total.
  7. Compare no eval: qualidade, tokens no contexto principal e custo total.

Armadilhas comuns

  • Passar o histórico ‘para ajudar’. Se o isolado vê a revisão inteira, você não isolou. A pergunta tem que ser autocontida.
  • Resposta sem evidência. O principal passa a repetir afirmações inventadas. Recuse evidence vazio no código.
  • Pergunta vaga. “Veja os testes” devolve um ensaio. “A função X, neste PR, tem teste? Ignore o resto” devolve um fato.
  • Orçamento só no principal. O isolado com while True é Loop Sem Fim numa sala ao lado. O teto vale para a árvore.

Variações

  • Chamada isolada simples. Sem loop: uma pergunta e um pedaço de material, numa chamada. Útil quando já se sabe o que ler.
  • Subagente isolado. Com loop e ferramentas, para explorar. É a Delegação a Subagentes.
  • Isolamento por segurança. O contexto isolado lê conteúdo não confiável e devolve dados estruturados. É o LLM Duplo.
  • Etapas de workflow. Cada passo de uma chain recebe só os campos de que precisa, não a saída inteira dos anteriores.

Custo, latência e falhas

Aspecto O que acontece Como aparece no trace
Chamadas Uma ou mais por pergunta isolada spans isolated filhos
Custo total Pode subir, porque contextos isolados releem material soma de tokens dos spans isolated
Custo do principal Cai muito, porque o contexto fica pequeno tokens de entrada estáveis no principal
Latência Perguntas independentes podem rodar em paralelo spans isolated sobrepostos
Falha: pergunta incompleta O contexto isolado não sabe uma restrição do principal resposta correta para a pergunta errada
Falha: resposta sem evidência O principal confia numa afirmação inventada campo evidence vazio

Como avaliar

  • Qualidade do resultado final com e sem isolamento.
  • Tokens no contexto principal ao longo da tarefa.
  • Comentários fora de escopo (no caso do revisor), que devem cair.
  • Acerto das respostas isoladas em perguntas com resposta conhecida.
{ "diff": "fixtures/pr-512.diff", "expected_comments": 2, "max_out_of_scope_comments": 0 }

Meça os dois custos. Time que olha só a fatura total às vezes desfaz o padrão, sem ver que os comentários fora de escopo que sumiram valiam mais.

Em produção

  • Span por contexto isolado, com pergunta, tokens e resposta.
  • Painel com tokens do principal contra tokens dos isolados.
  • Amostra de respostas isoladas sem evidência para revisão.
  • Alerta se o principal começar a enviar o próprio histórico como argumento da ferramenta.

Segurança

Contextos isolados são o lugar certo para ler conteúdo não confiável. Dê a eles só ferramentas de leitura, e trate a resposta como dado no contexto principal.

Greshake et al. (2023) documentaram injeção indireta: instruções escondidas numa página ou num e-mail que o modelo lê. Se essa página entra no mesmo contexto das ferramentas de efeito, o texto hostil vira ordem. Isolar a leitura não substitui o portão nas ferramentas, mas corta o canal mais comum.

Prós e contras

Prós Contras
Contexto principal pequeno e focado Custo total pode subir
Material lido não contamina o raciocínio A pergunta precisa ser autocontida
Partes com instruções e ferramentas próprias Mais spans para depurar
Leitura de conteúdo hostil longe das ferramentas de efeito A resposta curta pode perder detalhe útil

Relações

Código

As abas expõem uma ferramenta ask_codebase que responde perguntas num contexto novo, sem o histórico da revisão. Python e TypeScript zeram a lista de mensagens na mão. LangChain faz o mesmo com um create_agent que só recebe a pergunta: o histórico do revisor não entra no dicionário.

Python. Use quando a revisão roda em Python e a leitura isolada é uma função comum.

import anthropic
from pydantic import BaseModel

client = anthropic.Anthropic()


class Evidence(BaseModel):
    path: str
    lines: str


class Answer(BaseModel):
    answer: str
    evidence: list[Evidence]


READER = "Você responde uma pergunta sobre o repositório usando só as ferramentas de leitura. Seja breve e cite arquivo e linhas."


def ask_codebase(question: str, max_steps: int = 10) -> Answer:
    messages = [{"role": "user", "content": question}]  # 3. nada da revisão entra aqui
    for _ in range(max_steps):
        reply = client.messages.create(
            model="claude-haiku-4-5", max_tokens=4000, system=READER,
            tools=READ_TOOLS, messages=messages,
        )
        if reply.stop_reason != "tool_use":
            break
        messages.append({"role": "assistant", "content": reply.content})
        messages.append({"role": "user", "content": run_tools(reply)})  # 4
    messages.append({"role": "user", "content": "Responda agora no formato pedido."})
    return client.messages.parse(  # 5. só a resposta curta sai daqui
        model="claude-haiku-4-5", max_tokens=1000, system=READER,
        messages=messages, output_format=Answer,
    ).parsed_output


ASK_TOOL = {
    "name": "ask_codebase",
    "description": "Responde uma pergunta sobre código fora do diff (testes, chamadas, histórico). "
                   "A pergunta deve ser autocontida. Devolve resposta curta com arquivo e linhas.",
    "input_schema": {"type": "object", "properties": {"question": {"type": "string"}}, "required": ["question"]},
}

O que você ganhou: a revisão nunca carrega arquivos inteiros, e a leitura usa um modelo barato. O que você perdeu: cada pergunta relê o que precisa; para muitas perguntas sobre os mesmos arquivos, considere cache.

TypeScript. Use quando a revisão roda no runner do SDK e a leitura isolada é uma ferramenta tipada.

import Anthropic from "@anthropic-ai/sdk";
import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
import { z } from "zod";

const client = new Anthropic();

const READER =
  "Você responde uma pergunta sobre o repositório usando só as ferramentas de leitura. " +
  'Termine com JSON {"answer": string, "evidence": [{"path": string, "lines": string}]}.';

export const askCodebase = betaZodTool({
  name: "ask_codebase",
  description:
    "Responde uma pergunta sobre código fora do diff (testes, chamadas, histórico). " +
    "A pergunta deve ser autocontida. Devolve resposta curta com arquivo e linhas.",
  inputSchema: z.object({ question: z.string() }),
  run: async ({ question }) => {
    // 3. um runner novo = um contexto novo, sem o histórico da revisão
    const final = await client.beta.messages.toolRunner({
      model: "claude-haiku-4-5",
      max_tokens: 4000,
      system: READER,
      tools: READ_TOOLS,
      messages: [{ role: "user", content: question }],
      max_iterations: 10,
    });
    return final.content.find((b) => b.type === "text")?.text ?? "{}"; // 5
  },
});

// revisão: tools: [askCodebase]; o diff é a única coisa grande no contexto principal

O que você ganhou: o isolamento é estrutural, porque cada chamada da ferramenta cria seu próprio runner. O que você perdeu: a resposta chega como texto; valide o JSON antes de confiar.

Python + LangChain. Use quando o leitor isolado é um create_agent e a chamada dele recebe só a pergunta.

from langchain.agents import create_agent
from langchain.tools import tool
from pydantic import BaseModel


class Evidence(BaseModel):
    path: str
    lines: str


class Answer(BaseModel):
    answer: str
    evidence: list[Evidence]


# 3. este agente não recebe as mensagens da revisão
reader = create_agent(
    "anthropic:claude-haiku-4-5",
    tools=READ_TOOLS,
    system_prompt="Você responde uma pergunta sobre o repositório usando só as ferramentas de leitura. "
                  "Seja breve e cite arquivo e linhas.",
    response_format=Answer,
)


@tool
def ask_codebase(question: str) -> str:
    """Responde uma pergunta sobre código fora do diff. A pergunta deve ser autocontida."""
    out = reader.invoke(
        {"messages": [{"role": "user", "content": question}]},  # só a pergunta
        {"recursion_limit": 20},
    )
    return out["structured_response"].model_dump_json()  # 5

READ_TOOLS são as ferramentas de leitura. O revisor principal recebe ask_codebase e não recebe READ_TOOLS. As outras formas desse loop estão em Loop ReAct.

O que você ganhou: o histórico da revisão não tem onde entrar, porque a chamada não o recebe. O que você perdeu: recursion_limit conta passos, não reais.

Teste seu entendimento

Checagem +20 XP de primeiraO agente principal passa o histórico inteiro da revisão para a chamada isolada, 'para dar mais contexto'. O que isso faz com o padrão?

Checagem +20 XP de primeiraDepois do isolamento o custo total subiu, porque os contextos isolados releem os mesmos arquivos. Qual leitura está certa?

Checagem +20 XP de primeiraO subagente foi perguntado 'a apply_discount tem testes?' sem a restrição de ignorar problemas antigos fora do diff. Ele reporta um teste que falta há dois anos. Qual é o diagnóstico?

Perguntas rápidas

O que é Isolamento de Contexto?

Isolamento de Contexto (Context Isolation) é um padrão de projeto de IA para apps com LLM e agentes, do grupo Contexto e conhecimento. Rodar subtarefas em contextos separados e trazer de volta só o resultado.

Quais smells o padrão Isolamento de Contexto ajuda a curar?

Contexto Podre, Mega-Agente e Rascunho Compartilhado.

Onde Isolamento de Contexto aparece na prática?

Nos cenários reais Agente de código, Pesquisa profunda com citações e Revisor automático de PR.

Para ir além

Relações

Refatorações que chegam aqui 1
Buscar