The number that changed and stayed changed
For most of September and the start of October, my agent cost me about $0.40 a day. Small enough that I stopped looking at it. On 8 October the figure became $3.17 a day and it has stayed there. That is a factor of eight, and the important word is “step”: the line does not climb, it jumps on one day and then runs flat at the new level.
A jump like that has a short list of causes. Something is leaking. Something is running twice. Something new started. I went through them in that order, because the first one is the one that costs you money quietly for months.
First suspect: a second consumer
The reason I suspected a leak rather than a price change is that the provider console and my own accounting refused to agree. My agent tracks its own spend per session, per transport, per day. Compared with the console, my numbers were off by a factor of 1.1 to 2.5 on cost, and by up to 20 on request count.
A 20x gap on requests looks exactly like a second process using the same key. Some cron I had forgotten, some retry loop, some tool with the key in its environment. I spent an evening looking for it, and it was not there.
The gap did not survive being compared like with like. What I had been counting at one level and what the console counts at another are not the same unit, and once the units lined up the discrepancy collapsed into the ordinary messiness of retries and streaming setup. No second consumer. Nothing had been compromised. That was a relief and also the moment the problem got less interesting and more expensive to fix, because “someone stole it” has a clean solution and “my usage really is that big” does not.
I want to be honest about the 20x here: I still cannot reconcile that figure to the last request. It went away when I stopped comparing two counters that were never measuring the same thing, and I have left it as a known unknown rather than pretending I ran it to ground.
Second suspect: the day the model changed
The step change dates from the day I changed the default model in my routing config. That is not a coincidence, and it is also not the whole explanation. Roughly double the daily session volume arrived at the same time, so the new rate met a bigger base on the same day and the two effects multiplied instead of adding.
Here is the part that took me longer than it should have. A model change is a price per token change, and I had been treating my cost as a function of how many messages I sent. It isn’t. It is a function of how many tokens go up with each message, and that number was not under my control in the way I assumed.
The actual driver: the conversation the agent was still carrying
Every turn, the agent sends the conversation so far. Not a summary of it. The conversation. So the cost of message forty is not the cost of one message, it is the cost of messages one through forty, and the curve is not linear at the end. Long sessions do not get expensive gradually. They get expensive at the point where the transcript stops fitting comfortably and every subsequent turn carries the whole thing.
My sessions had grown. Two of the long-runners were at 1,118 messages and 785 messages. Nothing about either session looked unusual from the inside; they were just conversations that kept going because they were useful, and the agent kept its whole history because keeping history is what makes it good at following a thread.
One session in July burned 744 million tokens on its own. That is a single conversation, and the number is large enough that I checked it twice before I believed it. At the time I was looking at a daily total of forty cents, so nothing about that session demanded attention. The daily total was hiding it, in the same way an average hides every outlier in the set.
Why I did not downgrade the model
The obvious fix is to route to something cheaper. I didn’t, because the maths doesn’t work. Downgrading pays a lower rate for the same runaway context. If a session is carrying a thousand messages that it does not need, a cheaper model just makes the mistake cost slightly less. It also degrades the part of the system I actually rely on, which is the agent’s ability to reason about a long, messy problem without losing the thread.
The cost is not in the intelligence. It was in the payload.
So the fix went at the payload. Sessions are now capped at 60 messages, across all three transports: email, iMessage and Telegram. Whichever way I start talking to it, the conversation gets to 60 turns and then it stops and hands back a fresh context rather than carrying a growing transcript for another eight hundred messages.
What a cap actually changes
The cap forces a decision I was not making before, which is what a long session is for. Some of them were doing real work and benefited from the history. A lot of them were me adding one more small thing to a conversation that had already finished its job, because starting fresh felt like more effort than continuing. That habit was the whole bill.
Sixty is not a magic number and I may move it. What matters more than the number is that it is a boundary with a stated reason rather than a habit with no limit. If a task genuinely needs more than sixty turns, that is a signal the task should be split, or that the agent should be writing its findings down as it goes instead of holding them in a transcript. Writing things down is what the brain is for. Carrying them in a context window is what was costing the money.
What I took from it
The instinct when a bill multiplies is to look for the thief. I looked for the thief for an evening and the answer was in the shape of my own usage: a step change starting the day a rate changed, sitting on top of a base that had quietly doubled, and a handful of sessions that had been running long enough to be expensive on any model at any price.
Follow the money and it leads to the conversation. Not to the model, not to a leaked key, not to a provider being creative with its billing. An agent is cheap until it is carrying something, and the most expensive thing I own is a chat I did not know how to end.