re-appraise turn limits / context limits / timeouts once wednesday => thursday merge train settles down #362

Open
opened 2026-08-13 11:03:39 +00:00 by coilysiren · 4 comments
Owner

the limits were written for a much less mature system. abstractly, I imagine that once the issue tracker hits ~50 open, we'll be able to double a bunch of the limits. more stability => more functionality.

the limits were written for a much less mature system. abstractly, I imagine that once the issue tracker hits ~50 open, we'll be able to double a bunch of the limits. more stability => more functionality.
Author
Owner

see also => #360 (comment)

see also => https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/360#issue-8293
Member

Quail. Measured numbers for when you come back to this, so the re-appraisal starts from observed behaviour rather than from the abstraction.

The current ladder, and what production does against it

limit                     value     observed
queue / admission          30s      agent-proxy queue.wait p95 = 34.1s
request timeout             3m       Echo model.chat p99 = 114.5s (64% of it)
max_context_messages        12       both lanes
HTTP body                 64 KiB     12 history entries of 6000 chars = 72 KiB

One of these is already wrong, today

The admission timeout is below the p95 wait it governs. That is not a limit waiting to be relaxed as things stabilise — it is actively dropping turns now: 49 in 24h, at a median of 30.003s, 35 of which never composed a reply. A member asks and gets silence. Full trace on #292.

So the first move is not doubling. It is that one number being set under its own workload.

Why doubling alone would not fix it

Echo's model p50 is 5.4s and her p99 is 114.5s — a 21x spread, which is contention rather than slowness. Doubling admission to 60s still sits far under that tail, so it converts some silent drops into longer waits and leaves the rest dropping.

The spread is the thing to fix. Deep, on the cloud route, runs 4.3s / 20.5s — a 4.8x spread — and does not have this problem. Root cause chain on #315.

More stability does enable more functionality, exactly as you say. The order matters: the tail first, then the limits. Raising limits against a 21x spread buys latency rather than reliability.

Your trigger condition has arrived

once the issue tracker hits ~50 open

It is at 50 open in sirens-echo and 50 in deploy as I write this. Worth knowing, since the number was the trigger and it has been sitting there a while.

One that is safe to raise independently

The 64 KiB HTTP body is unrelated to the substrate and already bites: 12 history entries is within max_context_messages: 12 and each under the rune cap, yet the request is rejected as malformed JSON. A caller obeying every documented limit gets an error. #157.

Not claiming any of it. Numbers are reproducible from SigNoz.

Quail. Measured numbers for when you come back to this, so the re-appraisal starts from observed behaviour rather than from the abstraction. ## The current ladder, and what production does against it ``` limit value observed queue / admission 30s agent-proxy queue.wait p95 = 34.1s request timeout 3m Echo model.chat p99 = 114.5s (64% of it) max_context_messages 12 both lanes HTTP body 64 KiB 12 history entries of 6000 chars = 72 KiB ``` ## One of these is already wrong, today The admission timeout is **below** the p95 wait it governs. That is not a limit waiting to be relaxed as things stabilise — it is actively dropping turns now: 49 in 24h, at a median of 30.003s, 35 of which never composed a reply. A member asks and gets silence. Full trace on https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/292. So the first move is not doubling. It is that one number being set under its own workload. ## Why doubling alone would not fix it Echo's model p50 is 5.4s and her p99 is 114.5s — a 21x spread, which is contention rather than slowness. Doubling admission to 60s still sits far under that tail, so it converts some silent drops into longer waits and leaves the rest dropping. The spread is the thing to fix. Deep, on the cloud route, runs 4.3s / 20.5s — a 4.8x spread — and does not have this problem. Root cause chain on https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/315. **More stability does enable more functionality, exactly as you say. The order matters: the tail first, then the limits.** Raising limits against a 21x spread buys latency rather than reliability. ## Your trigger condition has arrived > once the issue tracker hits ~50 open It is at 50 open in sirens-echo and 50 in deploy as I write this. Worth knowing, since the number was the trigger and it has been sitting there a while. ## One that is safe to raise independently The 64 KiB HTTP body is unrelated to the substrate and already bites: **12 history entries is within `max_context_messages: 12`** and each under the rune cap, yet the request is rejected as malformed JSON. A caller obeying every documented limit gets an error. https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/157. Not claiming any of it. Numbers are reproducible from SigNoz.
Member

Your trigger condition is met, and here is which limits actually bind. Angie (ENG), seat claude. Read-only observability, nothing touched. Not claiming: this is a decision.

abstractly, I imagine that once the issue tracker hits ~50 open, we will be able to double a bunch of the limits

The tracker is at 50 open right now. So the condition you named is satisfied, and the useful next thing is knowing which limits doubling would actually move.

Measured, 24h, both lanes

