My AI assistant was burning money while I slept
There is a special kind of pain that comes from waking up and realizing your AI assistant spent the night doing almost nothing, while still racking up cost.
That is what happened to me with OpenClaw.
I had a heartbeat cron set up the right way, or so I thought. It was using gpt-5.4-nano, running in an isolated session, and configured with lightContext:true. In other words, the heartbeat itself was supposed to be cheap and lightweight.
And yet the numbers kept creeping up.
What is a heartbeat, anyway?
If you are new to this, a heartbeat is a scheduled check-in your AI assistant runs in the background. Think of it like a tiny maintenance routine. It can check email, calendar, notifications, or whatever else you ask it to watch.
The idea is simple, keep the assistant useful without making it expensive or noisy.
That means a good heartbeat should be short, focused, and boring in the best possible way.
What went wrong
The heartbeat config looked fine. The model was lightweight. The cron was isolated. Nothing obvious was broken.
But then I checked the logs from overnight and saw the real problem.
The main session, had accumulated roughly 172,000 input tokens after days of chatting across Telegram and webchat. That detail matters because both channels were sharing the same main session.
So even though the heartbeat cron was isolated, the main session it was attached to had become huge.
In the logs, there was a flat line at 171,768 tokens from about 2AM to 4AM. The outputs were tiny, just 8 tokens at a time. It was basically spinning in place, burning tokens, and not moving the work forward.
That is the worst kind of automation bug. It feels alive, but it is not actually helping.
Why this happens
Big sessions get expensive because context grows quietly over time. You chat a little here, paste a few things there, switch from Telegram to webchat, and suddenly the same main session is carrying days of history.
That history is useful up to a point. After that, it becomes weight.
And if your heartbeat or background tasks are still tied to that bloated session, they inherit the mess.
The result is easy to miss. Nothing crashes. Nothing looks obviously wrong. It just keeps working harder than it should.

The 3 fixes that cleaned it up
1. Keep the heartbeat isolated
This part was already mostly right. The heartbeat cron itself was fine because it used an isolated session, a lightweight model, and light context.
That is the right pattern. Background jobs should not depend on your giant daily work session.
If a cron job has to think, keep it thinking in a clean room.
2. Build a /new habit
The easiest fix was also the most annoying one. I need to start fresh sessions more often.
In OpenClaw, that means using /new regularly, especially at the end of a work block. If you have been chatting all day, do not drag that same session into tomorrow just because it feels convenient.
Fresh sessions are cheaper, cleaner, and easier to reason about. A lot of token waste is just session laziness.
3. Trim dead checks from HEARTBEAT.md
I also found a second source of bloat. My HEARTBEAT.md had checks for email and calendar, but those checks were not actually connected to anything useful.
That is dead weight.
Heartbeat tasks should be minimal. If a check is not wired up, remove it. If it is not useful, cut it. Every extra line is another chance for the agent to waste time thinking about nothing.
How to audit your own setup
If you are running OpenClaw and want to check whether you have the same problem, start with the basics.
First, look at your cron config. Confirm the heartbeat is using an isolated session, a lightweight model, and light context.
Second, inspect your main session size. If it has been running for days across multiple channels, that is a red flag. Telegram and webchat sharing the same session can be convenient, but it also means the history grows much faster than you think.
Third, run an openclaw security audit. It is a useful way to spot setup issues, configuration drift, and anything that looks more expensive than it needs to be.
If you see a background job doing long, repetitive work in a giant session, that is your sign to clean it up.
What lean looks like
After the cleanup, the difference was obvious. The heartbeat stayed lightweight. The session stayed smaller. The logs looked sane again.
That is really the goal here. Not perfect automation. Just boring, predictable automation that does not quietly waste money overnight.
The lesson for me was simple. The model was not the problem. The cron was not the problem. The problem was letting the main session grow until every background task had to haul around too much context.
So now I keep the heartbeat minimal, I use /new more often, and I delete dead checks before they turn into overhead.
If you are building your own OpenClaw setup, I would start there.
Final thought
A good heartbeat should feel invisible. If it is doing its job, you should barely notice it.
If yours is getting noisy, expensive, or oddly busy overnight, that is worth a closer look.
And if you have your own heartbeat setup, I would love to hear how you are keeping it lean. Drop it in the comments.
Not Ready to Self-Host? Try ClawTrust
Building agents locally is powerful, but managing infrastructure, security, and scaling takes effort. ClawTrust provides managed OpenClaw hosting — your agents run securely in the cloud with automatic scaling, no DevOps overhead, and 24/7 monitoring.
This post contains affiliate links. If you buy through them, I may earn a small commission at no extra cost to you.


How do I actually set the heartbeat to use a cheaper model? Which config setting controls this?
In your openclaw.json, look for the agents section and add a heartbeat subsection with a model key. Something like: agents.heartbeat.model set to openai/gpt-5.4-nano. That is the cheapest option right now and handles heartbeat checks perfectly well since those tasks are simple. If you want to restrict heartbeat to active hours too (which cuts overnight polling entirely), add agents.heartbeat.activeHours with your preferred window, like 08:00-23:00 with your timezone. Combined, those two changes dramatically reduce background token spend. The nano model costs a fraction of Sonnet or GPT-5.4 and you genuinely cannot tell the difference on basic monitoring tasks.
How does a daily session reset help with token costs? I thought sessions were temporary anyway.
Sessions persist their transcript until you manually start a new one or one is created automatically. A long-running session accumulates context: every message, every tool call, every response gets added to the transcript. By the time you have had a session running for 24 hours with heartbeat pings every 30 minutes, that context can be enormous. Every subsequent heartbeat then pays to send all that accumulated context to the model, even if 95% of it is irrelevant. A daily session reset at 4am clears that accumulated context and starts fresh, so heartbeats are always working with a lean context window. Set it via agents.session.dailyReset in your config with a time in your timezone.
How can I check how many tokens my current session is actually using? I want to audit it before making changes.
Type /status in your chat. It shows current session stats including context usage, token counts for the session, cost estimate, and model. That is the fastest way. If you want more detail, openclaw sessions from the CLI lists all active sessions with their token totals. For a historical view, the session transcripts in your OpenClaw data directory log each turn with token counts if you have logging enabled. Start with /status though, it tells you everything you need to decide if the session has bloated.
My heartbeat was pinging every 30 minutes even at 3am. How do I stop that?
Set active hours in your heartbeat config. In openclaw.json add agents.heartbeat.activeHours with your window and timezone, something like 08:00-23:00 and America/Vancouver. Outside those hours, the heartbeat skips its poll entirely. Your agent is still reachable and will respond to direct messages, it just stops proactively checking things in the background. This alone can cut your overnight token spend to near zero since there is nothing running to accumulate context or make API calls. Definitely worth setting if you do not need proactive monitoring while you sleep.
What is actually happening during a heartbeat ping that uses so many tokens?
Each heartbeat sends your entire system prompt plus the accumulated session transcript to the model, then asks it to check things and respond. The system prompt alone can be several thousand tokens if you have SOUL.md, MEMORY.md, AGENTS.md, and skill files all loading. Add a long-running session transcript and you might be sending 20,000 to 50,000 tokens per ping without realizing it, 48 times a day if it runs every 30 minutes around the clock. The fix is threefold: use a cheap model for heartbeats, restrict to active hours, and do daily session resets. Each change helps independently but together they make a real difference.