This guide documents the Python DSL workflow extension path used by FlowCompile. A workflow should be a structured graph of reusable agents and tools; evaluation and scoring belong in benchmarks, not in the workflow definition.
Add a package under:
src/flowcompile/workflows/<workflow_name>/
Typical contents:
workflow.py for the DSL workflow definitionagents.py for custom SubAgent implementations when needed__init__.py to re-export the workflow classThe repository includes a template package under src/flowcompile/workflows/template/.
If you add custom agents, subclass SubAgent and implement run(...) ->
AgentResult. Let SubAgent.execute record metadata such as token counts,
raw prompts, raw outputs, processed outputs, timestamps, and status.
A typical DSL workflow subclasses WorkflowModule and defines a
forward(query) method:
from flowcompile.dsl.torchlike import WorkflowModule, AgentNode, ToolNode
class MyWorkflowDSL(WorkflowModule):
workflow_type = "myworkflow"
def __init__(self):
super().__init__(name="myworkflow_dsl", execution_mode="sequential")
self.solver = AgentNode("solver")
self.extract = ToolNode("extract", impl="extract_answer")
def forward(self, query):
problem = query["problem"]
solution = self.solver(problem=problem)
answer = self.extract(solution=solution)
return {
"final_answer": answer,
"full_solution": solution,
"final_solution": solution,
}
range(...) loops are unrolled
during capture, and loop-break patterns of the form if <cond>: break are
supported for tool-output fields such as test_passed.query object.AgentNode names. The node name is the key used by profiling
data, compiled runtime configs, and structure IDs.final_answerfull_solutionfinal_solutionexecution_mode="sequential" unless the runtime adds explicit support for more modes.metric_agents, profiling_agents,
runtime_agent_map, or subagent_aliases; the current implementation
expects canonical agent names.Update src/flowcompile/workflows/dsl_registry.py so the new workflow_type resolves to your DSL class.
The current flat CLI schema accepts the built-in workflow types math,
gsm8k, hotpotqa, and livecodebench. A genuinely new workflow type also
requires updating the CLI validator in src/flowcompile/core/cli.py and the
runtime support paths that dispatch by workflow type.
WorkflowModule.backward(payload) defaults to the auto-backward proxy in
flowcompile.dsl.auto_backward. It composes profiled sub-agent accuracy
and latency according to the captured graph and inferred structure.
Only implement a custom backward(payload) when the workflow uses conditional
logic or composition rules that auto-backward does not support. Custom backward
implementations receive:
payload["structure"]: the selected structure dictionary.payload["metrics"]: per-agent metric DataFrames with setting,
accuracy, and latency.If the new workflow changes expected inputs or outputs, update the relevant
helpers in src/flowcompile/dsl/runtime.py:
_preprocess_query_build_trace_*These functions control how raw dataset rows become DSL inputs and how runtime execution writes trace entries.
If useful, export the new DSL class from the package __init__.py for convenient imports.
Validate that:
python - <<'PY'
from flowcompile.workflows.dsl_registry import get_workflow_module
workflow = get_workflow_module("myworkflow")
for structure in workflow.enumerate_structures():
print(structure["structure_id"], structure["active_agent_counts"])
PY
The workflow registry helpers are documented in the curated API page for flowcompile.workflows.