Einen privaten lokalen KI-Stack aufbauen (Ende-zu-Ende)
Du hast die einzelnen Bausteine bereits getrennt gesehen: ein lokales Modell, eine lokale Agent-Schleife, über MCP bereitgestellte Tools und die Claude+lokal-Hybridmuster. Dies ist der krönende Abschluss — die Seite, die alles zu einem funktionierenden privaten Assistenten auf deinem eigenen Rechner verdrahtet: ein lokal laufendes Open-Weight-Modell, eine modellagnostische Agent-Schleife, die Tools aufrufen kann, diese Tools bereitgestellt über einen lokalen MCP-Server, ein Schutzmechanismus vor den gefährlichen Tools und — optional — Claude als opt-in-„intelligente Schicht" für die schwierigsten 5 % der Schritte. Der rote Faden: Alles Sensible bleibt auf dem Gerät; die Cloud ist optional und der schwierigen Minderheit vorbehalten.
- Den gesamten Stack als ein Diagramm sehen: lokales Modell + Agent-Schleife + lokale MCP-Tools + Schutzmechanismus (+ optional Claude)
- Ein Open-Weight-Modell lokal ausführen und bestätigen, dass es Tool-Aufrufe beherrscht
- Eine minimale Agent-Schleife aufsetzen, die modellagnostisch ist — dieselbe Schleife, nur der Endpunkt wird getauscht
- Ein paar Tools über einen lokalen MCP-Server bereitstellen und den Agenten sie aufrufen lassen
- Einen Schutzmechanismus hinzufügen: Freigabe für destruktive Aktionen, eine Schleifen-/Budget-Obergrenze und Behandlung nicht vertrauenswürdiger Ergebnisse
- Optional nur das schwierigste Reasoning an Claude weiterleiten, während der Standardpfad vollständig lokal bleibt
Der gesamte Stack in einem Bild
Das mentale Modell besteht aus einer kleinen Zahl von Boxen, von denen du jede bereits auf einer Schwesterseite kennengelernt hast. Der Assistent ist einfach diese Boxen, miteinander verdrahtet:
Lies es als eine Schleife. Der Agent fragt das lokale Modell, was als Nächstes zu tun ist. Das Modell antwortet entweder oder gibt einen Tool-Aufruf aus. Jeder Tool-Aufruf durchläuft einen Schutzmechanismus, bevor er den lokalen MCP-Server erreicht, der die eigentliche Arbeit erledigt (eine Datei liest, einen Befehl ausführt, deine Notizen durchsucht) und ein Ergebnis zurückgibt. Der Agent gibt das Ergebnis an das Modell zurück und wiederholt das Ganze, bis die Aufgabe erledigt ist. Der gestrichelte Pfad zu Claude ist opt-in: Der Agent eskaliert nur die Schritte, die das lokale Modell nicht bewältigen kann, und nur, wenn du es erlaubst.
Drei Eigenschaften machen diesen Stack bauwürdig:
- Lokal als Standard. Das Modell, die Schleife, die Tools und deine Daten liegen alle auf deiner Hardware. Nichts verlässt die Box, es sei denn, der optionale Claude-Pfad wird ausgelöst — und selbst dann nur das, was du zu senden wählst.
- Modellagnostische Schleife. Der Agent spricht mit einem Chat-Endpunkt im OpenAI-Format. Richte ihn heute auf den lokalen Endpunkt von Ollama; richte ihn morgen auf einen anderen Anbieter, ohne die Schleife neu zu schreiben.
- Tools hinter einem Standard. Fähigkeiten liegen in einem MCP-Server, nicht fest in der Schleife codiert. Baue ein Tool einmal und jeder MCP-fähige Client (dein Agent, Claude Code, eine andere App) kann es nutzen.
Schritt-für-Schritt-Aufbau
- Installiere Ollama und starte ein Modell, das Tool-Aufrufe unterstützt. ollama run lädt beim ersten Gebrauch herunter und stellt eine lokale OpenAI-kompatible API unter localhost:11434 bereit. Das ist dein standardmäßiges ‚Gehirn' — privat und offline. (Vollständige Einrichtung: die Seite Modelle lokal ausführen.)
- Schreibe eine winzige Schleife: Sende Nachrichten + ein Tool-Schema an den Chat-Endpunkt, lies die Antwort, führe enthaltene tool_calls aus, hänge die Ergebnisse an und wiederhole, bis das Modell eine endgültige Antwort liefert. Die Schleife weiß nichts darüber, mit welchem Modell sie spricht — nur über das OpenAI-Chat-Format.
- Lege deine echten Fähigkeiten (eine Datei lesen, einen Befehl ausführen, Notizen durchsuchen) in einen lokalen MCP-Server über stdio, statt sie fest zu codieren. Der Agent listet die Tools des Servers auf, bildet sie in das Tool-Schema des Modells ab und ruft sie bei Bedarf auf. Einmal bauen, über Clients hinweg wiederverwenden.
- Bevor irgendein Tool läuft, sichere es ab: Read-only-Tools automatisch erlauben, für destruktive (run_shell, write_file, delete) ausdrückliche Freigabe verlangen, die Zahl der Schleifendurchläufe und Gesamttokens begrenzen und jedes Tool-Ergebnis als nicht vertrauenswürdige Eingabe behandeln, die versuchen könnte, das Modell zu steuern.
- Behalte den lokalen Pfad als Standard. Wenn ein Schritt wirklich schwierig ist — kniffliges mehrstufiges Reasoning, ein Plan, den das lokale Modell immer wieder vermasselt — lass den Agenten genau diesen Schritt an die Claude API eskalieren und kehre dann zur lokalen Schleife zurück. Das ist die Router-/Entwurf-dann-Verfeinern-Idee von der Hybrid-Seite, angewandt auf jeweils einen Schritt.
1. Das lokale Modell (dein Standard-Gehirn)
Starte das Modell und bestätige, dass der lokale Endpunkt läuft. Wähle ein Modell, das Tool-Aufrufe bewirbt — die Agent-Schleife hängt davon ab.
Ein tool-fähiges lokales Modell ausführen + die API bestätigen
# 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. Die modellagnostische Agent-Schleife
Die Schleife ist bewusst dumm: Sie leitet Nachrichten und ein Tool-Schema an den Chat-Endpunkt weiter, und wann immer das Modell darum bittet, ein Tool aufzurufen, führt sie das Tool aus und gibt das Ergebnis zurück. Da sie nur das OpenAI-Chat-Format spricht, funktioniert dieselbe Schleife heute gegen den lokalen Endpunkt und später gegen einen anderen Anbieter — du änderst eine base_url, nicht die Logik.
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 ist die Liste der Tools (im OpenAI-Funktionsaufruf-Format) und dispatch ist die eine Funktion, die entscheidet, ob und wie ein angefordertes Tool tatsächlich ausgeführt wird — dort leben der Schutzmechanismus und der MCP-Server.
3. Tools über einen lokalen MCP-Server
Statt Tools fest in der Schleife zu codieren, stelle sie über einen lokalen MCP-Server bereit. MCP ist ein offener Standard, um einen KI-Client mit externen Tools zu verbinden; ein lokaler Server läuft als kleines Programm auf deinem Rechner und spricht über stdio mit dem Client, sodass deine Daten und Aktionen auf der Box bleiben. (Warum dies die richtige Grenze ist und wie man einen Server baut, wird unter Claude über MCP mit lokalen Tools verbinden behandelt.)
Ein minimaler Python-MCP-Server, der ein sicheres, schreibgeschütztes Tool bereitstellt:
# 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
Der Agent verbindet sich mit diesem Server, bittet ihn, seine Tools aufzulisten, konvertiert jedes in das OpenAI-Tool-Schema, das deine Schleife bereits versteht, und leitet die Tool-Aufrufe des Modells an den Server weiter. Dieselbe Schleife, echte Fähigkeiten — und der Server ist von jedem MCP-fähigen Client wiederverwendbar.
4. Der Schutzmechanismus (überspringe das nicht)
Das ist der Unterschied zwischen einem Spielzeug und etwas, dem du auf deinem eigenen Rechner vertrauen würdest. Die dispatch-Funktion aus Schritt 2 ist der einzige Engpass, an dem jeder Tool-Aufruf vor seiner Ausführung geprüft wird. Drei Aufgaben:
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>"
Kombiniere das mit den Schleifen-/Budget-Obergrenzen, die bereits in der Schleife stecken (MAX_STEPS, plus eine Token-Obergrenze, die du pro Lauf verfolgst), und du hast die drei Kontrollen, die zählen: ein Mensch in der Schleife für alles Destruktive, ein harter Stopp, damit der Agent nicht ewig kreisen oder ausgeben kann, und die Gewohnheit, Tool-Ausgaben als nicht vertrauenswürdigen Text zu behandeln.
5. Optional — Claude als intelligente Schicht
Standardmäßig rufst du nie die Cloud auf. Aber einige Schritte gehen wirklich über ein kleines lokales Modell hinaus — verzwicktes mehrstufiges Planen, ein Refactoring, das korrekt sein muss, eine Synthese über langen Kontext. Nur für diese Schritte kann der Agent an die Claude API eskalieren, eine bessere Antwort erhalten und in die lokale Schleife zurückfallen. Das ist die Router-/Entwurf-dann-Verfeinern-Idee aus Claude + lokale Modelle, angewandt auf jeweils einen Schritt.
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
Zwei Regeln halten das ehrlich: Der Cloud-Pfad ist opt-in (standardmäßig aus) und du sendest nur das, was dieser einzelne Schritt braucht — nicht deinen gesamten Kontext. Das lokale Modell bleibt das Arbeitspferd; Claude ist der Spezialist, den du für die schwierigen 5 % rufst. Die genauen aktuellen Modell-IDs und Preise findest du in der Verifizierungsnotiz unten.
- Lokale Agenten führen immer noch echte Aktionen auf deinem Rechner aus — sandboxe Tools, verlange Freigabe für destruktive Schritte, begrenze Schleifen/Budget und behandle Tool-Ergebnisse als nicht vertrauenswürdig (Prompt-Injection).
Überprüfe dich selbst
Überprüfe dich selbst
0/4- Ein privater Assistent besteht aus vier Boxen, die zu einer Schleife verdrahtet sind: lokales Modell + modellagnostischer Agent + lokale MCP-Tools + ein Schutzmechanismus — mit Claude als optionaler fünfter Box
- Lokal ist der Standard und die Datenschutz-Garantie: Das Modell, die Schleife, die Tools und deine Daten bleiben alle auf deinem Rechner, es sei denn, DU entscheidest dich für den Cloud-Pfad
- Halte die Schleife dumm und modellagnostisch (OpenAI-Chat-Format) und lege echte Fähigkeiten hinter einen lokalen MCP-Server — einmal bauen, über Clients hinweg wiederverwenden
- Der Schutzmechanismus ist der Teil, den du nicht überspringen kannst: destruktive Schritte freigeben, Schleifen/Budget begrenzen, Tools sandboxen und Tool-Ergebnisse als nicht vertrauenswürdig behandeln
- Claude ist die opt-in-intelligente Schicht für die schwierigen 5 % — eskaliere jeweils einen Schritt und sende nur das, was dieser Schritt braucht
- Flüchtige Details (Modellnamen, IDs, Preise, SDK-APIs) stehen hinter Verifizierungsnotizen; die Architektur ist beständig, die Zahlen sind es nicht
Quellen & weiterführende Literatur
- Ollama — OpenAI-kompatible API (localhost:11434, tools-Parameter)
- Ollama — Ankündigung der Tool-Unterstützung
- Ollama-Modellbibliothek (aktuelle tool-fähige Modelle)
- Model Context Protocol — Einführung
- Model Context Protocol — offizielle SDKs (Python, TypeScript)
- MCP Python SDK (GitHub)
- MCP TypeScript SDK (GitHub)
- Anthropic — Claude-Modelle & Preise