4.1 KiB
Python Source Provider
Date: 2026-06-11
Status: first static config slice implemented
Related:
- Runtime source lifecycle
- Workflow config targets and sources
- Long-lived workflow API boundary
- Project map
Purpose
wf_sources_python should prove that workflow sources are not MCP-shaped. It is
not a replacement for wf_authoring; it is the provider package that loads
project-local Python capabilities and projects them into WorkflowApi as
ordinary CapabilitySource and executable NodeSpec objects.
Boundary
wf_authoring
owns authoring primitives:
@node
NodeSpec
build_registry / build_async_registry
reducers
WorkflowBuilder
wf_sources_python
owns source-provider glue:
config entry interpretation
module/object loading
validation of exported specs
source qualification
CapabilitySource projection
wf_server
owns composition:
read wf_config
select provider by source kind
merge provider sources with built-ins
So wf_sources_python acts more like wf_sources_mcp than wf_authoring.
wf_authoring creates specs; wf_sources_python imports and exposes specs from
user code.
First Slice
Start with static config only:
{
"kind": "python",
"id": "local.ops",
"path": ".",
"module": "my_project.workflow_ops",
"registry": "registry"
}
The loaded object may be:
- a mapping of local name to
NodeSpec - a sequence of
NodeSpec - a callable returning either of the above
The provider qualifies local specs under the configured source id. A local spec
named echo becomes local.ops.echo. A spec already named
authoring.echo should become local.ops.echo, matching built-in source
qualification behavior.
Non-Goals For First Slice
- No source registry mutation/apply support.
- No hot reload on every call.
- No subprocess sandbox.
- No package installation or dependency management.
- No move of
wf.stdorwf.recipes. - No reducer loading until a concrete use case needs it.
- No OpenAPI/HTTP source behavior.
Error Policy
Configuration and import errors should fail server construction clearly:
- module cannot be imported
- registry object is missing
- registry object is not a supported shape
- exported value is not a
NodeSpec - duplicate local spec names inside one Python source
Runtime errors from Python node execution are ordinary workflow node failures, not source-load failures.
Why Not Move wf.recipes
wf.recipes is first-party built-in workflow content. It belongs with local
sources because it is always available and versioned with the platform.
wf_sources_python is for user/project-defined source entries configured by a
server operator. It should be optional and explicit.
Later Slices
After static config works:
- Add source registry/apply support for Python source entries.
- Consider explicit development reload.
- Consider reducer exports if a real project source needs custom reducers.
- Consider isolation policy for untrusted Python. The first version is trusted in-process code only.
Implementation Status
Implemented:
wf_configacceptsserver.sources[]entries withkind: "python".wf_sources_pythonloads trusted in-processNodeSpecregistries frompathplusmodule:registry.wf_sources_python.PythonSourceProviderimplements the staticWorkflowSourceProvider.load_sources()seam used bywf_server.config.wf config validateimports configured trusted Python sources and reports missing modules, missing registries, invalid registry shapes, and duplicate specs before server startup.- Capability listing/calling works over JSON-RPC.
- JSON-RPC integration coverage now proves a Python source capability can be converted into a draft artifact, deployed with required source bindings, and run as a workflow.
Still deferred:
- mutable source registry/apply support
- hot reload
- reducer exports
- sandboxing/untrusted code