- Je telt totale kosten, maximale diepte en fan-out van een eindig oefenplan.
- Je stopt vóór overschrijding en houdt het verbruik van de geaccepteerde prefix bij.
Een assistent krijgt één vraag, maar maakt daar twintig vervolgacties van. Ook wanneer iedere losse actie klein is, kan het totaal te groot worden. Een grens per verzoek is daarom iets anders dan een grens voor de hele uitvoering.
We gebruiken een eindig oefenplan met vooraf vertrouwde bovengrenzen voor tokens en uitvoereenheden. Die getallen zijn geen claims van het model en geen echte factuur of tokenizermeting. Er wordt niets uitgevoerd behalve het tellen van eigen gegevens.
1. Kijk naar het hele werk
Stel je een project voor met een hoofdtaak en twee deeltaken. Kosten stapelen op; nesting vergroot de diepte en meerdere kinderen van dezelfde ouder vergroten de vertakking, ook wel fan-out. Diepte en breedte kunnen dus verschillende problemen veroorzaken.
Iedere planregel heeft een id, een eerdere ouder of None, en twee kostentellers. Een root heeft diepte één. In deze oefening delen alle roots de virtuele ouder None, zodat ook meerdere losse hoofdtaken meetellen bij fan-out.
U is het totale gebruik van één soort eenheid. We tellen de bijdrage u van iedere stap i op; n is het aantal stappen. Dezelfde optelling geldt afzonderlijk voor tokens en output; aantal stappen, maximale diepte en maximale fan-out bewaren we daarnaast als eigen tellers.
Met de hand kosten de eerste twee stappen twee en drie tokens. Samen is dat vijf, terwijl geen losse stap meer dan drie kost. De tweede stap is kind van de eerste, dus de maximale diepte is twee.
plan = [
dict(id="a", parent=None,
tokens=2, output=1),
dict(id="b", parent="a",
tokens=3, output=2),
]
used = aggregate_usage(plan)
print(used["tokens"])
print(used["max_depth"])
print(used["max_fanout"])
# 5
# 2
# 1
01De limieten gelden voor het hele plan. Een geweigerde stap en alle latere stappen tellen niet mee als verbruik. Exact op de grens mag wel.
Het hele plan zonder grens
- Stappen
- 4
- Oefentokens
- 6
- Uitvoereenheden
- 4
- Maximale diepte
- 3
- Maximale fan-out
- 2
Werkelijk geaccepteerde prefix
- Stappen
- 1
- Oefentokens
- 2
- Uitvoereenheden
- 1
- Maximale diepte
- 1
- Maximale fan-out
- 1
Stap aGeaccepteerd
Bovenliggende stap: None (hoofdtaak)
2 oefentokens · 1 uitvoereenheden
Stap bHier gestopt
Bovenliggende stap: a
3 oefentokens · 0 uitvoereenheden
Stap cNiet bereikt
Bovenliggende stap: a
0 oefentokens · 2 uitvoereenheden
Stap dNiet bereikt
Bovenliggende stap: b
1 oefentokens · 1 uitvoereenheden
Geaccepteerd: a
Gestopt vóór b door tokenlimiet.
Hoofdtaken hebben diepte 1 en delen één virtuele ouder voor fan-out. Ook een gratis stap verbruikt een stap. Kosten zijn vooraf vertrouwde oefenbovengrenzen; geen eigen schatting van een model of echte factuur.
Alle kaarten, rechten, routes en kosten zijn eigen oefengegevens. Deze oefening voert geen externe tools uit en verstuurt geen gegevens.
2. Controleer vóór je accepteert
Een waarschuwing na het werk kan de overschrijding niet terugnemen. Onze begrenzer berekent daarom eerst het voorgenomen gebruik. Alleen als alle grenzen passen, wordt de stap geaccepteerd en worden de tellers bijgewerkt.
Voor één optelteller is U het geaccepteerde gebruik, u de volgende bijdrage en L de limiet. Gelijkheid mag. Voor diepte en fan-out controleer je op dezelfde plek hun eigen voorgenomen waarde, zonder ze met tokenkosten te verwarren.
Met een tokenlimiet van vier past stap a. Stap b zou het totaal vijf maken en wordt dus vooraf gestopt. Haar kosten komen niet in usage en eventuele latere stappen worden ook niet geaccepteerd.
limits = dict(steps=4, tokens=4,
output=10, depth=4,
fanout=4)
answer = bounded_workflow(plan, limits)
print(answer["accepted"])
print(answer["stopped"])
print(answer["reason"])
print(answer["usage"]["tokens"])
# ['a']
# b
# tokens
# 2
02Er zijn vijf verschillende grenzen. Als één volgende stap meerdere grenzen overschrijdt, toont onze oefening eerst steps, daarna tokens, output, depth en fanout. Die vaste redenvolgorde maakt een test reproduceerbaar; zij geeft geen rangorde van alle werkelijke beveiligingsrisico’s.
3. Test de grens en de vorm van het werk
Een veelgemaakte fout is al weigeren wanneer het totaal precies gelijk wordt aan de grens. Verhoog de tokenlimiet naar vijf en beide normale stappen passen. De geaccepteerde uitvoering eindigt dan met complete en heeft geen geweigerde stap.
exact = dict(limits, tokens=5)
done = bounded_workflow(plan, exact)
print(done["reason"])
print(done["stopped"])
print(done["usage"]["tokens"])
# complete
# None
# 5
Een tweede fout is alleen betaalde stappen tellen. Ook een vervolgactie met nul oefenkosten verbruikt één stap en kan nieuwe kinderen voorstellen. Daartegen helpen een stapbudget en aparte diepte- en fan-outgrenzen.
free = [dict(id="z", parent=None,
tokens=0, output=0)]
no_steps = dict(limits, steps=0)
stop = bounded_workflow(free, no_steps)
print(stop["reason"])
print(len(stop["accepted"]))
print(stop["usage"]["tokens"])
# steps
# 0
# 0
Valideer het hele plan, ook de regels na een waarschijnlijke stop. Een toekomstige ouder, een dubbele id of een bool als kostenteller is ongeldige invoer. Die gevallen horen niet stil te verdwijnen omdat de eerste stap toevallig al wordt geweigerd.
De oefenteller onderbreekt geen hangende callback en meet geen werkelijk modelgebruik. In een echt systeem zijn daarnaast van buitenaf afgedwongen uitvoeringstijd, meting en stopcontroles nodig. De bestaande browserworker houdt zijn eigen grenzen; deze les verruimt of vervangt die niet.
Wat je nu kunt
- Je houdt totaalgebruik, diepte en fan-out apart zichtbaar.
- Je weigert vóór de overschrijdende stap en telt alleen het geaccepteerde prefix.
- Je test grensgelijkheid, gratis stappen en behoud van gewoon werk.
Hierna nemen we ook de beschrijvingen en bevoegdheden van MCP-tools onder de loep.
Bronnen
Gecontroleerd op 30 oktober 2026: OWASP 2026 LLM06 over begrensd resourcegebruik en MITRE ATLAS 2026.10, AML.T0034.002 en AML.M0036. Planregels, tellerdefinities en kosten zijn eigen begrensde oefengegevens.