Run a workflow YAML and return the end-node message plus metadata.
(
yaml_file: Union[str, Path],
*,
task_prompt: str,
attachments: Optional[Sequence[Union[str, Path]]] = None,
session_name: Optional[str] = None,
fn_module: Optional[str] = None,
variables: Optional[Dict[str, Any]] = None,
log_level: Optional[Union[LogLevel, str]] = None,
)
| 72 | |
| 73 | |
| 74 | def run_workflow( |
| 75 | yaml_file: Union[str, Path], |
| 76 | *, |
| 77 | task_prompt: str, |
| 78 | attachments: Optional[Sequence[Union[str, Path]]] = None, |
| 79 | session_name: Optional[str] = None, |
| 80 | fn_module: Optional[str] = None, |
| 81 | variables: Optional[Dict[str, Any]] = None, |
| 82 | log_level: Optional[Union[LogLevel, str]] = None, |
| 83 | ) -> WorkflowRunResult: |
| 84 | """Run a workflow YAML and return the end-node message plus metadata.""" |
| 85 | ensure_schema_registry_populated() |
| 86 | |
| 87 | yaml_path = _resolve_yaml_path(yaml_file) |
| 88 | if not yaml_path.exists(): |
| 89 | raise FileNotFoundError(f"YAML file not found: {yaml_path}") |
| 90 | |
| 91 | attachments = attachments or [] |
| 92 | if (not task_prompt or not task_prompt.strip()) and not attachments: |
| 93 | raise ValidationError( |
| 94 | "Task prompt cannot be empty", |
| 95 | details={"task_prompt_provided": bool(task_prompt)}, |
| 96 | ) |
| 97 | |
| 98 | design = load_config(yaml_path, fn_module=fn_module, vars_override=variables) |
| 99 | normalized_session = _normalize_session_name(yaml_path, session_name) |
| 100 | |
| 101 | graph_config = GraphConfig.from_definition( |
| 102 | design.graph, |
| 103 | name=normalized_session, |
| 104 | output_root=OUTPUT_ROOT, |
| 105 | source_path=str(yaml_path), |
| 106 | vars=design.vars, |
| 107 | ) |
| 108 | |
| 109 | if log_level: |
| 110 | resolved_level = LogLevel(log_level) if isinstance(log_level, str) else log_level |
| 111 | graph_config.log_level = resolved_level |
| 112 | graph_config.definition.log_level = resolved_level |
| 113 | |
| 114 | graph_context = GraphContext(config=graph_config) |
| 115 | task_input = _build_task_input(graph_context, task_prompt, attachments) |
| 116 | |
| 117 | executor = GraphExecutor.execute_graph(graph_context, task_input) |
| 118 | final_message = executor.get_final_output_message() |
| 119 | |
| 120 | logger = executor.log_manager.get_logger() if executor.log_manager else None |
| 121 | log_id = logger.workflow_id if logger else None |
| 122 | token_usage = executor.token_tracker.get_token_usage() if executor.token_tracker else None |
| 123 | |
| 124 | meta_info = WorkflowMetaInfo( |
| 125 | session_name=normalized_session, |
| 126 | yaml_file=str(yaml_path), |
| 127 | log_id=log_id, |
| 128 | outputs=executor.outputs, |
| 129 | token_usage=token_usage, |
| 130 | output_dir=graph_context.directory, |
| 131 | ) |
nothing calls this directly
no test coverage detected