Workflow Studio
The Workflow Studio is the operator-facing surface for the additive
orchestration control plane introduced by the seven-phase refactor in
orchestration-refactor-rollout.md.
It composes the five existing graph builders, the three (then five)
adapters, and the new hash-locked WorkflowSpec registry into a
single replayable workflow concept.
What ships
| Layer | File / Path |
|---|---|
| Spec contract | alphaswarm/agents/orchestration/spec.py |
| Registry + persist_spec | alphaswarm/agents/orchestration/registry_specs.py |
| Runtime | alphaswarm/agents/orchestration/runtime.py |
| Adapter ABC + metaclass | alphaswarm/agents/orchestration/base.py |
| Adapter registry | alphaswarm/agents/orchestration/registry.py |
| Adapters (5) | alphaswarm/agents/orchestration/adapters/ |
| ORM | alphaswarm/persistence/models_workflows.py |
| Migration | alembic/versions/0046_workflow_versioning.py |
| REST | alphaswarm/api/routes/workflows.py |
| Celery tasks | alphaswarm/tasks/orchestration_tasks.py |
| DataMCP tools | alphaswarm/data/mcp/tools/orchestration.py, alphaswarm/data/mcp/tools/automation.py |
| Cache entry | workflows category in alphaswarm/cache/keys.py |
| Frontend routes | alphaswarm_client/src/routes/workflows/ |
| Frontend components | alphaswarm_client/src/components/workflows/ |
Spec shape
A workflow selects exactly one
OrchestrationAdapter by alias
and hands it adapter-specific params. The adapter dispatches
internally — composite flows (Crew + Graph + Debate) belong inside
their own adapter, not at the spec layer.
name: research.dialectical_with_fusion_v1
description: "Bull/Bear debate + fusion + weight-centric execution"
adapter: LangGraphAdapter
adapter_kind: graph
params:
builder: dialectical # one of build_* in alphaswarm/agents/graph/
builder_kwargs:
max_rounds: 2
schedule:
cron: "30 13 * * 1-5"
timezone: UTC
enabled: false # operator flips after the studio + schedule flags
guardrails:
cost_budget_usd: 3.0
max_calls: 60
max_duration_seconds: 900
annotations: [research, dialectical]
template_target: research
WorkflowSpec.snapshot_hash() is the SHA256 of the canonical JSON
form (sorted keys, no whitespace). Re-snapshotting a spec with the
same hash returns the existing workflow_spec_versions row;
changing any field inserts a NEW row (parallel to
agent_spec_versions, bot_versions, rl_experiment_versions,
analysis_spec_versions).
Operator flow
- Operator flips
ALPHASWARM_ORCHESTRATION_STUDIO_ENABLED=true(see the rollout doc). - Frontend navigates to
/workflows. List + detail render through<EntityPicker kind="workflows" />so the dropdown shares the same cache invalidation path as every other entity picker. - Operator hits Run → POST
/workflows/{name}/run→ enqueuesalphaswarm.tasks.orchestration_tasks.run_workflow. The route returns atask_id; the studio attaches via the existinguseLiveStreamhook for_progress.emitframes (rule 4). - Operator hits Replay on a historical run → POST
/workflows/runs/{run_id}/replayre-dispatches with the capturedspec_version_idfor deterministic reproduction. - Operator hits the topbar KillSwitch's "Halt workflows" action →
POST
/workflows/haltmirrors the five canonical halt endpoints (/agents/halt,/paper/stop-all,/bots/halt-all,/rl/halt-all,/quant-agents/halt).
Halt fan-out
The Phase 2 WorkflowRuntime checks should_halt(state) between
every adapter transition. should_halt is the OR of:
has_kill_switch()— Redis-backed global flag (the existing topbar KillSwitch flips this).state["halt_token"]— per-run boolean the Phase 6/workflows/haltendpoint sets on every activeWorkflowRunrow insideALPHASWARM_ORCHESTRATION_HALT_CHECK_TIMEOUT_SECONDSof the API call.
Long-running adapters (CrewProcessAdapter, LangGraphAdapter,
DialecticalDebateAdapter) poll context.is_halted() between
inner steps so the SLA holds even mid-debate.
Adapter catalog (Phases 2-5)
| alias | kind | source | when registered |
|---|---|---|---|
LangGraphAdapter | graph | alphaswarm | always |
CrewProcessAdapter | crew | finrobot | always (gated invoke) |
DialecticalDebateAdapter | debate | tradingagents | always |
AutomationScheduleAdapter | schedule | daily_stock_analysis | always (gated invoke) |
SignalFusionAdapter | fusion | vibe_trading | always (gated invoke) |
WeightCentricExecutionAdapter | execution | finrl | always (gated invoke) |
WorkflowStudioAdapter (Phase 7) | studio | langflow | TBD |
New adapters land by subclassing
OrchestrationAdapter and
setting adapter_kind + adapter_alias. The metaclass auto-registers
them through
alphaswarm.core.registry.register and the
shadow per-kind index in
alphaswarm/agents/orchestration/registry.py.
Audit trail
Every run produces:
- A
workflow_runsrow (one per run) withspec_version_id,inputs,final_state,breadcrumbs,experiment_id,test_id(rule 34),cost_usd,duration_ms,status,halted,error. - A series of
_progress.emitframes the studio streams live throughuseLiveStream(frame shape per rule 4). - Per-adapter
node_spanOTEL spans emitted byalphaswarm/agents/observability.py. - Optional
agent_runs_v2rows for each innerAgentRuntimecall the wrapped adapter makes.
Replay semantics
POST /workflows/runs/{run_id}/replay looks up the matching
workflow_runs row, hydrates the frozen
workflow_spec_versions.payload, and re-dispatches with the same
inputs. Replay produces a NEW workflow_runs row tagged with the
original run's id in parent_run_id so the trace lineage stays
intact.
See also
- orchestration-refactor-rollout.md — operator runbook + per-flag rollback.
- multi-agent-patterns.md — the seven adapter topologies (Phase 7 docs update).
- data-mcp.md —
data.orchestration.*anddata.automation.*tool catalog. - agentic-development.md — where
WorkflowSpecsits in the four-runtime + skill-artifact framework.