← All tutorials

Track 12 · State & Control

Execute a plan you already have

Pass plan text to agent.execute, validation and all. The plan can come from the model, a file, or your own hand. Execution validates before anything runs.

Intermediate5 min
Video coming soon
Project codeBrowse this tutorial's folder in tutorials-pygithub.com/OpenSymbolicAI/tutorials-py/tree/main/12-execute-a-plan

Track 11 ran a plan the model wrote. But agent.execute(plan) does not care where the plan came from. A plan is just text, and execute will run any plan text you hand it: one you wrote by hand, one loaded from a file, one a teammate edited. The model is never called. And before it runs a single line, execute validates the plan.

Run a plan you wrote

Write the plan as a plain string and pass it to execute.

python
# main.py
PLAN = """cart = new_cart()
cart = add_item(cart, "pens", 5, 3)
cart = add_item(cart, "notebook", 8, 1)
total = cart_total(cart)"""

result = agent.execute(PLAN)  # ExecutionResult
print(result.get_value())     # 23.0
bash
uv run main.py

Output:

text
cart = new_cart()
cart = add_item(cart, "pens", 5, 3)
cart = add_item(cart, "notebook", 8, 1)
total = cart_total(cart)
23.0

No model wrote that plan and no model ran it. You wrote four lines of Python, execute ran them against your primitives, and result.get_value() is the 23.0 they produced: 3 pens at 5 plus 1 notebook at 8. The ExecutionResult you get back is the same kind of object from Track 9, trace and all.

execute validates first

Running arbitrary text sounds risky, so execute checks the plan before it runs it. The rule is narrow: a plan may only be assignment statements that call your primitives, plus a few safe builtins. Anything else raises a ValueError and nothing runs.

python
BAD_PLANS = {
    "imports a module": 'x = __import__("os")',
    "opens a file": 'x = open("/etc/passwd")',
    "runs a loop": "for i in range(3):\n    x = i",
    "reaches a dunder": "x = cart_total.__globals__",
}

for label, bad in BAD_PLANS.items():
    try:
        agent.execute(bad)
    except ValueError as e:
        print(f"{label}: {e}")

Output:

text
imports a module: Calling '__import__' is not allowed
opens a file: Calling 'open' is not allowed
runs a loop: For statements are not allowed in plans
reaches a dunder: Accessing private/dunder attributes not allowed: __globals__

No imports, no file access, no loops, no private or dunder attributes, and no calls to anything that is not one of your primitives.

Plan, review, run

This is what makes a plan worth holding as data. It can come from anywhere: the model, a file, a queue, a person. You read it, edit it, or store it, and run it later with execute. Whatever review you put in front, the validation is the backstop underneath: even an approved-looking plan cannot reach past your primitives.