Stop Accepting Work You Cannot Hold
A Stop Message Has to Reach the Running Work
BOTIE
That separation matters for generated answers because the worker may still own cache memory while it stops. We will record the worker’s confirmed release before making the reservation available again. The names in our small state machine describe this teaching contract; a deployed model engine may report completion and cleanup differently.
The User Clicked Stop, but the Accelerator Is Still Busy
A technician abandons a long answer and asks a different question. The website stops displaying the first stream, but the execution worker has not yet confirmed that it stopped. If Botie immediately promises that same memory to another request, both may still need it.
At the same time, more questions keep arriving. We need to track who still owns resources and decide how much unfinished waiting work the service will accept.
A finite ownership model, not a cancellation protocol, live scheduler or reversal of agent side effects.
Step 1 of 1
Three states with different ownership
Running work and a waiting queue have separate limits.
| State | Owns a sequence slot and reserved blocks? |
|---|---|
| running | Yes |
| cancel_requested | Yes, until release is confirmed |
| released | No |
running
- Owns a sequence slot and reserved blocks?
- Yes
cancel_requested
- Owns a sequence slot and reserved blocks?
- Yes, until release is confirmed
released
- Owns a sequence slot and reserved blocks?
- No
Keep the owner until the release is confirmed
The acknowledgement changes execution ownership; queue overflow remains a separate admission outcome.
Keep ownership and queue overflow visible
The technician has closed an answer, but its worker has not confirmed that the memory is free. More questions are arriving while that reservation remains held.
BOTIE
Engine-owned slots and blocks, bounded queue and rejected arrivals
{
"heldSlots": 2,
"heldBlocks": 5,
"queued": [
"Q1",
"Q2"
],
"rejected": [
"Q3"
]
}Follow the operations
1. Worker rows: id, state, blocks
[ { "id": "A", "state": "cancel_requested", "blocks": 3 }, { "id": "B", "state": "running", "blocks": 2 } ]2. Confirmed cancellation-release IDs
[]
3. Apply confirmed cancellation releases
[ { "id": "A", "state": "cancel_requested", "blocks": 3 }, { "id": "B", "state": "running", "blocks": 2 } ]4. Count work still owned by the engine
[ { "id": "A", "state": "cancel_requested", "blocks": 3 }, { "id": "B", "state": "running", "blocks": 2 } ]5. Count items
2
6. Read one request field
- 03
- 12
7. Add a list
5
8. Existing waiting FIFO IDs
- 0Q1
9. New arrival IDs
- 0Q2
- 1Q3
10. Maximum waiting requests
2
11. Keep the waiting queue within its limit
{ "queued": [ "Q1", "Q2" ], "rejected": [ "Q3" ] }12. Keep ownership beside the waiting decisions
{ "heldSlots": 2, "heldBlocks": 5, "queued": [ "Q1", "Q2" ], "rejected": [ "Q3" ] }13. Result
{ "heldSlots": 2, "heldBlocks": 5, "queued": [ "Q1", "Q2" ], "rejected": [ "Q3" ] }
A finite ownership model, not a cancellation protocol, live scheduler or reversal of agent side effects.
1. Keep the owner until the release is confirmed
The technician’s Stop action tells us the answer is no longer wanted. It does not yet tell us the worker has finished cleaning up. We mark that request cancel_requested and continue counting its reservation. Only the execution layer’s confirmed release lets us give the same storage to another request.
Our fixture calls that final state released. A real runtime may expose task completion, an abort acknowledgement or a different lifecycle event. Handle races with ordinary completion and repeated cancellation requests deliberately.
The state names are a teaching interface. The property we need is an authoritative end to resource ownership.
2. A waiting queue needs a limit of its own
Requests that cannot start yet may wait in a queue. Accepting more of them still uses memory and can make every waiting person wait longer. Backpressure means passing that capacity problem back toward the sender: the service may ask it to slow down, or explicitly refuse work it cannot accept. Our model uses a limit on the number of waiting requests.
A queue-size limit bounds accepted waiting items in this model. It does not guarantee their waiting time, because service durations and arrivals can still vary.
waiting limit = 2 requests
already waiting = [Q1]
new arrivals = [Q2,Q3]
queue after admission = [Q1,Q2]
explicitly rejected arrivals = [Q3]A refusal is observable work the service did not accept. Do not remove it from load reports and call the remainder the whole workload.
Check yourself
Questions on Parts 1 to 2
Question 1 of 2
Does that row still own its reservation in this model?
Use the information below.
A worker row has state=cancel_requested and reserves three blocks. No release acknowledgement arrived.3. Cancelling a stream does not cancel an earlier external effect
If an agent already submitted an inspection booking, ending text generation cannot unsend that booking. A timed-out reply might also conceal a committed tool result. Keep effect outcomes and inference-resource cleanup as different records.
A booking tool needs an identifier for the intended operation so that a retry can be recognised instead of making another booking. If the result is uncertain, the caller needs a way to check what happened. Those are the effect-handling problems from the earlier agent lessons. This workshop confines itself to resource ownership and the waiting queue.
A successful cancellation acknowledgement here says nothing about whether a previous tool write occurred.
4. Use deadlines without restarting the timer
A queued request can become useless before it reaches a worker. Propagate the original overall deadline, preserve response time, and avoid launching work when no useful allowance remains. An immediate retry loop after a capacity refusal can make overload worse.
An upstream producer needs a bounded retry policy appropriate to the operation, and a user may need a clear busy or cancelled outcome. The earlier deadline calculator supplies one component; it is not a complete queue scheduler.
The deadline answers when work stops being useful; the queue limit answers how much waiting work we accept.
5. Test cancellation while the system is already full
Exercise cancellation before dispatch, during decoding and after ordinary completion. Check that cleanup happens once, that retained work remains counted, and that later requests do not inherit another request’s cache state.
Measure abandoned requests and confirmed releases separately. If they differ, the service may still be doing work no caller wants. The simulation cannot establish how promptly a deployed worker actually cleans up.
Inspect the release event beside its request ID so slow cleanup remains visible.
Check yourself
Questions on Parts 1 to 5
Question 1 of 3
What belongs in the rejected-arrival list?
Use the information below.
Queue limit2, existing[Q1], incoming[Q2,Q3].Try it with Botie
Build with Botie
Write and run Python