feat: deliver Python workflow client
This commit is contained in:
@@ -22,6 +22,15 @@ The durable product path is now `wf-rpc-server` plus neutral `wf_config` /
|
||||
`wf_server` composition. The old `wf-mcp` script remains a legacy/special-purpose
|
||||
MCP entrypoint and compatibility surface.
|
||||
|
||||
Completed: the async `wf_client` Python slice is verified against the real
|
||||
JSON-RPC ASGI application. It covers capability discovery, local graph
|
||||
authoring, remote validation, immutable artifact save, deployment selection,
|
||||
and durable run execution. Rich client objects have bounded, secret-safe
|
||||
`repr()` and `_repr_html_()` views that never perform remote I/O. Draft
|
||||
workspaces remain a separate server/admin surface and are not part of the
|
||||
client; server registration is explicit so the artifact -> deployment -> run
|
||||
path does not require draft storage.
|
||||
|
||||
## Active Initiative: Workflow Console And Defense Demo
|
||||
|
||||
The next product-facing push is a local-first web console and defense demo that
|
||||
|
||||
@@ -25,6 +25,7 @@ For verified Python 3.14 dependency constraints and their removal criteria, see
|
||||
| `wf_api` | Workflow application surface over core/artifacts/platform: capabilities, drafts, artifacts, deployments, runs, and source/admin surfaces. | `wf_cli`, `wf_server`, JSON-RPC clients, future transports. |
|
||||
| `wf_server` | Durable server composition boundary around `WorkflowApi` plus optional admin/source-registry surfaces. Owns the `wf-rpc-server` startup CLI/policy. | Transport packages and server startup code. |
|
||||
| `wf_transport_rpc_http` | JSON-RPC-over-HTTP app/client and compatibility CLI shim. | Remote `wf` clients and local server smoke tests. |
|
||||
| `wf_client` | Async-native Python client for capability discovery, local authoring, immutable artifacts, deployments, and durable runs. | Python applications and notebooks using a workflow server. |
|
||||
| `wf_sources_mcp` | MCP-as-upstream-source implementation: ids, registry DTOs, auth/catalog stores, discovery, SDK client/facade, runtime pool, wrappers. | `wf_server`, broker glue, MCP source tests. |
|
||||
| `wf_mcp` | MCP frontend/compatibility package: legacy `wf-mcp` entrypoints, broker glue, proxy/admin tools, and shims while extraction continues. | Compatibility callers and MCP transport work. |
|
||||
| `wf_cli` | Command-line frontend over local or remote workflow APIs. | Humans, scripts, agent skills. |
|
||||
@@ -87,6 +88,8 @@ permanent graph node or expose it as a final workflow-output source.
|
||||
- `wf_server.WorkflowServer`: durable workflow server composition object.
|
||||
- `wf_transport_rpc_http.RpcWorkflowApiClient`: JSON-RPC client implementing
|
||||
the workflow/admin surfaces over HTTP.
|
||||
- `wf_client.App`: transport-independent async Python facade over capabilities,
|
||||
authored workflows, saved artifacts, deployments, and durable runs.
|
||||
- `wf_transport_rpc_http.create_rpc_app`: JSON-RPC HTTP adapter over an existing
|
||||
`WorkflowServer`.
|
||||
- `wf_sources_mcp.McpRuntimePool`: persistent MCP source runtime for stateful
|
||||
@@ -121,6 +124,43 @@ permanent graph node or expose it as a final workflow-output source.
|
||||
`--keep-temp` to preserve the generated config/store on failure.
|
||||
- `examples/browser_click_workflow/` is a serial browser-click workflow
|
||||
example with bounded before/after snapshots and full lifecycle tests.
|
||||
|
||||
### Python client walkthrough
|
||||
|
||||
The Python client is intended for an application that already has a running
|
||||
workflow server. This is the complete shape of a real client call; the schema
|
||||
arguments may be JSON Schema dictionaries or the application's schema model
|
||||
values:
|
||||
|
||||
```python
|
||||
from wf_client import App
|
||||
|
||||
app = App.from_http_jsonrpc("http://localhost:8765/rpc")
|
||||
capability = await app.capability("wf.std.constant")
|
||||
graph = app.new_workflow(
|
||||
"example",
|
||||
input_schema=InputModel,
|
||||
state_schema=StateModel,
|
||||
output_schema=OutputModel,
|
||||
)
|
||||
step = graph.use(capability)
|
||||
graph.set_entry_point(step)
|
||||
validation = await graph.validate()
|
||||
validation.raise_for_errors()
|
||||
artifact = await graph.save(version=1)
|
||||
run = await artifact.run({})
|
||||
```
|
||||
|
||||
The graph is a local, mutable builder. `validate()` checks its structure locally
|
||||
and then asks the server to validate the serialized plan. `save()` persists an
|
||||
immutable artifact version; it does not deploy or execute the graph.
|
||||
`artifact.run()` selects or creates a deployment, validates its source bindings,
|
||||
and starts a durable run. The returned run is a loaded snapshot; call
|
||||
`refresh()`, `resume()`, or bounded `trace(start=..., limit=...)` when more
|
||||
server state is needed.
|
||||
|
||||
Draft workspaces are intentionally not part of `wf_client`. They are a separate
|
||||
server/admin surface and must be explicitly enabled when composing a server.
|
||||
- `examples/agent_challenges/` contains reusable opencode challenge harnesses
|
||||
for evaluating whether agents can use the public workflow CLI/server path.
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ OpenAPI, or a built-in source. It should see `CapabilitySource` and executable
|
||||
| `wf_sources_python` | Trusted Python module registry loading and projection to `CapabilitySource`. | Authoring primitives, registry mutation/apply, sandboxing. |
|
||||
| `wf_server` | `WorkflowServer` composition from config/store/source providers. | JSON-RPC method definitions, MCP protocol frontend. |
|
||||
| `wf_transport_rpc_http` | JSON-RPC HTTP app/client around an existing `WorkflowServer`. | Server startup policy, source-provider composition. |
|
||||
| `wf_client` | Async Python facade over a narrow client port: capability discovery, local authoring, artifact/deployment snapshots, and durable runs. | Draft workspace authoring, server composition, transport registration. |
|
||||
| `wf_mcp` | Legacy/special-purpose MCP frontend, broker glue, proxy, compatibility shims. | New durable product behavior unless explicitly retiring old callers. |
|
||||
|
||||
## Data Flow
|
||||
@@ -65,6 +66,17 @@ wf_config.server.sources[]
|
||||
-> transport or CLI
|
||||
```
|
||||
|
||||
Python applications consume the same server through `wf_client.App`; the
|
||||
client's local builder and immutable snapshots sit above the transport:
|
||||
|
||||
```text
|
||||
wf_client.App
|
||||
-> WorkflowClientPort
|
||||
-> RpcWorkflowApiClient
|
||||
-> JSON-RPC HTTP
|
||||
-> WorkflowServer / WorkflowApi
|
||||
```
|
||||
|
||||
The first shared provider seam is intentionally static:
|
||||
|
||||
```python
|
||||
@@ -212,3 +224,18 @@ Then add:
|
||||
|
||||
Do not add source-family branches inside `wf_api` run execution. Source-specific
|
||||
logic belongs in the provider package or server composition layer.
|
||||
|
||||
## Python client boundary
|
||||
|
||||
`wf_client` is a consumer-facing layer, not another server API.
|
||||
`App.from_http_jsonrpc()` creates a lazy HTTP transport; the first
|
||||
capability/artifact/deployment/run operation performs I/O. `EditableWorkflow`
|
||||
keeps graph construction local and uses the port only for remote validation and
|
||||
artifact persistence. The server remains responsible for durable artifact,
|
||||
deployment, and run stores and for resolving concrete source bindings.
|
||||
|
||||
The client intentionally omits draft workspace operations. Drafts are a
|
||||
server-side authoring/admin surface, and a server composition must opt in to
|
||||
registering their JSON-RPC methods. This keeps a normal Python application
|
||||
focused on the stable artifact -> deployment -> run lifecycle while retaining
|
||||
the underlying draft implementation for explicit server users.
|
||||
|
||||
@@ -20,6 +20,7 @@ frontends can share.
|
||||
| `wf_sources_mcp` | MCP-as-upstream-source implementation: source ids, source registry DTOs, auth/catalog stores, discovery, SDK client/facade, persistent runtime pool, and tool-wrapper helpers. |
|
||||
| `wf_mcp` | MCP frontend/compatibility package: old `wf-mcp` server entry points, broker glue around MCP-hosted services, proxy/admin tools, and compatibility shims while callers migrate. |
|
||||
| `wf_transport_rpc_http` | JSON-RPC-over-HTTP transport adapter and remote client over `WorkflowApiSurface`, not a reimplementation of workflow business logic. |
|
||||
| `wf_client` | Async Python consumer facade over a narrow capability/artifact/deployment/run port. It reconstructs immutable snapshots and keeps representations bounded and inert. |
|
||||
| future `wf_http` / WebSocket / MCP server transports | Additional transports over `WorkflowApiSurface`, not new workflow application APIs. |
|
||||
| `wf_cli` | CLI frontend over `WorkflowApiSurface`; it may run locally against process-local stores or target a remote JSON-RPC backend. |
|
||||
|
||||
@@ -107,6 +108,40 @@ Important rules:
|
||||
Do not add a catch-all `service` field to the context. If a domain API needs a
|
||||
new dependency, add a narrow protocol or explicit field.
|
||||
|
||||
## Python client lifecycle
|
||||
|
||||
The Python client makes the intended application flow explicit:
|
||||
|
||||
```python
|
||||
app = App.from_http_jsonrpc("http://localhost:8765/rpc")
|
||||
capability = await app.capability("wf.std.constant")
|
||||
graph = app.new_workflow(
|
||||
"example",
|
||||
input_schema=InputModel,
|
||||
state_schema=StateModel,
|
||||
output_schema=OutputModel,
|
||||
)
|
||||
step = graph.use(capability)
|
||||
graph.set_entry_point(step)
|
||||
validation = await graph.validate()
|
||||
validation.raise_for_errors()
|
||||
artifact = await graph.save(version=1)
|
||||
run = await artifact.run({})
|
||||
```
|
||||
|
||||
The graph is an in-process builder. Validation is local structural checking
|
||||
plus a server plan check. Saving creates an immutable, versioned artifact; it
|
||||
does not execute anything. A deployment is the server's runnable configuration
|
||||
for one exact artifact version, including logical-to-concrete source bindings
|
||||
and drift policy. A run is a durable execution record for that deployment;
|
||||
inspection and bounded trace reads return snapshots, while resume is an
|
||||
explicit operation for interrupted runs.
|
||||
|
||||
`wf_client` does not expose draft workspaces. Draft API classes remain useful
|
||||
to server/admin and console callers, but normal server composition keeps draft
|
||||
JSON-RPC registration opt-in so artifact, deployment, and run durability do not
|
||||
depend on a draft store.
|
||||
|
||||
## WorkflowApiSurface And Domain Services
|
||||
|
||||
`WorkflowApiSurface` is the public application contract shared by local and
|
||||
|
||||
Reference in New Issue
Block a user