Skip to main content
Iterative execution allows you to pause Monty execution at each external function call, giving you complete control over when and how those functions are executed.

Why Iterative Execution?

Instead of providing all external functions upfront with run(), iterative execution lets you:
  • Inspect function calls before executing them (useful for logging, security, or rate limiting)
  • Handle async operations manually
  • Serialize and resume execution across process boundaries
  • Implement custom execution strategies (e.g., batching, caching)

Basic Flow

Use start() to begin execution and resume() to continue after each external function call:
1

Start execution

2

Inspect the function call

3

Resume with return value

Snapshot Types

Iterative execution returns different types depending on the execution state:

FunctionSnapshot

Returned when execution pauses at an external function call:

MontyComplete

Returned when execution finishes:

FutureSnapshot

Returned when async code is waiting for futures to complete (Python only):

Handling Multiple External Calls

When code makes multiple external function calls, resume each one in sequence:

Loop Pattern for Multiple Calls

Resuming with Exceptions

You can resume with an exception instead of a return value:
If you resume with an exception that isn’t caught by the Monty code, it will propagate to your host code wrapped in a MontyRuntimeError.

Serialization

Both Monty and snapshot types can be serialized to bytes:
Serialization enables powerful patterns like saving execution state to a database and resuming later, or distributing work across multiple processes.

Resume Constraints

A FunctionSnapshot can only be resumed once. Attempting to call resume() twice will raise a RuntimeError.

Name Lookups

In addition to FunctionSnapshot, you may receive a NameLookupSnapshot when code references an undefined variable:
This feature is useful for implementing dynamic variable resolution or lazy imports.

JavaScript Example

Best Practices

  1. Always check types: Use isinstance() (Python) or instanceof (JavaScript) to determine the snapshot type
  2. Handle all paths: Your code should handle both FunctionSnapshot and MontyComplete returns
  3. Log function calls: Iterative execution is perfect for audit logs and debugging
  4. Serialize strategically: Only serialize when needed (e.g., for long-running operations or persistence)
  5. Don’t reuse snapshots: Each snapshot can only be resumed once

Common Patterns

Function Call Logger

Rate Limiting

Next Steps

Async Execution

Learn about async external functions and run_monty_async()

Error Handling

Handle exceptions and errors in Monty code