April 22, 2026 • Version: 2026.4.9

[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 response

2. 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:

  1. Der Agent sendet `params.body`, das die ursprüngliche Benutzeraufforderung enthält, an das Modell
  2. Der Modellaufruf schlägt fehl oder es tritt ein Timeout auf (z.B. xiaomi/mimo-v2-pro)
  3. OpenClaw setzt `params.isFallbackRetry = true`
  4. OpenClaw prüft `params.sessionHasHistory = true` (Sitzung enthält vorherige Nachrichten)
  5. Die Funktion führt den Ersetzungspfad aus:
    return "Continue where you left off. The previous model attempt failed or timed out.";
  6. 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

  1. Finden Sie die betroffene Datei:
    find /path/to/openclaw -name "agent-command-*.js" -type f
  2. Sichern Sie die Originaldatei:
    cp /path/to/agent-command-*.js /path/to/agent-command-*.js.bak
  3. 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
  4. Überprüfen Sie die Änderung:
    grep -A3 "function resolveFallbackRetryPrompt" /path/to/agent-command-*.js
  5. 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 true

4. 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 -d

5. 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 accumulate

Abhilfe: Ü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:

VersionDateimusterStatus
2026.4.9agent-command-8TL7BESJ.jsAffected
2026.4.11agent-command-BUw17dbz.jsAffected

Ü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-IDBeschreibungStatus
GH-XXXXErstmeldung: Subagent verliert Aufgabenkontext bei WiederholungOffen
GH-YYYYSitzungsprotokolle zeigen Benutzernachrichten mit null Absender-MetadatenZugehö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);

Belege & Quellen

Diese Troubleshooting-Anleitung wurde automatisch von der FixClaw Intelligence Pipeline aus Community-Diskussionen synthetisiert.