Adding a tool to an agent feels like adding capability. It also adds another action that can fail, repeat, or leave something half finished. I would like the permission to use a tool to arrive with a description of how the run ends. Without that description, the system can become very busy while giving its operator less certainty about what has actually happened.
Isuru Wijesiri’s Harness Engineering 101 uses a small implementation to explain agent infrastructure. I reviewed its public README; I am not adapting the book’s chapters, examples or code here. The useful starting question for this article is independent: how would we bound a simple task before increasing the number of actions an agent can take? The following invoice example is hypothetical and deliberately limited to read-only work.
Define the useful result first
Imagine an agent checking a folder of sample invoices against a local policy. Its output should identify the files examined, the checks applied, uncertain findings and files it could not read. It cannot pay an invoice, contact a supplier or modify the originals. That boundary makes the result easier to inspect. A run that reads eight files and clearly reports two unreadable ones may be more useful than a run that keeps trying forever in pursuit of an unqualified success label.
The first limit is a deadline. In this proposed design, a run has two minutes to produce a report. The second limit is an action budget of twelve tool calls. These numbers are illustrative choices for the example, not recommended defaults. Whichever limit arrives first ends further tool use. The agent then returns the partial result with the reason for stopping. A limit that merely changes the displayed status while background calls continue is not doing the job described by this contract.
The third limit deals with repetition. Suppose the agent receives the same permission error twice while opening one file. Retrying with unchanged access and the same request has no new basis. A no-progress record could compare the requested operation, target and error category, without copying sensitive file contents into a log. The report would say access was unavailable. It would not silently widen permissions, move the file elsewhere or describe the unread file as checked. Ending honestly is a useful capability.
Cancellation needs a receipt
Now imagine the operator cancels the run after seven files. What should remain? I would preserve the seven completed checks, identify any operation still in progress, and stop issuing new calls. The final status would distinguish cancellation from a completed review. If a tool cannot be interrupted immediately, the interface should show that specific outstanding operation instead of suggesting that everything has stopped. A cancel button is a request whose fulfilment needs evidence, just like any other action in the system.
Read-only work makes this example simpler. Once a workflow can change external state, stopping has a different meaning. A draft may already exist even if the next network request times out. Repeating the create action can produce a duplicate. Before adding that kind of tool, I would require a way to identify the intended object and reconcile an uncertain result. This is a design requirement, not an instruction to give the hypothetical invoice agent write access. Its current scope remains read-only.
The boundaries can be tested without asking a model to behave badly on demand. A stub tool can always return a permission error. Another can wait longer than the run’s remaining time. A third can return malformed data. The proposed checks ask whether the controller stops new actions, records the exact incomplete work and produces an inspectable partial report. They test the surrounding execution rules. They do not demonstrate that the model’s financial judgements are accurate, and they should not be reported as doing so.
Give each limit an owner
A model instruction saying please do not loop is different from a controller enforcing an action count. I would put the deadline and action budget in the part of the system that dispatches tools, then make their outcomes visible to the model and operator. The model can decide what useful explanation to provide within those limits. It should not be able to extend them merely by describing the next attempt as essential. Otherwise the boundary depends on the same judgement it was meant to constrain.
There is a practical tradeoff here. A strict budget can stop a task that another minute would have solved. A generous budget can make repeated failure expensive and hard to supervise. The right response is to record where a bounded run stopped and decide whether a specific continuation is justified. That is a smaller, clearer decision than granting an open-ended retry. Before I add another tool, I want to know what a useful partial result looks like, who can stop the run, and what proves that it stopped.



