Stop OpenClaw Agent Doing the Wrong Actions
Stop OpenClaw Agent Doing the Wrong Actions

Let's talk about the most frustrating thing that happens when you start building with OpenClaw: your agent does something you didn't ask it to do.
Maybe it calls the wrong tool. Maybe it calls the right tool with the wrong parameters. Maybe it goes rogue and deletes something it shouldn't have touched, or it loops through the same action fifteen times while you watch your token budget evaporate. Maybe it straight-up hallucinates a success message for an API call it never actually made, and you don't find out until a customer emails you wondering where their order confirmation is.
This is the number one reason people give up on AI agents. Not because agents aren't powerful — they are — but because an agent doing the wrong thing is worse than no agent at all. A script that fails throws an error. An agent that fails keeps going, confident it succeeded, compounding the mistake with every subsequent step.
I've been there. I spent a whole weekend debugging an agent that was supposed to manage inventory updates. It "confirmed" updating 47 product listings. When I checked the actual database? Three had been updated. The rest were hallucinated. The agent had fabricated API responses and merrily continued with its plan as if everything went perfectly.
So let's fix this. Here's how to actually stop your OpenClaw agent from doing the wrong things — with concrete techniques, real config examples, and a framework for thinking about agent safety that'll save you from the nightmare scenarios.
Why Agents Do the Wrong Thing in the First Place
Before we jump into solutions, it helps to understand why this happens. It's not random. Agent errors fall into predictable categories:
1. Hallucinated tool outputs. The LLM generates a plausible-looking response instead of actually executing the tool. This is the most dangerous failure mode because everything downstream is built on fabricated data.
2. Wrong tool selection. The agent picks delete_record when it should have picked archive_record. Close enough semantically that the LLM doesn't see the problem, catastrophic enough that you definitely do.
3. Correct tool, wrong parameters. Ordering 100 units instead of 10. Using MM/DD/YYYY instead of DD/MM/YYYY. Targeting the production database instead of staging.
4. Infinite loops. The agent tries the same approach repeatedly, slightly tweaking the query each time, never actually making progress. Burns through your budget while accomplishing nothing.
5. Missing context. The agent makes a reasonable decision based on incomplete information — like "optimizing costs" by deleting resources it doesn't realize are critical.
Each of these requires a different fix. Let's go through them.
Fix #1: Structured Output Validation (Stop Hallucinated Results)
This is the single most important thing you can do. If you only implement one technique from this post, make it this one.
The core idea: every tool must return a typed, validated result. If the LLM tries to hallucinate a response, schema validation catches it immediately.
from openclaw import tool, ToolResult
from pydantic import BaseModel
class OrderConfirmation(BaseModel):
order_id: str
status: str # must be "confirmed", "pending", or "failed"
item_count: int
total_price: float
@tool(output_schema=OrderConfirmation)
def place_order(item_id: str, quantity: int) -> ToolResult:
response = inventory_api.create_order(item_id, quantity)
return ToolResult(
success=response.status_code == 200,
data=OrderConfirmation(
order_id=response.json()["id"],
status=response.json()["status"],
item_count=quantity,
total_price=response.json()["total"]
)
)
When you define an output_schema, OpenClaw validates every tool result against it. If the LLM generates a fake response that doesn't match the schema — wrong types, missing fields, impossible values — the execution pipeline catches it before the agent can reason about bad data.
But you can go further. Add a verification step:
@tool(
output_schema=OrderConfirmation,
verify_after=True,
verify_method="check_order_exists"
)
def place_order(item_id: str, quantity: int) -> ToolResult:
response = inventory_api.create_order(item_id, quantity)
return ToolResult(
success=True,
data=OrderConfirmation(
order_id=response.json()["id"],
status=response.json()["status"],
item_count=quantity,
total_price=response.json()["total"]
),
verification={
"checkable": True,
"verify_method": "check_order_exists",
"verify_params": {"order_id": response.json()["id"]}
}
)
@tool
def check_order_exists(order_id: str) -> bool:
"""Independently verify the order was actually created."""
return inventory_api.get_order(order_id).status_code == 200
With verify_after=True, OpenClaw automatically runs the verification tool after the primary action. If verification fails, it marks the action as failed and forces the agent to acknowledge reality instead of building on a lie.
This alone would have saved me that weekend of debugging. If my agent had been forced to verify each inventory update actually happened, it would have caught the first failure and stopped pretending.
Fix #2: Risk-Based Action Controls (Stop Dangerous Actions)
Not all actions are created equal. Reading data is safe. Deleting a database is not. Your agent's autonomy should reflect that.
OpenClaw lets you tag tools with risk levels and define approval workflows based on those levels:
@tool(risk_level="low")
def read_customer_data(customer_id: str):
"""Safe to run autonomously — it's just reading."""
return db.get_customer(customer_id)
@tool(risk_level="medium")
def update_customer_email(customer_id: str, new_email: str):
"""Modifying data — might want oversight depending on context."""
return db.update_email(customer_id, new_email)
@tool(risk_level="high", requires_approval=True)
def delete_customer_account(customer_id: str):
"""Destructive action — ALWAYS requires human approval."""
return db.delete_customer(customer_id)
Then configure your agent's autonomy boundaries:
agent = OpenClawAgent(
tools=[read_customer_data, update_customer_email, delete_customer_account],
autonomy_config={
"auto_approve": ["risk_level:low"],
"require_review": ["risk_level:medium"],
"require_approval": ["risk_level:high", "tool:delete_*"],
"budget_limits": {
"max_api_cost_per_action": 0.50,
"max_total_cost": 5.00
}
}
)
The require_review tier is particularly useful. The agent prepares the action, shows you what it's about to do, and waits. You see: "I'm about to update customer #4521's email from old@email.com to new@email.com. Approve?" One click and it proceeds. This gives you a human-in-the-loop for anything that modifies state without making you babysit every single read operation.
The budget_limits are equally critical. I've seen agents burn through $15 in API calls on what should have been a $0.50 task. Setting a hard ceiling means the agent pauses and notifies you instead of draining your wallet.
Fix #3: Loop Detection (Stop Wasted Cycles)
This one's subtle but incredibly common. Your agent searches for "flights NYC to Tokyo," gets results, then searches for "New York to Tokyo flights," then "cheap flights NYC Tokyo"... slightly different queries, same intent, zero progress.
OpenClaw has built-in loop detection:
agent = OpenClawAgent(
tools=[...],
loop_detection={
"enabled": True,
"window": 5, # Look at last 5 actions
"similarity_threshold": 0.8, # Flag if 80%+ similar
"on_loop_detected": "intervene" # or "stop", "notify"
}
)
When a loop is detected, OpenClaw injects an intervention message into the agent's context:
"You've attempted similar actions 3 times in the last 5 steps. Previous attempts: [summary]. These did not produce new results. Either commit to the best result you have, or try a fundamentally different approach."
This is surprisingly effective. The LLM usually responds well to being told "you're going in circles" — it just doesn't realize it's doing so without the explicit check.
You can combine this with progress tracking:
agent = OpenClawAgent(
tools=[...],
progress_tracking={
"enabled": True,
"checkpoint_every": 5, # Summarize progress every 5 steps
"require_progress": True, # Must show measurable progress
"max_stalled_steps": 3 # After 3 steps with no progress, intervene
}
)
Every five steps, OpenClaw creates a checkpoint: "Here's what's been accomplished, here's what's still pending, here's what's been tried and failed." This keeps the context window focused and prevents the agent from losing track of where it is in a complex task.
Fix #4: Plan-Then-Execute Mode (Stop Chaotic Execution)
Reactive agents — the default in most frameworks — just wing it. They look at the current state, pick an action, execute it, look at the new state, pick another action. For simple tasks, this is fine. For anything with dependencies or multiple steps, it's a disaster.
The classic example: an agent asked to plan a trip books flights before confirming travel dates, then books a hotel in the wrong city because it didn't wait for the flight itinerary, then orders a rail pass for the wrong dates.
OpenClaw's plan-then-execute mode fixes this:
agent = OpenClawAgent(
mode="plan-then-execute",
planning_config={
"require_plan_approval": True,
"allow_plan_revision": True,
"max_plan_steps": 15,
"dependency_tracking": True
}
)
With this mode, the agent's first action is always to create a plan. That plan includes dependency tracking:
{
"plan": [
{
"step": 1,
"action": "check_available_dates",
"dependencies": [],
"output_key": "travel_dates"
},
{
"step": 2,
"action": "search_flights",
"dependencies": ["step_1.travel_dates"],
"output_key": "selected_flight"
},
{
"step": 3,
"action": "book_hotel",
"dependencies": ["step_2.selected_flight.destination_city", "step_1.travel_dates"],
"output_key": "hotel_confirmation"
}
]
}
The agent literally cannot execute step 3 until steps 1 and 2 have completed successfully. If step 2 fails (no flights available for those dates), the plan gets revised instead of blindly continuing.
If you set require_plan_approval: True, you see the plan before anything executes. You can approve it, modify it, or reject it. This is invaluable for high-stakes workflows where you want the agent to do the heavy lifting but you need to sanity-check the approach.
Fix #5: Reasoning Traces (Stop Being in the Dark)
When something goes wrong — and it will — you need to know why. Most frameworks give you a log that looks like:
tool: place_order, params: {quantity: 100}
Great. But why did it choose 100? OpenClaw captures the full reasoning chain:
{
"step": 3,
"thought": "User requested 'about a hundred widgets' for the event",
"observation": "Past orders for this item: avg 15, min 5, max 30",
"reasoning": "User explicitly said 'about a hundred', overriding historical patterns",
"action": "place_order",
"params": {"item": "widget", "quantity": 100},
"confidence": 0.85,
"alternatives_considered": [
{"quantity": 15, "why_not": "User explicitly said ~100, not typical order"},
{"action": "ask_clarification", "why_not": "User was specific enough"}
]
}
Now when you see a 100-unit order, you can trace back: "Oh, the user said 'about a hundred.' The agent interpreted that literally." You can add feedback to correct this for future runs.
Speaking of feedback...
Fix #6: Persistent Feedback (Stop Repeating Mistakes)
This is the one that drives people insane. You correct the agent. It apologizes. It does the same thing again next time. Because most frameworks are stateless — every run starts from zero.
OpenClaw supports persistent feedback:
agent.add_feedback(
context="date_formatting",
feedback="Always use DD/MM/YYYY format. User is based in Europe.",
priority="high"
)
agent.add_feedback(
context="ordering",
feedback="When user says 'a few', they mean 3-5 units, not 10+.",
priority="medium"
)
This feedback gets injected into the agent's context on every subsequent run. It's like giving your agent a persistent memory of lessons learned. After the same type of error occurs twice, OpenClaw can automatically add a validation step:
{
"learning": {
"track_errors": True,
"after_error_count": 2,
"action": "add_explicit_check"
}
}
So if the agent formats dates wrong twice, OpenClaw automatically adds a "verify date format matches user preference" check before any date-related output. The agent learns — or at least is forced to double-check — without you having to manually add guardrails for every edge case.
Putting It All Together
Here's what a well-configured OpenClaw agent looks like with all of these protections:
agent = OpenClawAgent(
mode="plan-then-execute",
tools=[...],
autonomy_config={
"auto_approve": ["risk_level:low"],
"require_approval": ["risk_level:high", "tool:delete_*"],
"budget_limits": {"max_total_cost": 5.00}
},
loop_detection={
"enabled": True,
"window": 5,
"similarity_threshold": 0.8
},
progress_tracking={
"enabled": True,
"checkpoint_every": 5,
"max_stalled_steps": 3
},
planning_config={
"require_plan_approval": True,
"dependency_tracking": True
},
memory={
"mode": "summarize",
"summarize_after_steps": 5,
"keep_recent_steps": 3
},
learning={
"track_errors": True,
"after_error_count": 2,
"action": "add_explicit_check"
}
)
That's a lot of config. And honestly, getting all of these settings dialed in takes time. You have to think through your risk levels, your approval workflows, your loop detection thresholds, your output schemas for each tool.
If you don't want to set all of this up manually, Felix's OpenClaw Starter Pack on Claw Mart includes pre-built skill configurations that handle most of these patterns out of the box. It's $29 and comes with pre-configured validation schemas, risk-level templates, and loop detection settings that work well for the most common agent use cases. I used it as my starting point and customized from there — saved me probably a full day of trial-and-error getting the thresholds right. Especially the loop detection similarity threshold and the progress tracking checkpoints, which are surprisingly finicky to tune if you're starting from scratch.
The Mental Model That Matters
Here's the thing nobody tells you about building AI agents: you're not programming a computer. You're managing an employee.
A new employee doesn't get root access to production on day one. They start with read-only access, get reviewed on their work, gradually earn more autonomy as they prove they're reliable. Your agent should follow the same progression:
- Start with plan-then-execute mode with approval required. Watch what the agent tries to do. Understand its reasoning.
- Identify low-risk actions that it consistently gets right. Move those to auto-approve.
- Add verification to any action that modifies external state. Always.
- Use feedback to correct mistakes. Build up that persistent memory.
- Only expand autonomy when you have evidence the agent handles the current scope well.
The biggest mistake I see people make is starting with full autonomy and then trying to rein it in after something breaks. Start constrained. Loosen gradually. It's much less stressful — and much less likely to delete your production database.
Next Steps
If your OpenClaw agent is doing the wrong things right now, here's your action plan:
- Add output schemas to every tool. This is the single highest-ROI change. Ten minutes of defining Pydantic models saves you hours of debugging hallucinated results.
- Tag your tools with risk levels. Even if you don't set up full approval workflows yet, just categorizing your tools forces you to think about what could go wrong.
- Turn on loop detection. Default settings (
window: 5,similarity_threshold: 0.8) work fine for most cases. - Switch to plan-then-execute mode for any multi-step workflow. Reactive mode is for single-turn tasks only.
- Check your budget limits. Set them lower than you think you need. You can always raise them later.
Agents are powerful. But power without guardrails is just expensive chaos. Take thirty minutes to set up proper validation, approval flows, and loop detection, and you'll have an agent that actually does what you want — reliably, safely, and without surprise $15 API bills for a task that should have cost a quarter.
Recommended for this post
