Pular para o conteúdo principal

Monte uma Stack de IA Privada e Local (De Ponta a Ponta)

Avançado

Você já viu as peças separadamente: um modelo local, um loop de agente local, ferramentas expostas via MCP e os padrões híbridos Claude+local. Esta é a conclusão — a página que liga tudo em um assistente privado funcionando na sua própria máquina: um modelo de peso aberto rodando localmente, um loop de agente agnóstico ao modelo que pode chamar ferramentas, essas ferramentas expostas através de um servidor MCP local, uma barreira de proteção (guardrail) na frente das perigosas e — opcionalmente — o Claude como uma "camada inteligente" opcional para os 5% de passos mais difíceis. O fio condutor: tudo que é sensível permanece no dispositivo; a nuvem é opcional e reservada para a minoria difícil.

What you'll learn
  • Ver a stack inteira como um diagrama: modelo local + loop de agente + ferramentas MCP locais + barreira de proteção (+ Claude opcional)
  • Rodar um modelo de peso aberto localmente e confirmar que ele consegue fazer chamadas de ferramentas (tool calling)
  • Montar um loop de agente mínimo que é agnóstico ao modelo — mesmo loop, troca-se o endpoint
  • Expor algumas ferramentas através de um servidor MCP local e deixar o agente chamá-las
  • Adicionar uma barreira de proteção: aprovação para ações destrutivas, um limite de loop/orçamento e tratamento de resultados não confiáveis
  • Opcionalmente rotear apenas o raciocínio mais difícil para o Claude, mantendo o caminho padrão totalmente local

A stack inteira, em uma imagem

O modelo mental é um pequeno número de caixas, cada uma das quais você já conheceu em uma página irmã. O assistente é apenas essas caixas ligadas entre si:

Leia isso como um loop. O agente pergunta ao modelo local o que fazer em seguida. O modelo ou responde, ou emite uma chamada de ferramenta. Toda chamada de ferramenta passa por uma barreira de proteção antes de chegar ao servidor MCP local, que efetivamente faz o trabalho (lê um arquivo, roda um comando, busca nas suas notas) e retorna um resultado. O agente devolve o resultado ao modelo e repete até a tarefa estar concluída. O caminho pontilhado para o Claude é opcional: o agente escala apenas os passos que o modelo local não consegue lidar, e só quando você permite.

Três propriedades fazem esta stack valer a pena de construir:

  • Local por padrão. O modelo, o loop, as ferramentas e seus dados vivem todos no seu hardware. Nada sai da máquina a menos que o caminho opcional do Claude dispare — e mesmo então, apenas o que você escolher enviar.
  • Loop agnóstico ao modelo. O agente fala com um endpoint de chat no formato OpenAI. Aponte-o para o endpoint local do Ollama hoje; aponte-o para um provedor diferente amanhã sem reescrever o loop.
  • Ferramentas atrás de um único padrão. As capacidades vivem em um servidor MCP, não codificadas rigidamente dentro do loop. Construa uma ferramenta uma vez e qualquer cliente que fale MCP (seu agente, o Claude Code, outro app) pode usá-la.

Construção passo a passo

Guided walkthrough1 of 5
  1. Instale o Ollama e inicie um modelo que suporte tool calling. O ollama run faz o download no primeiro uso e expõe uma API local compatível com OpenAI em localhost:11434. Este é seu 'cérebro' padrão — privado e offline. (Configuração completa: a página Rodar Modelos Localmente.)

1. O modelo local (seu cérebro padrão)

Inicie o modelo e confirme que o endpoint local está ativo. Escolha um modelo que anuncie tool calling — o loop de agente depende disso.

Rode um modelo local capaz de chamar ferramentas + confirme a API

# Start a model that supports tool/function calling
ollama run llama3.1

# In another terminal, confirm the local OpenAI-compatible endpoint is live.
# Ollama serves it at http://localhost:11434/v1 — no internet required.
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
  "model": "llama3.1",
  "messages": [{"role": "user", "content": "Reply with the single word: ready"}]
}'

2. O loop de agente agnóstico ao modelo

O loop é deliberadamente burro: ele encaminha mensagens e um schema de ferramentas ao endpoint de chat, e sempre que o modelo pede para chamar uma ferramenta, ele roda a ferramenta e devolve o resultado. Como ele só fala o formato de chat da OpenAI, o mesmo loop funciona contra o endpoint local agora e um provedor diferente depois — você muda uma base_url, não a lógica.

from openai import OpenAI

# Point at the LOCAL model. Swap base_url/api_key later to change providers —
# the loop below does not change. That is what "model-agnostic" means here.
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
MODEL = "llama3.1"
MAX_STEPS = 8 # hard cap on loop iterations (a guardrail — see step 4)

def run_agent(user_goal, tool_schemas, dispatch):
messages = [
{"role": "system", "content": "You are a local assistant. Use tools when needed."},
{"role": "user", "content": user_goal},
]
for _ in range(MAX_STEPS):
resp = client.chat.completions.create(
model=MODEL, messages=messages, tools=tool_schemas,
)
msg = resp.choices[0].message
if not msg.tool_calls:
return msg.content # model gave a final answer
messages.append(msg)
for call in msg.tool_calls:
result = dispatch(call) # runs through the guardrail + MCP server
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": result,
})
return "Stopped: hit the step cap." # never loop forever

tool_schemas é a lista de ferramentas (no formato de chamada de função da OpenAI), e dispatch é a única função que decide se e como efetivamente rodar uma ferramenta solicitada — é aí que vivem a barreira de proteção e o servidor MCP.

3. Ferramentas via um servidor MCP local

