Files
lda-wf/docs/add/architecture.md
T

9.6 KiB

title, subtitle, author, date, lang, documentclass, papersize, fontsize, toc, toc-depth, numbersections, geometry, mainfont, sansfont, monofont, mathfont, colorlinks, linkcolor, urlcolor, toccolor, keywords, header-includes, diagram
title subtitle author date lang documentclass papersize fontsize toc toc-depth numbersections geometry mainfont sansfont monofont mathfont colorlinks linkcolor urlcolor toccolor keywords header-includes diagram
lda.chat wf Workflow Platform Architecture and Demo draft 2026-06-12 en-US report a4 10pt true 2 true
top=30mm
bottom=30mm
left=32mm
right=32mm
Libertinus Serif Libertinus Sans Libertinus Mono Libertinus Math true MidnightBlue MidnightBlue MidnightBlue
workflow
agents
JSON-RPC
MCP
Python sources
\usepackage{graphicx}
\usepackage{booktabs}
\usepackage{hyperref}
\usepackage{hyperxmp}
\usepackage[dvipsnames]{xcolor}
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhead[L]{\small wf platform}
\fancyhead[R]{\small\leftmark}
\fancyfoot[C]{\thepage}
\setlength{\parskip}{0.6em}
\setlength{\parindent}{0pt}
\setkeys{Gin}{width=\linewidth,height=0.55\textheight,keepaspectratio}
\renewcommand{\arraystretch}{1.3}
\hypersetup{pdfauthor={lda.chat}, pdftitle={lda.chat wf Workflow Platform Architecture and Demo}}
engine
mermaid
theme
neutral

Workflow Platform Presentation

This is a compact presentation narrative for the current product shape. It is not a full architecture reference; use the linked docs for implementation detail.

One-Sentence Thesis

LLMs should plan typed workflows, while a deterministic runtime executes those workflows against explicit, validated capability sources.

The Problem

Agents are good at deciding what should happen next, but bad at being the thing that directly owns side effects, retries, durable state, and schema contracts.

The platform separates those jobs:

  • The LLM or human author chooses and edits workflow structure.
  • The workflow runtime executes a typed graph.
  • Source providers expose callable capabilities.
  • Stores persist artifacts, deployments, and stopped runs.
  • Transports let CLI, future UI, and other clients talk to the same server.

Current Product Path

wf CLI
  -> JSON-RPC transport
  -> WorkflowServer
  -> WorkflowApi
  -> wf_core runtime + wf_artifacts stores + wf_sources_* providers

The preferred server entrypoint is:

uv run wf-rpc-server --config wf.config.json

The preferred client entrypoint is:

uv run wf --config wf.config.json status

wf-mcp still exists for legacy/special-purpose MCP-facing work, but the durable product path is now wf-rpc-server plus wf.

Core Model

A workflow is a typed graph:

  • input_schema validates run input.
  • state_schema defines workflow memory and reducer behavior.
  • output_schema defines the final result contract.
  • Nodes do real work through NodeSpec handlers.
  • Edges route by declared outcomes.
  • Deployments bind logical source requirements to concrete sources.

The runtime does not know whether a node came from MCP, Python, OpenAPI, or a built-in package. It resolves a NodeSpec, validates payloads, executes, records trace, and commits reducer-aware state changes.

Platform sources such as wf.std and wf.source are process-provided sources. They can appear in artifacts and runs without deployment self-bindings like wf.std=wf.std. Deployment validation rejects explicit platform-source bindings as stale configuration. Configured sources such as local.ops or everything.default still use deployment bindings when a workflow needs portability across accounts or workspaces.

Source Model

The common provider output is CapabilitySource.

source provider
  -> CapabilitySource
  -> WorkflowSpecProvider
  -> WorkflowApi

Current source families:

Source Kind Role
wf.std system built-in standard workflow nodes and reducers
wf.recipes system first-party workflow recipes
MCP sources connection upstream MCP tools/resources/prompts via persistent sessions
Python sources python trusted project-local NodeSpec registries

The first explicit provider seam is intentionally small:

class WorkflowSourceProvider(Protocol):
    def load_sources(self) -> Mapping[str, CapabilitySource]: ...

This seam is for static source inventory. MCP also has runtime pools, auth/catalog stores, admin/apply behavior, and live checks, so it should not be forced into a tiny static interface too early.