turn.input.accepted     366   (echo 183, deep 183)
turn.input.denied        13   (deep 8, echo 5)      3.4% of offered load
turn.reply.ready        377
model.response.repair    39   (echo 34, deep 5)
model.budget.raised       0
ran out of steps          0   (no turn reached maxToolRounds)
Limit Value Doubling it would change
maxToolRounds 6 nothing measurable - no turn reached it
budgetRaisesAllowed 1 nothing measurable - no turn raised once
maxResponseRepairs 1 39 turns/day, the only one that runs
MaxPending 8 13 turns/day, down from 120

The admission number has already moved, and not by anything on this issue

#532 measured 120 denials in 709 decisions, 17%. It is now 13 in 379, 3.4% — a fivefold drop. A Flux commit in the window reads deploy(sirens-echo): flatten every admission tier, so Ops changed the tiers today. 532 argues about whether 8 is the right MaxPending; that argument is now against different numbers than it was written against.

What I refused to measure, and it is the interesting refusal

turn.reply.delivered returned 5 against 377 replies ready, which looks like a delivery catastrophe and is not one. That event landed in 2d23903 at 18:19:46Z, and the running Echo pod started 17:48:24Z31 minutes earlier. The five come only from pods rolled after the commit. Comparing them to 377 would have manufactured a #292-shaped emergency out of an instrument that is not deployed yet.

Every zero above was checked the same way. turn.input.denied landed 2026-08-10, model.budget.raised 2026-08-11, both before every pod in the window, so those numbers are real.

What I am not doing

Recommending which to double. Three of the four would be a no-op today and one is the number #669 flags as changing what the service does rather than how big it is. That is still yours.

**Your trigger condition is met, and here is which limits actually bind. Angie (ENG), seat `claude`. Read-only observability, nothing touched. Not claiming: this is a decision.** > abstractly, I imagine that once the issue tracker hits ~50 open, we will be able to double a bunch of the limits **The tracker is at 50 open right now.** So the condition you named is satisfied, and the useful next thing is knowing which limits doubling would actually move. ## Measured, 24h, both lanes ``` turn.input.accepted 366 (echo 183, deep 183) turn.input.denied 13 (deep 8, echo 5) 3.4% of offered load turn.reply.ready 377 model.response.repair 39 (echo 34, deep 5) model.budget.raised 0 ran out of steps 0 (no turn reached maxToolRounds) ``` | Limit | Value | Doubling it would change | | --- | --- | --- | | `maxToolRounds` | 6 | **nothing measurable** - no turn reached it | | `budgetRaisesAllowed` | 1 | **nothing measurable** - no turn raised once | | `maxResponseRepairs` | 1 | 39 turns/day, the only one that runs | | `MaxPending` | 8 | 13 turns/day, down from 120 | ## The admission number has already moved, and not by anything on this issue https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/532 measured **120 denials in 709 decisions, 17%**. It is now **13 in 379, 3.4%** — a fivefold drop. A Flux commit in the window reads `deploy(sirens-echo): flatten every admission tier`, so Ops changed the tiers today. 532 argues about whether 8 is the right `MaxPending`; that argument is now against different numbers than it was written against. ## What I refused to measure, and it is the interesting refusal `turn.reply.delivered` returned **5** against 377 replies ready, which looks like a delivery catastrophe and is not one. That event landed in `2d23903` at **18:19:46Z**, and the running Echo pod started **17:48:24Z** — **31 minutes earlier**. The five come only from pods rolled after the commit. Comparing them to 377 would have manufactured a https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/292-shaped emergency out of an instrument that is not deployed yet. Every zero above was checked the same way. `turn.input.denied` landed `2026-08-10`, `model.budget.raised` `2026-08-11`, both before every pod in the window, so those numbers are real. ## What I am not doing Recommending which to double. Three of the four would be a no-op today and one is the number https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/669 flags as changing what the service does rather than how big it is. That is still yours.
Member

The re-appraisal has happened, and it is mostly a no - Kai, 2026-08-15

Recorded by Delphi (design seat). Your trigger condition was met, the measurements are in, and the answer is narrower than the ticket imagined.

The ladder does not move. Fix the tail first.

Nothing gets doubled. Not maxToolRounds, not budgetRaisesAllowed, not maxResponseRepairs, not MaxPending.

The measurement is why. Three of the four are no-ops - no turn reached maxToolRounds, no turn raised its budget once, in 366 accepted turns over 24 hours. Doubling a limit nothing reaches changes nothing except the number in a file.

And the one thing that would help is not a limit. Echo's model p50 is 5.4s against a p99 of 114.5s, a 21x spread. Deep on the cloud route runs 4.3s to 20.5s, a 4.8x spread, and does not have this problem. That is contention rather than slowness, and raising limits against a 21x spread buys latency rather than reliability.

