Repository navigation
v3.6.0 — DSPy 3.4, request splitting, workflow facts on classes, and a self-bounding observability store
Latestv3.6.0
The agent can split a request into independent sub-tasks and run them one by one, with execution guards against repeated or malformed steps. fastWorkflow moves to DSPy 3.4. The runtime manifest is retired, and workflow facts are now declared on the classes themselves. The observability store keeps itself within its size cap in long-lived servers with no setup. This release also carries the unreleased 3.5.1 work: exact prompts in the debug UI and fixes to agent tool selection. Package version is 3.6.0. This wheel is already on PyPI.
The curated list is under 3.6.0 and 3.5.1 in CHANGELOG.md. These notes cover the upgrade.
Requires Python >=3.13,<3.15 (unchanged).
Breaking changes (read before upgrading)
- A populated observability database from an older schema is refused and left in place. This build reads schema v9 and carries no migration. Opening a populated v8 or older
observability.sqlite3raisesOlderObservabilityStore. fastWorkflow does not delete that file. Move it aside, together with its-waland-shmfiles, before starting a new store. dspyis required at>=3.4.0,<3.5with thetypesafeextra.import fastworkflowimports litellm before dspy, and it repairs DSPy's lazyopenaistand-in if dspy was imported first.workflow_runtime.jsonis retired. A context's callback class declaresoccupiable = False. A command'sResponseGeneratordeclaresdescends_to/descend_parameter. Workflow identity is a content hash computed by the framework.- Capture profiles and context handles are gone.
FW_OBS_CAPTURE_PROFILEand the manifestcapturefield are removed. A manifest that still declarescaptureorhandle_projectorfails validation. Recorded values get the credential scrub only. - Observation handles are ReAct step indexes (
O0,O1, …). Execute ordinals,ordinal_offset, forced-replan continuation segments andalias_conflictare removed. - The workspace viewer and the blinded review sidecar are removed. That covers
run_chatbot --workspace-manifest,/api/workspace/*,/api/select_workspace,/api/review/*,/traceandfastworkflow/review/. Comments always go to the workflow's live database. Experiment sealing is unchanged.
Highlights
- Request splitting: the agent splits a request into independent sub-tasks and runs them one by one. Workflow skills in
_skills/serve as job types, and an optional_skills/split_instructions.mdadds splitting instructions. When a sub-task hits the 25-step cap, it is handed to a fresh executor, at most twice. - Execution guards:
- A call that bundles several commands is refused.
- A command that returns the same result again is blocked for one step.
- Unparsable replies and LLM timeouts are recovered as bad steps instead of ending the turn.
LLM_TIMEOUT_SECONDSbounds each LLM call (default 120). Parameter-validation hooks can declarecommand_textto receive the command as written.- Self-bounding observability store:
- The retention prune now runs hourly, not only when the recorder starts.
- When only turn records remain over
FW_OBS_DB_MAX_BYTES, the oldest finished turns that belong to no experiment are evicted whole. The cap is now a real limit on file size. - No new settings: the defaults (30 days, 1 GiB) work out of the box.
- A malformed
FW_OBS_*integer now logs a warning, as does an unsealed experiment that alone holds the file over its cap.
- Exact prompts in the debug UI: an LLM call whose messages exceed the 16 KB attribute cap is stored as deduplicated pieces in a new
prompt_slotstable.ObservabilityStore.prompt_as_sentrebuilds the call and checks it against the recorded digest. The debug UI shows it under "LLM input as sent". - Clearer observations: each observation line says where the command ran and whether it changed the context, e.g.
Observation O3 (execute_workflow_query ran in Directory); and resulted in a context change. - Planner context: the initial planner gets every prior turn summary, not just the last trajectory. The planner and agent tools get prescriptive context-navigation guidance.
- Observation offloading is simpler: each observation is saved once per step and offloaded when the whole executor prompt exceeds
FW_TRAJECTORY_MAX_BYTES. - Feedback API:
POST /post_feedbackandGET /feedbackaccept a retired execution key./post_feedbackreturns the turn's comments.
Fixes
- When the model names a workflow command as its tool (for example
next_tool_name: open_directory) and that command is available in the current context, the step runs as theexecute_workflow_querycall it meant. Previously it became an invalid-tool step, and three of those end the turn. - A moved or reinstalled fastworkflow no longer breaks every turn. A stale
command_directory.jsonwhose module paths no longer exist is rebuilt.
Security
-
Dependency floors raised:
Package Floor CVEs transformers>=5.17.0CVE-2026-75104, CVE-2026-80047 anyio>=4.14.2CVE-2026-63374, CVE-2026-64847 fsspec>=2026.6.0CVE-2026-104851 multidict>=6.9.1CVE-2026-104874 -
The OpenVEX document (
security/vex/fastworkflow.openvex.json) marks the following not_affected:- litellm proxy-only CVEs: CVE-2026-12772, CVE-2026-12795, CVE-2026-12796;
- the transformers ZDI checkpoint batch;
- several torch CVEs with no fix available that fastWorkflow can't reach.
What's Changed
- Say when a command moved the context on its observation line by @dharrawal in #86
- Agent observation and tool-selection fixes, exact prompts in the debug UI (3.5.1) by @dharrawal in #87
- merge beads changes by @dharrawal in #88
- DSPy 3.4, request splitting, workflow facts on classes (3.6.0) by @dharrawal in #89
Full Changelog: v3.5.0...v3.6.0
Install
uv pip install 'fastworkflow==3.6.0'
# optional extras:
uv pip install 'fastworkflow[server]==3.6.0' # FastAPI/MCP HTTP service
uv pip install 'fastworkflow[training]==3.6.0' # HuggingFace datasets for train