Source inventory is broader than workflow-callable nodes. Sources may own tools, workflow capabilities, resources, and prompts. Current CLI smoke paths can list resource and prompt names with wf source resources and wf source prompts without fetching resource bodies or rendering prompt templates.

Resource refs are pass-by-value data using a logical source plus provider URI. wf.source.read_resource is the explicit helper that dereferences such refs through runtime/platform context and bounded output policy. Prompt rendering is intentionally not a workflow helper yet; keep it at inventory/inspection level until there is a concrete graph use case and bounded output contract.

Demo: Python Source End To End

Write ops.py:

from pydantic import BaseModel
from wf_authoring import node


class EchoInput(BaseModel):
    text: str


class EchoOutput(BaseModel):
    echoed: str


@node(name="echo")
def echo(payload: EchoInput) -> EchoOutput:
    return EchoOutput(echoed=payload.text)


registry = [echo]

Configure it:

{
  "version": 1,
  "client": {
    "target": {
      "kind": "rpc_http",
      "url": "http://127.0.0.1:8766/rpc",
      "timeout_seconds": 30
    }
  },
  "server": {
    "store": {"kind": "filesystem", "root": ".wf_python_store"},
    "transports": [
      {"kind": "rpc_http", "host": "127.0.0.1", "port": 8766, "path": "/rpc"}
    ],
    "sources": [
      {
        "kind": "python",
        "id": "local.ops",
        "path": ".",
        "module": "ops",
        "registry": "registry"
      }
    ]
  }
}

Validate before starting:

uv run wf config validate wf.python.config.json

Start the server:

uv run wf-rpc-server --config wf.python.config.json

Call the capability:

uv run wf --config wf.python.config.json cap call local.ops.echo --input '{"text":"hello"}'

Turn it into a saved workflow:

uv run wf --config wf.python.config.json draft create `
  python_echo_ws --capability local.ops.echo --name python_echo

uv run wf --config wf.python.config.json draft save python_echo_ws `
  --artifact python_echo `
  --version 1 `
  --title "Python Echo" `
  --outcome ok `
  --binding local.ops=local.ops

uv run wf --config wf.python.config.json deploy save python_echo.default `
  --artifact python_echo `
  --version 1 `
  --binding local.ops=local.ops

uv run wf --config wf.python.config.json run start python_echo.default `
  --input '{"text":"hello workflow"}'

Expected run result:

{
  "status": "completed",
  "outcome": "ok",
  "output": {"echoed": "hello workflow"}
}

What Works Today

  • CLI can target local or remote workflow servers.
  • JSON-RPC server can run from neutral config.
  • wf config validate checks config shape, config-relative paths, and trusted Python source imports.
  • wf status summarizes target, sources, capabilities, runs, admin surfaces, and registry availability.
  • Capabilities can be listed, inspected, and called directly.
  • cap call has compact/text output options for human and agent smoke checks without dumping large raw provider payloads by default.
  • Source resource/prompt inventories can be listed safely without reading or rendering upstream content.
  • Drafts can be created from capabilities and saved as immutable artifacts.
  • Deployments bind configured logical sources to concrete sources; platform sources such as wf.std do not need self-bindings.
  • Runs are persisted at stopped boundaries and can be inspected/listed.
  • MCP upstream sessions are stateful through McpRuntimePool.
  • Local/dev auth records support typed OAuth refresh-token credentials and source-owned MCP auth binding; production secret storage remains future work.
  • Python sources can run through the full draft -> artifact -> deployment -> run lifecycle.

Honest Limits

  • Python sources are trusted in-process code; there is no sandbox.
  • Python sources are static at server startup; no hot reload yet.
  • Python source registry/apply support is not implemented yet.
  • WorkflowSourceProvider covers static inventory only, not runtime/admin/apply lifecycle.
  • Run deletion is not implemented.
  • File-backed stores are the proven storage backend; SQL/secret-manager stores are future work.
  • MCP app/widget passthrough is not a durable workflow product feature yet.
  • Prompt rendering is not exposed as a workflow helper source yet.
  • Google Drive MCP is useful as manual OAuth/MCP smoke coverage, but not a reliable regression fixture because provider quotas/permissions are unstable.

Next Direction

Near-term work should make source providers more regular without prematurely flattening them:

  • Provider lifecycle for add/update/remove/apply/reload across source families.
  • OpenAPI source provider using the same CapabilitySource shape.
  • Clearer config/status diagnostics for source health.
  • Optional Python source development reload.
  • Production-grade auth/secret store integration.

Reading Map