Run a Python workflow ``source`` to completion. Raises :class:`WorkflowMetaError` if the ``meta`` block is missing/invalid (pre-flight). A script *runtime* exception is captured into ``WorkflowResult.error`` and ends the run gracefully.
(
source: str,
*,
runner: AgentRunner,
args: Any = None,
run_id: str = "wf",
on_progress: Optional[Callable[[WorkflowProgress], None]] = None,
on_start: Optional[Callable[["WorkflowRun"], None]] = None,
resume: Optional[Mapping[CallKey, JournalRecord]] = None,
resolve_workflow: Optional[Callable[[str], str]] = None,
budget_total: Optional[int] = None,
max_concurrent: Optional[int] = None,
controller: Optional[AbortController] = None,
scheduler: Optional[Scheduler] = None,
budget: Optional[Budget] = None,
base_path: CallKey = (),
_depth: int = 0,
)
| 314 | |
| 315 | |
| 316 | async def run_workflow( |
| 317 | source: str, |
| 318 | *, |
| 319 | runner: AgentRunner, |
| 320 | args: Any = None, |
| 321 | run_id: str = "wf", |
| 322 | on_progress: Optional[Callable[[WorkflowProgress], None]] = None, |
| 323 | on_start: Optional[Callable[["WorkflowRun"], None]] = None, |
| 324 | resume: Optional[Mapping[CallKey, JournalRecord]] = None, |
| 325 | resolve_workflow: Optional[Callable[[str], str]] = None, |
| 326 | budget_total: Optional[int] = None, |
| 327 | max_concurrent: Optional[int] = None, |
| 328 | controller: Optional[AbortController] = None, |
| 329 | scheduler: Optional[Scheduler] = None, |
| 330 | budget: Optional[Budget] = None, |
| 331 | base_path: CallKey = (), |
| 332 | _depth: int = 0, |
| 333 | ) -> WorkflowResult: |
| 334 | """Run a Python workflow ``source`` to completion. |
| 335 | |
| 336 | Raises :class:`WorkflowMetaError` if the ``meta`` block is missing/invalid |
| 337 | (pre-flight). A script *runtime* exception is captured into |
| 338 | ``WorkflowResult.error`` and ends the run gracefully. |
| 339 | """ |
| 340 | meta = extract_meta(source) |
| 341 | |
| 342 | scheduler = scheduler if scheduler is not None else Scheduler(max_concurrent) |
| 343 | budget = budget if budget is not None else Budget(budget_total) |
| 344 | journal = Journal(resume) |
| 345 | progress = WorkflowProgress(meta.phases, on_change=on_progress) |
| 346 | controller = controller if controller is not None else create_abort_controller() |
| 347 | |
| 348 | run = WorkflowRun( |
| 349 | meta=meta, |
| 350 | runner=runner, |
| 351 | args=args, |
| 352 | run_id=run_id, |
| 353 | scheduler=scheduler, |
| 354 | budget=budget, |
| 355 | journal=journal, |
| 356 | progress=progress, |
| 357 | controller=controller, |
| 358 | base_path=base_path, |
| 359 | resolve_workflow=resolve_workflow, |
| 360 | depth=_depth, |
| 361 | ) |
| 362 | |
| 363 | if on_start is not None: |
| 364 | on_start(run) # e.g. register the background task with the live run |
| 365 | |
| 366 | # Establish this run's base branch for deterministic call-path keys, and |
| 367 | # restore the caller's branch afterwards (matters for nested workflow()). |
| 368 | token = use_branch(base_path) |
| 369 | value: Any = None |
| 370 | error: Optional[str] = None |
| 371 | try: |
| 372 | value = await execute_workflow(source, run.namespace(), args) |
| 373 | except WorkflowMetaError: |