[Verwirft bei Modell-Fallback-Wiederholung die ursprüngliche Benutzeraufforderung] - resolveFallbackRetryPrompt Discards Original User Prompt on Model Fallback Retry
Wenn ein Modellaufruf fehlschlägt und eine Fallback-Wiederholung auslöst, ersetzt die Funktion resolveFallbackRetryPrompt() die gesamte ursprüngliche Benutzeraufforderung durch eine generische Nachricht, wodurch Agents den Aufgabenkontext verlieren.
🔍 Symptome
Beobachtbares Verhalten
Wenn ein Modellaufruf fehlschlägt oder ein Timeout auftritt und OpenClaw einen Fallback-Wiederholungsversuch auslöst, erhält der Agent nur eine generische Meldung anstelle der ursprünglichen Aufgabenanweisung. Dies manifestiert sich in zwei unterschiedlichen Weisen:
1. Sitzungsprotokoll-Beweis
Das Sitzungsprotokoll zeigt eine Benutzernachricht ohne Absender-Metadaten, die die ursprüngliche Aufgabe ersetzt:
// Session log excerpt (session ec19b29b)
Line 25: { customType: "model-snapshot", provider: "xiaomi", model: "mimo-v2-pro" }
Line 26: { role: "user", content: "Continue where you left off. The previous model attempt failed or timed out.", sender: null }
Line 27: { role: "assistant", model: "mimo-v2-pro" } // fallback retry response2. Kontextverlust in Subagent-Szenarien
Wenn ein Subagent mit einer spezifischen Aufgabenanweisung erstellt wird (z.B. [Subagent Task]: RECORD時系列整列), wird die ursprüngliche Aufgabe vollständig verworfen:
// Original prompt sent to subagent
"[Subagent Task]: RECORD時系列整列"
// Prompt received after fallback retry
"Continue where you left off. The previous model attempt failed or timed out."Der Agent muss die Aufgabe allein aus dem Sitzungsverlauf ableiten, was folgende Risiken birgt:
- Ungültige Aktionsauswahl basierend auf unvollständigem Kontext
- Unfähigkeit, die beabsichtigte Aufgabe abzuschließen
- Mögliche Generierung unbeabsichtigter Ausgaben
3. Diagnoseindikatoren
Das Problem kann durch Untersuchung des Verhaltens der Funktion resolveFallbackRetryPrompt() identifiziert werden:
// Current implementation (dist/agent-command-*.js)
function resolveFallbackRetryPrompt(params) {
if (!params.isFallbackRetry) return params.body;
if (!params.sessionHasHistory) return params.body;
return "Continue where you left off. The previous model attempt failed or timed out.";
}🧠 Ursache
Technische Analyse
Die Grundursache liegt in der bedingten Logik von resolveFallbackRetryPrompt(), die eine Ersetzungsstrategie mit Frührückgabe verwendet anstatt einer Verkettungsstrategie.
Fehlersequenz:
- Der Agent sendet `params.body`, das die ursprüngliche Benutzeraufforderung enthält, an das Modell
- Der Modellaufruf schlägt fehl oder es tritt ein Timeout auf (z.B. xiaomi/mimo-v2-pro)
- OpenClaw setzt `params.isFallbackRetry = true`
- OpenClaw prüft `params.sessionHasHistory = true` (Sitzung enthält vorherige Nachrichten)
- Die Funktion führt den Ersetzungspfad aus:
return "Continue where you left off. The previous model attempt failed or timed out."; - Das ursprüngliche `params.body` wird vollständig verworfen
Architektonische Inkonsistenz:
Die Funktion vermischt zwei unterschiedliche Anforderungen:
- Anforderung A: Das Modell darüber informieren, dass eine Wiederholung aufgetreten ist
- Anforderung B: Die ursprüngliche Aufgabenanweisung bewahren
Die aktuelle Implementierung erfüllt Anforderung A, während sie Anforderung B vollständig verletzt.
Code-Pfad-Analyse:
javascript // In runAgentAttempt(): const effectivePrompt = resolveFallbackRetryPrompt({ body: params.body, isFallbackRetry: params.isFallbackRetry, sessionHasHistory: params.sessionHasHistory });
Wenn isFallbackRetry true ist und sessionHasHistory true ist, gibt die Funktion einen festen String zurück, anstatt ihn mit params.body zu kombinieren.
Auswirkungskette:
Original Prompt (params.body)
↓
Model Call Fails
↓
isFallbackRetry = true
↓
sessionHasHistory = true
↓
resolveFallbackRetryPrompt() returns FIXED_STRING
↓
effectivePrompt = FIXED_STRING ← Original task LOST
↓
Fallback model receives no task context🛠️ Schritt-für-Schritt-Lösung
Lösungsstrategie
Ändern Sie resolveFallbackRetryPrompt(), um die Wiederholungsbenachrichtigung voranzustellen anstatt sie zu ersetzen.
Codeänderung
Datei: dist/agent-command-*.js (variiert je nach Version)
Vorher:
function resolveFallbackRetryPrompt(params) {
if (!params.isFallbackRetry) return params.body;
if (!params.sessionHasHistory) return params.body;
return "Continue where you left off. The previous model attempt failed or timed out.";
}Nachher:
function resolveFallbackRetryPrompt(params) {
if (!params.isFallbackRetry) return params.body;
if (!params.sessionHasHistory) return params.body;
return "[System: Previous model attempt failed or timed out. Continuing from where you left off.]\n\n" + params.body;
}Alternative Implementierung (Ausführlicher)
Für Umgebungen, die eine klarere Trennung erfordern:
function resolveFallbackRetryPrompt(params) {
if (!params.isFallbackRetry) return params.body;
if (!params.sessionHasHistory) return params.body;
const retryNotice = "[System: Previous model attempt failed or timed out. Continuing from where you left off.]\n\n";
const originalPrompt = params.body;
return retryNotice + originalPrompt;
}Bereitstellungsschritte
- Finden Sie die betroffene Datei:
find /path/to/openclaw -name "agent-command-*.js" -type f - Sichern Sie die Originaldatei:
cp /path/to/agent-command-*.js /path/to/agent-command-*.js.bak - Wenden Sie die Korrektur mit sed an:
sed -i 's/return "Continue where you left off. The previous model attempt failed or timed out.";/return "[System: Previous model attempt failed or timed out. Continuing from where you left off.]\\n\\n" + params.body;/g' /path/to/agent-command-*.js - Überprüfen Sie die Änderung:
grep -A3 "function resolveFallbackRetryPrompt" /path/to/agent-command-*.js - Starten Sie den OpenClaw-Dienst neu:
sudo systemctl restart openclaw
🧪 Verifizierung
Verifizierungsmethodik
Um die Korrektur zu bestätigen, simulieren Sie einen Modellfehler und überprüfen Sie, ob die Fallback-Wiederholungsaufforderung die ursprüngliche Aufgabe enthält.
Testverfahren
1. Aktivieren Sie das Debug-Logging:
export OPENCLAW_LOG_LEVEL=debug
export DEBUG=openclaw:agent:*2. Lösen Sie ein Fallback-Szenario aus:
Erstellen Sie eine Test-Agent-Konfiguration mit einem absichtlich fehlschlagenden Modell:
// test-fallback-prompt.json
{
"agent": {
"model": "intentionally-invalid-model-for-testing",
"fallbackModel": "gpt-4o-mini",
"prompt": "[Test Task]: Identify the color of the sky"
}
}3. Führen Sie den Agenten aus:
openclaw run --config test-fallback-prompt.json --session test-fallback-$(date +%s)4. Untersuchen Sie das Sitzungsprotokoll:
openclaw session log --session-id <session-id> --format json | jq '.messages[] | select(.role == "user") | {content, sender, metadata}'5. Überprüfen Sie die erwartete Ausgabe:
Vor der Korrektur zeigt die Ausgabe:
{
"content": "Continue where you left off. The previous model attempt failed or timed out.",
"sender": null,
"metadata": {}
}Nach der Korrektur sollte die Ausgabe zeigen:
{
"content": "[System: Previous model attempt failed or timed out. Continuing from where you left off.]\n\n[Test Task]: Identify the color of the sky",
"sender": "system",
"metadata": {
"isFallbackRetry": true
}
}Automatisiertes Verifizierungsskript
#!/bin/bash
SESSION_ID=$(openclaw session list --limit 1 --format json | jq -r '.[0].id')
FALLBACK_USER_MSG=$(openclaw session log --session-id "$SESSION_ID" --format json | jq -r '.messages[] | select(.role == "user" and .sender == null) | .content')
if echo "$FALLBACK_USER_MSG" | grep -q "\[System: Previous model attempt"; then
if echo "$FALLBACK_USER_MSG" | grep -q "\[Test Task\]"; then
echo "✅ VERIFIED: Original prompt preserved in fallback retry"
exit 0
else
echo "❌ FAILED: System message present but original prompt missing"
exit 1
fi
else
echo "❌ FAILED: Generic message still being used (fix not applied)"
exit 1
fi⚠️ Häufige Fehler
Grenzfälle und umgebungsspezifische Fallen
1. Leerer Prompt-Body (params.body ist ein leerer String)
Wenn params.body ein leerer String ist, erzeugt die korrigierte Implementierung einen Prompt mit nur der Systembenachrichtigung:
// Result when params.body = ""
"[System: Previous model attempt failed...]\n\n"
// ← Empty original task (may be valid if session history is sufficient)Abhilfe: Überprüfen Sie, ob params.body nicht leer ist, bevor Sie die Verkettung durchführen:
function resolveFallbackRetryPrompt(params) {
if (!params.isFallbackRetry) return params.body;
if (!params.sessionHasHistory) return params.body;
const retryNotice = "[System: Previous model attempt failed or timed out. Continuing from where you left off.]\n\n";
return params.body ? retryNotice + params.body : retryNotice.trim();
}2. Sehr lange ursprüngliche Prompts
Lange Prompts, die mit der Wiederholungsbenachrichtigung verkettet werden, können die Modellkontextlimits überschreiten.
- Überwachen Sie die Token-Nutzung, wenn ursprüngliche Prompts sich den Modelllimits nähern
- Erwägen Sie, `params.body` abzuschneiden, wenn es einen Schwellenwert überschreitet (z.B. 4000 Token)
3. Nicht-ASCII-Zeichen im ursprünglichen Prompt
Japanische Zeichen (wie im gemeldeten Problem mit RECORD時系列整列) müssen korrekt beibehalten werden:
// Verify encoding is maintained
const testPrompt = "[Subagent Task]: RECORD時系列整列";
const fixed = "[System: ...]\n\n" + testPrompt;
console.log(fixed.includes("RECORD時系列整列")); // Must be true4. Docker-Container-Caching
Wenn OpenClaw in Docker läuft, können zwischengespeicherte JavaScript-Dateien persistieren:
# Rebuild container to ensure new code is deployed
docker-compose down
docker-compose build --no-cache openclaw
docker-compose up -d5. Mehrfache aufeinanderfolgende Fallback-Wiederholungen
Wenn ein Modell mehrmals hintereinander fehlschlägt, könnte jede Wiederholung zusätzliche Systembenachrichtigungen voranstellen:
// After 3 retries, prompt becomes:
"[System: ...]\n\n[System: ...]\n\n[System: ...]\n\n[Test Task]: ..."
// ← Duplicate notices accumulateAbhilfe: Überprüfen Sie, ob der ursprüngliche Prompt bereits die Wiederholungsbenachrichtigung enthält, bevor Sie voranstellen:
function resolveFallbackRetryPrompt(params) {
if (!params.isFallbackRetry) return params.body;
if (!params.sessionHasHistory) return params.body;
if (params.body.includes("[System: Previous model attempt")) return params.body;
return "[System: Previous model attempt failed...]\n\n" + params.body;
}6. Versionskompatibilität
Die Funktionssignatur oder der Aufrufort kann sich zwischen Versionen ändern:
| Version | Dateimuster | Status |
|---|---|---|
| 2026.4.9 | agent-command-8TL7BESJ.js | Affected |
| 2026.4.11 | agent-command-BUw17dbz.js | Affected |
Überprüfen Sie immer den genauen Funktionsstandort und die Parameternamen in Ihrer bereitgestellten Version.
🔗 Zugehörige Fehler
Kontextuell verbundene Probleme
Die folgenden Fehler und historischen Probleme hängen mit dem Fallback-Wiederholungs-Prompt-Verhalten zusammen:
1. Modell-Timeout-Fehler
- E_TIMEOUT: Modellaufruf hat das Zeitlimit überschritten
- E_MODEL_UNAVAILABLE: Modell-Endpunkt nicht erreichbar
- E_RATE_LIMIT: API-Ratenlimit während Fallback-Versuch überschritten
Diese Fehler lösen das isFallbackRetry-Flag aus, das den problematischen Codepfad aktiviert.
2. Kontextfenster-Fehler
- E_CONTEXT_LENGTH: Kombinierter Prompt + Verlauf überschreitet Modellkontextlimit
- Kann nach der Korrektur auftreten, wenn Wiederholungsbenachrichtigung + ursprünglicher Prompt + Verlauf Limits überschreiten
3. Historische Probleme
| Problem-ID | Beschreibung | Status |
|---|---|---|
| GH-XXXX | Erstmeldung: Subagent verliert Aufgabenkontext bei Wiederholung | Offen |
| GH-YYYY | Sitzungsprotokolle zeigen Benutzernachrichten mit null Absender-Metadaten | Zugehörig |
4. Zugehörige Konfigurationsparameter
// These parameters control the fallback behavior
interface FallbackConfig {
enabled: boolean; // Enable/disable fallback retry
maxRetries: number; // Maximum retry attempts
retryDelay: number; // Delay between retries (ms)
retryModels: string[]; // List of fallback models to try
preserveOriginalPrompt: boolean; // NEW: Flag to preserve original prompt
}5. Ähnliche Muster in der Codebasis
Andere Funktionen, die ähnliche Ersetzungs-vs-Verkettungs-Probleme aufweisen könnten:
- `resolveSystemPrompt()` - Kann Systemanweisungen überschreiben
- `injectContextSummary()` - Könnte Kontext ersetzen anstatt anzuhängen
- `formatHistoryForModel()` - Könnte Verlauf abschneiden anstatt zusammenzufassen
6. Monitoring-Empfehlungen
Implementieren Sie Telemetrie für Fallback-Wiederholungsszenarien:
// Suggested metrics to track
metrics.increment('openclaw.fallback.retry.count');
metrics.gauge('openclaw.fallback.prompt.length', effectivePrompt.length);
metrics.histogram('openclaw.fallback.prompt.original_length', params.body.length);