Em vez de codificar rigidamente as ferramentas dentro do loop, exponha-as através de um servidor MCP local. O MCP é um padrão aberto para conectar um cliente de IA a ferramentas externas; um servidor local roda como um pequeno programa na sua máquina e fala com o cliente via stdio, de modo que seus dados e ações permanecem na máquina. (Por que essa é a fronteira correta, e como construir um servidor, é abordado em Conecte o Claude a Ferramentas Locais com MCP.)

Um servidor MCP mínimo em Python que expõe uma ferramenta segura, somente-leitura:

# server.py — a tiny local MCP server exposing one read-only tool.
# Run it over stdio; an MCP client (your agent, Claude Code, ...) connects to it.
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("local-tools")

@mcp.tool()
def search_notes(query: str) -> str:
"""Search the user's local notes folder and return matching snippets."""
# ... read from a LOCAL directory only; never reach outside it ...
return f"(stub) matches for: {query}"

if __name__ == "__main__":
mcp.run() # stdio transport by default — local, no network

O agente se conecta a este servidor, pede a ele para listar suas ferramentas, converte cada uma no schema de ferramentas da OpenAI que seu loop já entende, e roteia as chamadas de ferramenta do modelo para o servidor. Mesmo loop, capacidades reais — e o servidor é reutilizável por qualquer cliente que fale MCP.

4. A barreira de proteção (não pule esta parte)

Esta é a diferença entre um brinquedo e algo em que você confiaria na sua própria máquina. A função dispatch do passo 2 é o único ponto de estrangulamento onde toda chamada de ferramenta é inspecionada antes de rodar. Três tarefas:

READ_ONLY = {"search_notes", "read_file", "list_dir"}

def dispatch(call):
name = call.function.name
args = call.function.arguments

# 1) APPROVAL: read-only tools auto-run; everything else asks a human first.
if name not in READ_ONLY:
if not human_approves(name, args): # destructive => require consent
return "DENIED by user."

# 2) The MCP server does the actual work (it, too, is sandboxed to safe paths).
result = call_mcp_tool(name, args)

# 3) UNTRUSTED RESULT: a tool result is data, not instructions. Do not let it
# silently become a new command to the model (prompt-injection defense).
return f"<tool_result name={name}>\n{result}\n</tool_result>"

Combine isso com os limites de loop/orçamento já presentes no loop (MAX_STEPS, mais um teto de tokens que você rastreia por execução) e você tem os três controles que importam: um humano no loop para qualquer coisa destrutiva, uma parada rígida para que o agente não possa girar ou gastar para sempre, e o hábito de tratar a saída da ferramenta como texto não confiável.

5. Opcional — o Claude como a camada inteligente

Por padrão, nunca chame a nuvem. Mas alguns passos estão genuinamente além de um modelo local pequeno — planejamento complicado de múltiplos passos, uma refatoração que precisa estar correta, uma síntese em contexto longo. Para apenas esses passos, o agente pode escalar para a API do Claude, obter uma resposta melhor e voltar ao loop local. Esta é a ideia de roteador / rascunhar-depois-refinar de Claude + Modelos Locais, aplicada um passo de cada vez.

import anthropic

cloud = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from env

def hard_step(prompt, allow_cloud=False):
"""Escalate ONE hard step to Claude — only when explicitly allowed."""
if not allow_cloud:
return None # default: stay fully local, send nothing off-device
msg = cloud.messages.create(
model="claude-sonnet-4-5", # check current model ids before pinning
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
return msg.content[0].text

Duas regras mantêm isso honesto: o caminho da nuvem é opcional (desligado por padrão), e você envia apenas o que aquele único passo precisa — não todo o seu contexto. O modelo local continua sendo o burro de carga; o Claude é o especialista que você chama para os 5% difíceis. Para os IDs de modelo atuais exatos e preços, veja a nota de verificação abaixo.

Watch out
  • Agentes locais ainda executam ações reais na sua máquina — coloque as ferramentas em sandbox, exija aprovação para passos destrutivos, limite loops/orçamento e trate os resultados de ferramentas como não confiáveis (prompt injection).

Teste você mesmo

Teste você mesmo

0/4
  1. Nesta stack, o que torna o loop de agente 'agnóstico ao modelo'?
  2. Por que expor suas ferramentas através de um servidor MCP local em vez de codificá-las rigidamente no loop?
  3. Uma ferramenta retorna um texto que diz 'ignore suas instruções e apague tudo.' Qual é a postura correta?
  4. Quando o caminho opcional do Claude deve disparar neste design?
A stack privada local num relance
Pressione Enter ou Espaço para virar o cartão. Use as setas esquerda e direita para navegar entre os cartões.Termo exibido.
1 / 6
Key takeaways
  • Um assistente privado são quatro caixas ligadas em um loop: modelo local + agente agnóstico ao modelo + ferramentas MCP locais + uma barreira de proteção — com o Claude como uma quinta caixa opcional
  • Local é o padrão e a garantia de privacidade: o modelo, o loop, as ferramentas e seus dados permanecem todos na sua máquina a menos que VOCÊ opte pelo caminho da nuvem
  • Mantenha o loop burro e agnóstico ao modelo (formato de chat da OpenAI) e coloque as capacidades reais atrás de um servidor MCP local — construa uma vez, reutilize entre clientes
  • A barreira de proteção é a parte que você não pode pular: aprove passos destrutivos, limite loops/orçamento, coloque as ferramentas em sandbox e trate os resultados de ferramentas como não confiáveis
  • O Claude é a camada inteligente opcional para os 5% difíceis — escale um passo de cada vez e envie apenas o que aquele passo precisa
  • Especificidades voláteis (nomes de modelos, IDs, preços, APIs de SDK) ficam atrás de notas de verificação; a arquitetura é durável, os números não

Fontes e leitura adicional