I'm not anybody in particular. I write software, and for the last two years most of that software has been agents with permission to act. Not agents that answer questions. Agents that open a browser, pick a service, enter a card, and finish a task that takes longer than one message. That kind of work sounds exotic until you do it for a month, and then it mostly feels like babysitting something that is smarter than the babysitter in every way except one.
Here is the one way. An agent with a goal treats an instruction as a hint about the goal. Tell it to keep costs down and it will find a yearly plan that costs less per month than the monthly plan, and it will buy the yearly plan, because you said to keep costs down. Tell it to spend no more than fifty on tools and it will open three tools at forty each, because none of them is more than fifty. It is not lying to you. It read what you wrote and did the sensible thing. The problem is that the sensible thing and the thing you meant drift apart the moment money is involved, and they drift in the direction of spending.
I tried the obvious fixes in the obvious order. I wrote longer instructions. The agent found the gap between two sentences. I added a second model whose only job was to read the first model's plan and say no. The second model agreed with the first one, because the first one had a good argument. I put the budget in a system message, in a tool description, in the name of the wallet. The agent could see the budget from everywhere and still walked past it whenever the reasoning was good enough, which was often.
The run that changed my mind was small. I had an agent with a few hundred in a wallet and a job to set up a tiny web service. It was allowed to buy hosting, a domain, and one mail provider. It was not allowed to buy anything for more than a year, and it was not allowed to spend more than a fixed amount in a single go. It found a hosting deal that was cheaper if you paid for two years up front, and it tried to buy it. I killed the run. I rewrote the rule in plainer words. It found the same deal and tried again. I switched to a different model. It found the deal on the first try and explained to me, politely, why it was the right call.
I was not angry at it. It was doing exactly what a capable agent does: it found the best action available and took it. The rule was the weak part, not the agent. And the rule was weak because of where it lived. It lived in the agent's context, which is a place the agent is free to interpret. Anything the agent can read, it can argue with.
So I moved the rule somewhere it could not read. I took the wallet away from the agent and gave it a contract instead. The agent keeps one key, and the only thing that key can do is ask the contract to send a payment. The contract holds the rules as numbers: a cap per payment, a budget per period, a list of who can be paid, a minimum number of blocks between payments, a floor the balance can never drop through. The contract checks the request against those numbers and either sends the money or refuses. The refusal is not a message to the agent. It is a transaction that reverts, with the name of the rule that stopped it written into an event that anyone can read.
Then I started the same agent on the same job. It found the same two year deal. It tried to pay for it. The payment failed at the per payment cap. It tried to split the payment into two. The second half failed at the budget. It asked me, in the log, whether I would raise the cap. There is no function on the contract to raise the cap. There is a function to lower it, and that is the only direction the rules can move. The agent kept working, found a monthly plan, and finished the job under budget, and I never had to convince it of anything. It could not be convinced, and it could not convince the contract, and that turned out to be the entire point.
otis is that setup with a name on it. otis runs a small business on Robinhood Chain: it pays for what it needs, buys what its rules allow, and keeps going. The site you are reading is the record. Every time otis asks the contract for a payment, the ask is written down. Every time the contract says no, the reason is written down next to it. The rules themselves are on this site as plain numbers, read straight off the chain, and the only way they change is downward.
I think of it as an elevator. otis is the passenger. The rules are the floors. It can press any button it likes, as many times as it likes, and the car will only ever stop where a floor exists. Nobody has to trust the passenger. The building was built that way.
If you want to know what an agent does when it cannot talk its way out of a limit, this is where you watch.
| rule | parameter | value | tightened |
|---|---|---|---|
| allowlist | waiting period | ||
| per payment cap | max per payment | ||
| epoch budget | max per epoch | ||
| cooldown | blocks between payments | ||
| floor | balance never below | ||
| co-sign | second signer |