Gateway
Modelli locali
I modelli locali sono fattibili. Alzano anche l'asticella per hardware, dimensione del contesto e difesa dalla prompt injection: schede piccole o quantizzate in modo aggressivo troncano il contesto e riducono la sicurezza. Questa pagina è la guida pragmatica per stack locali di fascia alta e server locali personalizzati compatibili con OpenAI. Per un onboarding con meno attrito, inizia con LM Studio o Ollama e openclaw onboard.
Per i server locali che devono avviarsi solo quando un modello selezionato ne ha bisogno, consulta Servizi di modelli locali.
Base hardware minima
Punta in alto: ≥2 Mac Studio al massimo della configurazione o un rig GPU equivalente (~$30k+) per un ciclo agente confortevole. Una singola GPU da 24 GB funziona solo per prompt più leggeri con latenza maggiore. Esegui sempre la variante più grande / full-size che puoi ospitare; checkpoint piccoli o molto quantizzati aumentano il rischio di prompt injection (vedi Sicurezza).
Scegli un backend
| Backend | Usalo quando |
|---|---|
| ds4 | DeepSeek V4 Flash locale su macOS Metal con chiamate di strumenti compatibili con OpenAI |
| LM Studio | Prima configurazione locale, loader GUI, Responses API nativa |
| LiteLLM / OAI-proxy / proxy personalizzato compatibile con OpenAI | Fai da front a un'altra API di modello e hai bisogno che OpenClaw la tratti come OpenAI |
| MLX / vLLM / SGLang | Serving self-hosted ad alta produttività con endpoint HTTP compatibile con OpenAI |
| Ollama | Flusso di lavoro CLI, libreria di modelli, servizio systemd senza interventi |
Usa Responses API (api: "openai-responses") quando il backend la supporta (LM Studio lo fa). Altrimenti usa Chat Completions (api: "openai-completions").
Consigliato: LM Studio + grande modello locale (Responses API)
Il miglior stack locale attuale. Carica un modello grande in LM Studio (per esempio una build full-size di Qwen, DeepSeek o Llama), abilita il server locale (predefinito http://127.0.0.1:1234) e usa Responses API per mantenere il ragionamento separato dal testo finale.
{ agents: { defaults: { model: { primary: "lmstudio/my-local-model" }, models: { "anthropic/claude-opus-4-6": { alias: "Opus" }, "lmstudio/my-local-model": { alias: "Local" }, }, }, }, models: { mode: "merge", providers: { lmstudio: { baseUrl: "http://127.0.0.1:1234/v1", apiKey: "lmstudio", api: "openai-responses", models: [ { id: "my-local-model", name: "Local Model", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 196608, maxTokens: 8192, }, ], }, }, },}Checklist di configurazione
- Installa LM Studio: https://lmstudio.ai
- In LM Studio, scarica la build del modello più grande disponibile (evita varianti "small"/molto quantizzate), avvia il server, conferma che
http://127.0.0.1:1234/v1/modelsla elenchi. - Sostituisci
my-local-modelcon l'ID modello effettivo mostrato in LM Studio. - Mantieni il modello caricato; il caricamento a freddo aggiunge latenza di avvio.
- Regola
contextWindow/maxTokensse la tua build di LM Studio differisce. - Per WhatsApp, resta su Responses API così viene inviato solo il testo finale.
Mantieni configurati i modelli ospitati anche quando usi quelli locali; usa models.mode: "merge" così i fallback restano disponibili.
Configurazione ibrida: primario ospitato, fallback locale
{ agents: { defaults: { model: { primary: "anthropic/claude-sonnet-4-6", fallbacks: ["lmstudio/my-local-model", "anthropic/claude-opus-4-6"], }, models: { "anthropic/claude-sonnet-4-6": { alias: "Sonnet" }, "lmstudio/my-local-model": { alias: "Local" }, "anthropic/claude-opus-4-6": { alias: "Opus" }, }, }, }, models: { mode: "merge", providers: { lmstudio: { baseUrl: "http://127.0.0.1:1234/v1", apiKey: "lmstudio", api: "openai-responses", models: [ { id: "my-local-model", name: "Local Model", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 196608, maxTokens: 8192, }, ], }, }, },}Locale prima di tutto con rete di sicurezza ospitata
Scambia l'ordine di primario e fallback; mantieni lo stesso blocco providers e models.mode: "merge" così puoi passare a Sonnet o Opus quando la macchina locale non è disponibile.
Hosting regionale / instradamento dati
- Varianti ospitate MiniMax/Kimi/GLM esistono anche su OpenRouter con endpoint vincolati a una regione (per esempio ospitati negli Stati Uniti). Scegli lì la variante regionale per mantenere il traffico nella giurisdizione scelta, continuando a usare
models.mode: "merge"per i fallback Anthropic/OpenAI. - Solo locale resta il percorso più forte per la privacy; l'instradamento regionale ospitato è la via intermedia quando hai bisogno di funzionalità del provider ma vuoi controllare il flusso dei dati.
Altri proxy locali compatibili con OpenAI
MLX (mlx_lm.server), vLLM, SGLang, LiteLLM, OAI-proxy o gateway
personalizzati funzionano se espongono un endpoint /v1/chat/completions
in stile OpenAI. Usa l'adattatore Chat Completions a meno che il backend documenti
esplicitamente il supporto di /v1/responses. Sostituisci il blocco provider sopra
con il tuo endpoint e ID modello:
{ agents: { defaults: { model: { primary: "local/my-local-model" }, }, }, models: { mode: "merge", providers: { local: { baseUrl: "http://127.0.0.1:8000/v1", apiKey: "sk-local", api: "openai-completions", timeoutSeconds: 300, models: [ { id: "my-local-model", name: "Local Model", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 120000, maxTokens: 8192, }, ], }, }, },}Se api viene omesso su un provider personalizzato con un baseUrl, OpenClaw usa per impostazione predefinita
openai-completions. Le voci di provider personalizzati/locali considerano attendibile la loro origine
baseUrl esatta configurata per richieste di modello protette, inclusi loopback, LAN, tailnet
e host DNS privati. Le richieste ad altre origini private richiedono comunque
request.allowPrivateNetwork: true; le origini metadata/link-local restano bloccate
senza opt-in esplicito. Impostalo su false per disattivare l'attendibilità dell'origine esatta.
Il valore models.providers.<id>.models[].id è locale al provider. Non
includere lì il prefisso del provider. Per esempio, un server MLX avviato con
mlx_lm.server --model mlx-community/Qwen3-30B-A3B-6bit dovrebbe usare questo
ID di catalogo e riferimento modello:
models.providers.mlx.models[].id: "mlx-community/Qwen3-30B-A3B-6bit"agents.defaults.model.primary: "mlx/mlx-community/Qwen3-30B-A3B-6bit"
Imposta input: ["text", "image"] sui modelli vision locali o proxy così gli
allegati immagine vengono inseriti nei turni agente. L'onboarding interattivo per provider
personalizzati deduce gli ID comuni dei modelli vision e chiede solo per nomi sconosciuti.
L'onboarding non interattivo usa la stessa inferenza; usa --custom-image-input
per ID vision sconosciuti o --custom-text-input quando un modello che sembra noto è
solo testo dietro il tuo endpoint.
Mantieni models.mode: "merge" così i modelli ospitati restano disponibili come fallback.
Usa models.providers.<id>.timeoutSeconds per server di modelli locali o remoti lenti
prima di aumentare agents.defaults.timeoutSeconds. Il timeout del provider
si applica solo alle richieste HTTP del modello, inclusi connessione, header, streaming del corpo
e l'interruzione totale del guarded-fetch. Se il timeout dell'agente o dell'esecuzione è più basso, aumenta
anche quel limite, perché i timeout del provider non possono estendere l'intera esecuzione agente.
Nota di comportamento per backend locali/proxy /v1:
- OpenClaw li tratta come route compatibili con OpenAI in stile proxy, non come endpoint OpenAI nativi
- la modellazione delle richieste solo per OpenAI nativo non si applica qui: niente
service_tier, nientestoreResponses, niente modellazione payload di compatibilità per ragionamento OpenAI e niente suggerimenti per prompt-cache - gli header nascosti di attribuzione OpenClaw (
originator,version,User-Agent) non vengono iniettati su questi URL proxy personalizzati
Note di compatibilità per backend compatibili con OpenAI più rigorosi:
-
Alcuni server accettano solo
messages[].contentstringa su Chat Completions, non array strutturati di parti di contenuto. Impostamodels.providers.<provider>.models[].compat.requiresStringContent: trueper quegli endpoint. -
Alcuni modelli locali emettono richieste di strumenti autonome tra parentesi quadre come testo, ad esempio
[tool_name]seguito da JSON e[END_TOOL_REQUEST]. OpenClaw promuove quelle richieste a vere chiamate di strumenti solo quando il nome corrisponde esattamente a uno strumento registrato per il turno; altrimenti il blocco viene trattato come testo non supportato ed è nascosto dalle risposte visibili all'utente. -
Se un modello emette JSON, XML o testo in stile ReAct che sembra una chiamata di strumento ma il provider non ha emesso un'invocazione strutturata, OpenClaw lo lascia come testo e registra un avviso con l'ID esecuzione, provider/modello, pattern rilevato e nome dello strumento quando disponibile. Trattalo come incompatibilità delle chiamate di strumenti del provider/modello, non come un'esecuzione di strumento completata.
-
Se gli strumenti appaiono come testo dell'assistente invece di essere eseguiti, per esempio JSON grezzo, XML, sintassi ReAct o un array
tool_callsvuoto nella risposta del provider, verifica prima che il server stia usando un template/parser chat capace di chiamate di strumenti. Per backend Chat Completions compatibili con OpenAI il cui parser funziona solo quando l'uso degli strumenti è forzato, imposta un override di richiesta per modello invece di fare affidamento sul parsing del testo:json5 { agents: { defaults: { models: { "local/my-local-model": { params: { extra_body: { tool_choice: "required", }, }, }, }, }, },}Usalo solo per modelli/sessioni in cui ogni turno normale dovrebbe chiamare uno strumento. Sovrascrive il valore proxy predefinito di OpenClaw di
tool_choice: "auto". Sostituiscilocal/my-local-modelcon il riferimento provider/modello esatto mostrato daopenclaw models list.bash openclaw config set agents.defaults.models '{"local/my-local-model":{"params":{"extra_body":{"tool_choice":"required"}}}}' --strict-json --merge -
Se un modello personalizzato compatibile con OpenAI accetta sforzi di ragionamento OpenAI oltre il profilo integrato, dichiarali nel blocco compat del modello. Aggiungere
"xhigh"qui fa sì che/think xhigh, i selettori di sessione, la validazione Gateway e la validazionellm-taskespongano il livello per quel riferimento provider/modello configurato:json5 { models: { providers: { local: { baseUrl: "http://127.0.0.1:8000/v1", apiKey: "sk-local", api: "openai-responses", models: [ { id: "gpt-5.4", name: "GPT 5.4 via local proxy", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 196608, maxTokens: 8192, compat: { supportedReasoningEfforts: ["low", "medium", "high", "xhigh"], reasoningEffortMap: { xhigh: "xhigh" }, }, }, ], }, }, },}
Backend più piccoli o più rigorosi
Se il modello si carica correttamente ma i turni completi dell'agente si comportano in modo anomalo, procedi dall'alto verso il basso: conferma prima il trasporto, poi restringi la superficie.
-
Conferma che il modello locale stesso risponda. Nessuno strumento, nessun contesto dell'agente:
bash openclaw infer model run --local --model <provider/model> --prompt "Reply with exactly: pong" --json -
Conferma il routing del Gateway. Invia solo il prompt fornito: salta trascrizione, bootstrap di AGENTS, assemblaggio del motore di contesto, strumenti e server MCP in bundle, ma esercita comunque routing del Gateway, autenticazione e selezione del provider:
bash openclaw infer model run --gateway --model <provider/model> --prompt "Reply with exactly: pong" --json -
Prova la modalità leggera. Se entrambe le sonde passano ma i turni reali dell'agente falliscono con chiamate agli strumenti malformate o prompt sovradimensionati, abilita
agents.defaults.experimental.localModelLean: true. Rimuove i tre strumenti predefiniti più pesanti (browser,cron,message) e mette per impostazione predefinita i cataloghi di strumenti più grandi dietro controlli strutturati di Ricerca strumenti, tranne per le esecuzioni che devono mantenere la semantica di consegna diretta dimessage. Consulta Funzionalità sperimentali → Modalità leggera per modelli locali per la spiegazione completa, quando usarla e come confermare che sia attiva. -
Disabilita completamente gli strumenti come ultima risorsa. Se la modalità leggera non basta, imposta
models.providers.<provider>.models[].compat.supportsTools: falseper quella voce del modello. L'agente opererà quindi senza chiamate agli strumenti su quel modello. -
Oltre questo punto, il collo di bottiglia è a monte. Se il backend continua a fallire solo su esecuzioni OpenClaw più grandi dopo la modalità leggera e
supportsTools: false, il problema rimanente è di solito la capacità del modello o del server a monte: finestra di contesto, memoria GPU, eliminazione della kv-cache o un bug del backend. A quel punto non è il livello di trasporto di OpenClaw.
Risoluzione dei problemi
- Il Gateway può raggiungere il proxy?
curl http://127.0.0.1:1234/v1/models. - Modello LM Studio scaricato? Ricaricalo; l'avvio a freddo è una causa comune di "blocco".
- Il server locale indica
terminated,ECONNRESETo chiude lo stream a metà turno? OpenClaw registra unmodel.call.error.failureKinda bassa cardinalità più lo snapshot RSS/heap del processo OpenClaw nella diagnostica. Per la pressione di memoria di LM Studio/Ollama, confronta quel timestamp con il log del server o con il log di crash / jetsam di macOS per confermare se il server del modello è stato terminato. - OpenClaw deriva le soglie di preflight della finestra di contesto dalla finestra del modello rilevata, o dalla finestra del modello senza limite quando
agents.defaults.contextTokensabbassa la finestra effettiva. Avvisa sotto il 20% con un limite minimo di 8k. I blocchi rigidi usano la soglia del 10% con un limite minimo di 4k, con limite massimo alla finestra di contesto effettiva così che metadati del modello sovradimensionati non possano rifiutare un limite utente altrimenti valido. Se incontri quel preflight, aumenta il limite di contesto del server/modello o scegli un modello più grande. - Errori di contesto? Abbassa
contextWindowo aumenta il limite del server. - Il server compatibile con OpenAI restituisce
messages[].content ... expected a string? Aggiungicompat.requiresStringContent: truea quella voce del modello. - Il server compatibile con OpenAI restituisce
validation.keyso dice che le voci dei messaggi consentono soloroleecontent? Aggiungicompat.strictMessageKeys: truea quella voce del modello. - Le chiamate dirette minuscole a
/v1/chat/completionsfunzionano, maopenclaw infer model run --localfallisce su Gemma o su un altro modello locale? Controlla prima l'URL del provider, il riferimento del modello, il marcatore di autenticazione e i log del server;model runlocale non include gli strumenti dell'agente. Semodel runlocale riesce ma i turni dell'agente più grandi falliscono, riduci la superficie degli strumenti dell'agente conlocalModelLeanocompat.supportsTools: false. - Le chiamate agli strumenti compaiono come testo JSON/XML/ReAct grezzo, oppure il provider restituisce un
array
tool_callsvuoto? Non aggiungere un proxy che converte alla cieca il testo dell'assistente in esecuzione di strumenti. Correggi prima il template/parser della chat del server. Se il modello funziona solo quando l'uso degli strumenti è forzato, aggiungi l'override per modelloparams.extra_body.tool_choice: "required"sopra e usa quella voce del modello solo per sessioni in cui è prevista una chiamata a uno strumento a ogni turno. - Sicurezza: i modelli locali saltano i filtri lato provider; mantieni gli agenti ristretti e la Compaction attiva per limitare il raggio d'impatto della prompt injection.