Track 19·State & Control
max_total_primitive_calls and allow_break_continue
The two remaining DesignExecuteConfig knobs: a whole-plan call cap and a toggle for break/continue in loops.
intermediate8 min
Video coming soon
Browse this tutorial's folder in tutorials-pygithub.com/OpenSymbolicAI/tutorials-py/tree/main/19-design-execute-limitsBefore you start
Track 18 covered max_loop_iterations. DesignExecuteConfig has two more
knobs: max_total_primitive_calls and allow_break_continue.
The agent#
A shopping cart with three primitives:
python
# cart.py
from opensymbolicai.blueprints import DesignExecute
from opensymbolicai.core import primitive
PRICES = {"apple": 0.99, "banana": 0.49, "book": 12.99,
"notebook": 4.99, "pen": 1.49, "stapler": 8.99}
class Cart(DesignExecute):
"""A shopping cart agent."""
@primitive(read_only=True)
def item_total(self, name: str, qty: int) -> float:
"""Price for qty units of name."""
return round(PRICES[name] * qty, 2)
@primitive(read_only=True)
def add(self, a: float, b: float) -> float:
"""Add two amounts."""
return round(a + b, 2)
@primitive(read_only=True)
def format_total(self, total: float) -> str:
"""Format the grand total as a receipt line."""
return f"Total: ${total:.2f}"max_total_primitive_calls#
A cap on every primitive call in the plan, across all loops and branches.
The default is 1000. The five-item loop plan makes 11 calls total
(two per item, plus one format_total).
python
from opensymbolicai.models import DesignExecuteConfig
# Trips on the 4th call.
config = DesignExecuteConfig(max_total_primitive_calls=3)
agent = Cart(llm=llm, config=config)
result = agent.execute(LOOP_PLAN)
last = result.trace.steps[-1]
print(f"calls made before stop: {len(result.trace.steps)}")
print(f"error: {last.error}")
# All 11 calls fit.
config = DesignExecuteConfig(max_total_primitive_calls=15)
agent = Cart(llm=llm, config=config)
result = agent.execute(LOOP_PLAN)
print(f"calls made: {len(result.trace.steps)}")
print(f"result: {result.get_value()}")text
calls made before stop: 4
error: Exceeded maximum total primitive calls (3). Plan may contain too many iterations.
calls made: 11
result: Total: $56.88allow_break_continue#
Controls whether break and continue are legal in plans. The default is
True. Set False to reject any plan that contains them at validation time,
before a single primitive runs.
python
BREAK_PLAN = """\
total = 0.0
items = [('stapler', 1), ('pen', 2), ('notebook', 3)]
for name, qty in items:
line = item_total(name, qty)
total = add(total, line)
if total > 10:
break
return format_total(total)
"""
# True (default): break is allowed; loop stops early once total > $10.
config = DesignExecuteConfig(allow_break_continue=True)
agent = Cart(llm=llm, config=config)
result = agent.execute(BREAK_PLAN)
print(f"calls made: {len(result.trace.steps)}")
print(f"result: {result.get_value()}")
# False: validate_plan rejects the plan before any primitive runs.
config = DesignExecuteConfig(allow_break_continue=False)
agent = Cart(llm=llm, config=config)
try:
agent.validate_plan(BREAK_PLAN)
except ValueError as e:
print(f"allow_break_continue=False: {e}")text
calls made: 5
result: Total: $11.97
allow_break_continue=False: Break statements are not allowed in plans