MCPcopy Create free account
hub / github.com/agentforce314/clawcodex / make_workflow_tool

Function make_workflow_tool

src/tool_system/tools/workflow.py:131–203  ·  view source on GitHub ↗
(
    registry: Any,
    provider: Any = None,
    *,
    runner_factory: Optional[Callable[[ToolContext, str], Any]] = None,
)

Source from the content-addressed store, hash-verified

129
130
131def make_workflow_tool(
132 registry: Any,
133 provider: Any = None,
134 *,
135 runner_factory: Optional[Callable[[ToolContext, str], Any]] = None,
136) -> Tool:
137 factory = runner_factory or _default_runner_factory(registry, provider)
138
139 async def _call(tool_input: dict, context: ToolContext) -> ToolResult:
140 if not is_workflows_enabled():
141 return ToolResult(name=WORKFLOW_TOOL_NAME, output={"error": "dynamic workflows are disabled"}, is_error=True)
142
143 source, error = _resolve_source(tool_input, context.cwd)
144 if source is None:
145 return ToolResult(name=WORKFLOW_TOOL_NAME, output={"error": error}, is_error=True)
146
147 run_id = "wf_" + uuid.uuid4().hex[:12]
148 task_id = generate_task_id("local_workflow")
149 from src.agent.transcript import get_workflow_run_path
150
151 output_file = get_workflow_run_path(run_id)
152 runner = factory(context, run_id)
153
154 # Same-session resume: replay the prior run's journal if asked.
155 resume = None
156 prior_run_id = tool_input.get("resume_from_run_id")
157 if isinstance(prior_run_id, str) and prior_run_id.strip():
158 from src.workflow.launch import load_journal
159
160 try:
161 resume = load_journal(get_workflow_run_path(prior_run_id))
162 except ValueError:
163 resume = None # malformed run id
164
165 coro = run_workflow_task(
166 source=source,
167 runner=runner,
168 registry=context.runtime_tasks,
169 task_id=task_id,
170 run_id=run_id,
171 output_file=output_file,
172 args=tool_input.get("args"),
173 resume=resume,
174 tool_use_id=context.agent_id,
175 )
176
177 # Launch on a dedicated daemon thread that owns the run to completion.
178 # The production dispatch path executes this tool's ``call`` inside a
179 # throwaway ``asyncio.run`` loop (on a worker thread), so scheduling on
180 # the *current* loop would be torn down the instant we return the handle
181 # — the background run must outlive this call. ``task_manager.start``
182 # invokes ``target(stop_event)``, hence the ``_stop`` parameter.
183 context.task_manager.start(
184 name=f"workflow:{run_id}",
185 target=lambda _stop: asyncio.run(coro),
186 )
187
188 return ToolResult(

Calls 2

_default_runner_factoryFunction · 0.85
build_toolFunction · 0.85