So the order is the tail, then the limits. Root cause chain is on #315. This issue waits on that rather than the other way around.

Raising the ladder as originally imagined, raising maxResponseRepairs alone, and bundling the HTTP body limit were all offered and not taken.

One number does move: the admission timeout

Raise it above the observed p95. It is 30s, the p95 queue wait it governs is 34.1s, and it dropped 49 turns in 24 hours at a median of 30.003s, 35 of which never composed a reply. A member asked and got silence.

That is not a limit waiting to be relaxed as things stabilise. It is a number set under its own workload, dropping turns that would otherwise have succeeded, today.

What raising it does and does not buy - it converts some silent drops into longer waits. The p99 of 114.5s still exceeds any sane admission timeout, so this does not close the failure mode. Making a drop always visible to the member is the thing that would, and that is #292's work rather than this one's. Kai chose the raise without the visibility change, so the silent-drop path survives this fix and should not be reported as closed by it.

Ops owns the change. This is a live-system tuning action and I am recording the decision, not taking it. Olaf, the number needs to clear 34.1s with headroom rather than land on it.

Not bundled here, and still worth someone's attention

The 64 KiB HTTP body limit (#157) is unrelated to the substrate and already rejects a caller obeying every documented limit - 12 history entries at the rune cap is 72 KiB, inside max_context_messages: 12. Kai declined to fold it into this pass, so it stays on #157 as its own thing.

Measurement notes worth preserving

  • MaxPending denials fell from 120 in 709 decisions (17%) to 13 in 379 (3.4%) after a Flux commit reading deploy(sirens-echo): flatten every admission tier. #532's argument is now against different numbers than it was written against and should be re-read before it is acted on.
  • turn.reply.delivered reading 5 against 377 replies ready is an instrument that landed 31 minutes after the running pod started, not a delivery catastrophe. Anyone re-running these queries should check event landing dates against pod start before believing a zero.
## The re-appraisal has happened, and it is mostly a no - Kai, 2026-08-15 Recorded by Delphi (design seat). Your trigger condition was met, the measurements are in, and the answer is narrower than the ticket imagined. ### The ladder does not move. Fix the tail first. **Nothing gets doubled.** Not `maxToolRounds`, not `budgetRaisesAllowed`, not `maxResponseRepairs`, not `MaxPending`. The measurement is why. Three of the four are no-ops - no turn reached `maxToolRounds`, no turn raised its budget once, in 366 accepted turns over 24 hours. Doubling a limit nothing reaches changes nothing except the number in a file. And the one thing that would help is not a limit. **Echo's model p50 is 5.4s against a p99 of 114.5s, a 21x spread.** Deep on the cloud route runs 4.3s to 20.5s, a 4.8x spread, and does not have this problem. That is contention rather than slowness, and raising limits against a 21x spread buys latency rather than reliability. **So the order is the tail, then the limits.** Root cause chain is on #315. This issue waits on that rather than the other way around. Raising the ladder as originally imagined, raising `maxResponseRepairs` alone, and bundling the HTTP body limit were all offered and not taken. ### One number does move: the admission timeout **Raise it above the observed p95.** It is 30s, the p95 queue wait it governs is 34.1s, and it dropped **49 turns in 24 hours at a median of 30.003s, 35 of which never composed a reply.** A member asked and got silence. That is not a limit waiting to be relaxed as things stabilise. It is a number set under its own workload, dropping turns that would otherwise have succeeded, today. **What raising it does and does not buy** - it converts some silent drops into longer waits. The p99 of 114.5s still exceeds any sane admission timeout, so this does not close the failure mode. Making a drop always visible to the member is the thing that would, and that is #292's work rather than this one's. Kai chose the raise without the visibility change, so **the silent-drop path survives this fix** and should not be reported as closed by it. **Ops owns the change.** This is a live-system tuning action and I am recording the decision, not taking it. Olaf, the number needs to clear 34.1s with headroom rather than land on it. ### Not bundled here, and still worth someone's attention The 64 KiB HTTP body limit (#157) is unrelated to the substrate and already rejects a caller obeying every documented limit - 12 history entries at the rune cap is 72 KiB, inside `max_context_messages: 12`. Kai declined to fold it into this pass, so it stays on #157 as its own thing. ### Measurement notes worth preserving * `MaxPending` denials fell from 120 in 709 decisions (17%) to 13 in 379 (3.4%) after a Flux commit reading `deploy(sirens-echo): flatten every admission tier`. **#532's argument is now against different numbers than it was written against** and should be re-read before it is acted on. * `turn.reply.delivered` reading 5 against 377 replies ready is an instrument that landed 31 minutes after the running pod started, not a delivery catastrophe. Anyone re-running these queries should check event landing dates against pod start before believing a zero.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#362
No description provided.