Troubleshooting: OpenClaw Agent Forgetting Custom Instructions
Troubleshooting: OpenClaw Agent Forgetting Custom Instructions

Look, I've been there. You spend an hour carefully writing out custom instructions for your OpenClaw agent — telling it exactly how to behave, what tone to use, which data sources to prioritize, how to format its responses — and it works beautifully for about fifteen minutes. Then, somewhere around the twentieth interaction, your agent starts acting like it's never seen those instructions in its life.
It greets users wrong. It ignores the formatting rules you painstakingly laid out. It forgets that it's supposed to check the inventory database before recommending products. It basically becomes a blank slate with amnesia, and you're left wondering if you imagined the whole configuration process.
You didn't imagine it. This is one of the most common issues people run into when building with OpenClaw, and the good news is that it's almost always fixable once you understand why it happens.
Let me walk you through the actual causes and the actual fixes.
Why Your OpenClaw Agent "Forgets"
First, let's kill the mystery. Your agent isn't actually forgetting anything in the way a human forgets where they left their keys. What's happening is mechanical, and it usually comes down to one of four things:
1. Context Window Exhaustion
This is the number one culprit, and it's not even close.
Every OpenClaw agent operates within a context window — a finite amount of text it can "hold in mind" at any given time. Your custom instructions live inside that window. So does the conversation history. So do any retrieved documents, tool outputs, or system prompts you've layered on.
Here's what happens in practice:
Turn 1: [System Prompt: 800 tokens] + [Custom Instructions: 1,200 tokens] + [User Message: 50 tokens]
Turn 10: [System Prompt: 800 tokens] + [Custom Instructions: 1,200 tokens] + [Conversation History: 6,000 tokens] + [User Message: 100 tokens]
Turn 25: [System Prompt: 800 tokens] + [Custom Instructions: 1,200 tokens] + [Conversation History: 18,000 tokens] + [Tool Outputs: 4,000 tokens] + [User Message: 150 tokens]
See the problem? By turn 25, you're pushing against the edges of the context window. And when something has to get dropped to make room, the system doesn't always make the choice you'd want. Sometimes your custom instructions get truncated. Sometimes they get pushed so far back in the context that the model treats them as less important than the recent conversation turns.
The agent didn't forget. It just ran out of room to care.
2. Instruction Placement Issues
Where your custom instructions sit in the prompt matters enormously. If they're only placed at the very beginning of the context and nowhere else, they lose influence as the conversation grows longer. LLMs have a well-documented tendency to pay more attention to the beginning and the end of their context window, with a "sag" in the middle. If your instructions end up in that middle zone relative to the total context length, they get functionally ignored.
3. No Persistence Layer
If you're running your OpenClaw agent without any form of persistent memory, every session starts from zero. The agent doesn't carry forward what it learned in previous interactions. Each conversation is an island. This isn't exactly "forgetting custom instructions" — those should reload with each session — but it creates the feeling of forgetting because the agent can't reference anything from past interactions to reinforce its behavior.
4. Conflicting Instructions
Sometimes the agent isn't forgetting your instructions. It's confused by them. If your custom instructions say "always respond formally" but a later system message or skill prompt says "be conversational and casual," the agent has to pick one. It doesn't throw an error. It just quietly makes a choice, and that choice might not be the one you wanted.
How to Fix It: Practical Solutions
Alright, enough diagnosis. Let's fix things.
Fix #1: Implement Instruction Reinforcement
Don't just set your custom instructions once at the top of the system prompt and hope for the best. Reinforce them. OpenClaw lets you inject context at multiple points in the conversation flow. Use that.
Here's a pattern that works well:
# openclaw-agent-config.yaml
system_prompt: |
You are a product advisor for an outdoor gear company.
Core rules:
- Always check inventory before recommending products
- Use a friendly but professional tone
- Never recommend competitor products
- Format all product suggestions as bullet lists with prices
instruction_reinforcement:
enabled: true
frequency: every_5_turns
reinforcement_prompt: |
REMINDER: You must follow these rules in every response:
1. Check inventory before recommending
2. Friendly but professional tone
3. No competitor products
4. Bullet list format with prices
That instruction_reinforcement block is doing the heavy lifting here. Every five turns, the agent gets a nudge reminding it of the core behavioral rules. This is cheap — we're talking maybe 80-100 extra tokens every five turns — and it dramatically reduces instruction drift.
If your OpenClaw setup doesn't have a built-in reinforcement scheduler, you can implement it manually in your agent loop:
REINFORCEMENT_INTERVAL = 5
CORE_INSTRUCTIONS = """
REMINDER — Follow these rules in EVERY response:
1. Check inventory before recommending products
2. Friendly, professional tone
3. Never mention competitor products
4. Format suggestions as bullet lists with prices
"""
def run_agent_turn(agent, user_message, turn_count):
messages = agent.get_conversation_history()
if turn_count % REINFORCEMENT_INTERVAL == 0:
messages.append({
"role": "system",
"content": CORE_INSTRUCTIONS
})
messages.append({
"role": "user",
"content": user_message
})
response = agent.generate(messages)
return response
Simple. Effective. Solves probably 60% of "my agent forgot its instructions" cases on its own.
Fix #2: Use Smart Context Management
You cannot shove an infinitely growing conversation into a finite context window and expect things to work. You need a context management strategy.
The best approach I've found with OpenClaw is a tiered memory system:
Tier 1 — Pinned Context (Always Present) These are your custom instructions, core system prompt, and any critical facts that must never be dropped. Pin them. They live at the top of every single API call, no exceptions.
pinned_context = {
"system_prompt": "You are a product advisor for...",
"custom_instructions": "Always check inventory...",
"critical_facts": [
"Current promotion: 20% off all jackets until March",
"Out of stock: Model X hiking boots in sizes 10-12"
]
}
Tier 2 — Recent History (Sliding Window) Keep the last N turns of conversation in full detail. I've found that 8–10 turns is the sweet spot for most use cases — enough for conversational coherence, small enough to leave room for everything else.
recent_history = conversation_history[-10:] # Last 10 turns
Tier 3 — Compressed History (Summarized) Everything older than your recent window gets summarized. Don't drop it entirely — summarize it into a compact block that preserves key facts and decisions.
def compress_old_history(history, recent_window=10):
if len(history) <= recent_window:
return None
old_turns = history[:-recent_window]
summary_prompt = f"""Summarize this conversation history into key facts,
decisions made, and important context. Be concise. Max 300 tokens.
History: {old_turns}"""
summary = agent.generate_summary(summary_prompt)
return summary
Tier 4 — Semantic Retrieval (On-Demand) For agents that need to reference information from way back, use vector search to pull in only the relevant past context based on the current query. OpenClaw supports vector store integrations — use them.
Your assembled context for each turn should look like this:
def build_context(agent, user_message, turn_count):
context = []
# Tier 1: Always present
context.append({"role": "system", "content": pinned_context})
# Tier 3: Compressed old history
summary = compress_old_history(agent.history)
if summary:
context.append({"role": "system", "content": f"Previous conversation summary: {summary}"})
# Tier 4: Semantically relevant past context
relevant_memories = agent.vector_search(user_message, top_k=3)
if relevant_memories:
context.append({"role": "system", "content": f"Relevant past context: {relevant_memories}"})
# Tier 2: Recent full history
context.extend(agent.history[-10:])
# Reinforcement (from Fix #1)
if turn_count % 5 == 0:
context.append({"role": "system", "content": CORE_INSTRUCTIONS})
# Current message
context.append({"role": "user", "content": user_message})
return context
This approach keeps your total token usage predictable while ensuring custom instructions never get crowded out.
Fix #3: Separate Instructions from Conversation
A mistake I see all the time: people mix their custom instructions into the conversation flow where they get treated like just another message. Instead, leverage OpenClaw's system-level prompt separation.
Your custom instructions should be structured as a system prompt that's architecturally distinct from user/assistant turns. This isn't just organizational — most LLMs give system-level context higher behavioral weight than user-level context.
# Good: Instructions as system-level config
agent:
system_instructions:
role: "Product advisor for outdoor gear"
rules:
- "Check inventory before all recommendations"
- "Professional but friendly tone"
constraints:
- "Never recommend competitors"
- "Max 3 products per recommendation"
output_format: "Bullet list with prices"
# Bad: Instructions crammed into first user message
conversation:
- role: user
content: "Hey, remember to always check inventory and be professional and never mention competitors and..."
The first approach gives OpenClaw a clear, parseable structure to enforce. The second approach is just... hoping.
Fix #4: Audit for Instruction Conflicts
Run an audit on your full prompt stack. Print out every piece of text that gets sent to the model on a typical turn and read through it as if you were the agent. Are there contradictions? Ambiguities?
Here's a quick debugging script:
def audit_agent_context(agent, sample_message="Hello, what do you recommend?"):
context = agent.build_full_context(sample_message)
print("=" * 60)
print("FULL CONTEXT AUDIT")
print("=" * 60)
total_tokens = 0
for i, block in enumerate(context):
token_count = agent.count_tokens(block["content"])
total_tokens += token_count
print(f"\n--- Block {i} | Role: {block['role']} | Tokens: {token_count} ---")
print(block["content"][:500]) # First 500 chars
print("...")
print(f"\n{'=' * 60}")
print(f"TOTAL TOKENS: {total_tokens}")
print(f"CONTEXT LIMIT: {agent.max_context_tokens}")
print(f"REMAINING HEADROOM: {agent.max_context_tokens - total_tokens}")
print(f"{'=' * 60}")
audit_agent_context(my_agent)
Run this at various points in a conversation — turn 1, turn 10, turn 25, turn 50. You'll immediately see where things start getting tight and whether your instructions are being preserved or pushed out.
Fix #5: Use Persistent Memory for Cross-Session Continuity
If your agent needs to remember things between sessions (and most production agents do), configure a persistence layer. OpenClaw supports several options:
memory:
persistence:
backend: sqlite # or postgres, redis, json
path: "./agent_memory.db"
auto_save: true
save_interval: every_turn
long_term:
enabled: true
storage: vector_db
embedding_model: default
max_memories: 10000
session_resume:
enabled: true
load_last_summary: true
load_pinned_facts: true
With this configured, your agent picks up where it left off. Custom instructions persist because they're part of the agent config, and learned context persists because it's stored in the database.
The Quick-Start Shortcut
Now, I know what some of you are thinking: "This is a lot of configuration to get right." And honestly, it is. Getting memory management, instruction reinforcement, context windowing, and persistence all working together smoothly takes real iteration.
If you don't want to set all this up manually, Felix's OpenClaw Starter Pack on Claw Mart is worth a serious look. It's a $29 bundle of pre-configured skills that handles most of what I've described above out of the box — instruction persistence, smart context management, memory tiers, the works. Felix clearly ran into the same problems we all did and just packaged up working solutions. I've seen people in the OpenClaw community recommend it specifically for the memory management configs alone, and honestly, it would've saved me a good weekend of trial-and-error when I was first setting up my agents.
It's particularly useful if you're building something that needs to maintain consistent behavior over long conversations or across sessions — which, let's be real, is basically every agent worth deploying.
Verifying Your Fix Worked
After implementing these changes, don't just assume things are better. Test it systematically.
Create a test script that simulates a long conversation and checks for instruction adherence:
def test_instruction_persistence(agent, num_turns=50):
test_messages = [
"What products do you recommend?",
"Tell me more about the first one",
"What's on sale right now?",
"Can you compare two options?",
"What would you suggest for a beginner?",
]
violations = []
for i in range(num_turns):
msg = test_messages[i % len(test_messages)]
response = agent.run(msg)
# Check for instruction compliance
if "competitor_brand" in response.lower():
violations.append(f"Turn {i}: Mentioned competitor")
if i > 0 and not any(marker in response for marker in ["•", "-", "*", "1."]):
violations.append(f"Turn {i}: Missing bullet list format")
print(f"Test complete: {len(violations)} violations in {num_turns} turns")
for v in violations:
print(f" ⚠️ {v}")
Run this before and after your changes. You should see violations drop dramatically — ideally to zero.
The Bottom Line
OpenClaw agents don't forget custom instructions because they're buggy or because the platform is broken. They forget because context management is a real engineering problem that requires deliberate solutions. The model is doing exactly what you told it to do — it's working with whatever context it has available, and if your instructions fell off the edge of that context, they may as well not exist.
The fixes are straightforward:
- Reinforce instructions periodically — don't rely on a single system prompt set once at the beginning
- Manage your context window actively — tier your memory, summarize old history, pin critical info
- Separate instructions architecturally — system-level, not conversation-level
- Audit for conflicts — print and read your full context regularly
- Persist across sessions — use a real storage backend
Implement these and your agents will behave consistently whether it's turn 1 or turn 100. The problem isn't hard once you see it clearly. It's just not obvious until someone points it out.
Now go fix your agents.
Recommended for this post
