Skip to content

Plan — scoped_context (variables): run, contract, designer

This document is the implementation plan for workflow scoped_context, focused on variables first. It extends ADR 0001 with milestones, deliverables, and acceptance criteria.

For narrative background (“easier run side vs designer”), keep reading; for execution order, see Workstreams & sequencing at the end.

Architecture (2026-06): variable values and types live in the orchestrator run context; the variables provider is stateless (operations only). See ADR 0008.


Scope

In scope Out of scope (later)
Variables-oriented scoped_context (name, type, optional init) Non-variable scoped declarations (other providers) until schema exists
Orchestrator merge into run context + type metadata (_scoped.declarations) Provider-side variable storage / Redis buckets
Dashboard: visibility → edit path Replacing workflow YAML with registry-only storage
Stateless variables.* operations via service_call Full static analysis of every payload binding at design time

Source of truth remains scoped_context inside workflow YAML/JSON loaded by Orchestrator. Runtime values are in orchestrator context, not the provider.


Current baseline (implemented)

Layer What exists
Orchestrator WorkflowDoc.scoped_context parsed; apply_scoped_context_to_run_context; reserved _scoped.* keys; workflow_run_scoped_context structured log (workflow, scoped_declaration_count, provider_service, scoped_context_applied); operand type check before variables.* service_call when payload_from binds a declared variable; X-Scoped-Declarations header on variables.* HTTP calls
Variables service Statelessvariables.string_concat, variables.numbers_add, variables.scoped_context registry metadata; no set/get/list, no Redis
Dashboard Banner on workflow header + Run tab; Code tab: hint + schema link, read-only banner, admin table editor for scoped_context; buildWorkflowYaml emits scoped_context; save validates via POST /api/runtime/validate-workflow; fetchScopedDeclarationSchema / listScopedDeclarationProviderNames + provider datalist (registry scoped_declarations)

Deprecated / removed:

  • push_scoped_context_to_variables_provider / variables.set seeding
  • Dashboard GET /api/runtime/variables-list/{root_run_id} (provider had no list endpoint) — to be removed from UI; use run context / trace instead

Workstream R — Run-time observability & ops

Goal: Operators and developers can see scoped declarations and merge outcome without reading logs blindly.

ID Deliverable Acceptance criteria
R1 Structured log at workflow run start (or immediately after context merge) Done: Logger workflow, level INFO, message id workflow_run_scoped_context; extra fields: workflow, scoped_declaration_count, provider_service, scoped_context_applied (true when declarations merged); no secret values
R2 Dashboard run overview (minimal) Done (baseline): On Run tab for a selected run, fetch current workflow via GET /api/workflows/{name} and show the same read-only Scoped context banner as on the workflow header when scoped_context.variables is non-empty; subtitle clarifies it matches Design/Code.
R3 ~~variables list for current root run id~~ Superseded by ADR 0008 — values are in orchestrator context, not provider buckets. Optional future: show declared variables + current context slice from run ledger.
R4 Docs: operator note Done: Context variables; ADR 0008

Dependencies: R2 uses client-side GET /api/workflows/{name} when a run is selected (same payload as Design/Code); no trace-by-run endpoint required for the banner.


Workstream C — Capability contract & registry metadata

Goal: Designer can eventually render forms without hard-coding variables.service field lists (ADR 0001).

ID Deliverable Acceptance criteria
C1 Extend canonical doc Capability Provider Contract Done: Section Workflow scoped declarations (metadata.designer.scoped_declarations) — schema_version, variable_row, provider_block; settled key name scoped_declarations
C2 Variables service registration Done: Service registration includes metadata.designer.scoped_declarations (Python _scoped_declarations_metadata() aligned with ScopedVariableDecl / provider block)
C3 Dashboard helper (optional) Done: fetchScopedDeclarationSchema(serviceName), listScopedDeclarationProviderNames() (registry services with metadata.designer.scoped_declarations); Code-tab provider field uses datalist populated from registry

Dependencies: C1 before C2; C2 before Designer B3.


Workstream B — Dashboard designer

Goal: Edit scoped_context without raw YAML for common cases.

Phase ID Deliverable Acceptance criteria
B1 B1 Read-only everywhere useful Done: Code tab shows read-only Scoped context banner when declarations exist (subtitle ties to generated YAML)
B2 B2 YAML/Code editor assist Done: Hint + link to /static/schemas/workflow-scoped-context.json; wiki remains canonical narrative
B3 B3 Table UI Done (MVP): Admins get table (+ variable, name/type/init, provider service_name text field); Apply updates in-memory workflow + YAML preview; persist via existing Code → Save (PUT). Registry-driven provider dropdown deferred (optional after C3)
B4 B4 Validation Done: _validateScopedContextErrors in _validateWorkflow; Save YAML calls POST /api/runtime/validate-workflow → orchestrator /admin/validate

Dependencies: B3 MVP shipped with fixed columns + provider text field; optional C3 + registry dropdown can replace provider input later.


Cross-cutting

Topic Action
Testing Integration test: workflow with scoped_context + run → assert context contains init values and _scoped.declarations (variables_provider_test)
Security Never log init.value if marked sensitive (future); internal APIs use authz consistent with dashboard admin
i18n Solution language English for UI strings and docs
Type safety Orchestrator checks declared type vs variables.* operation when payload_from references context:<declared-name>; provider receives X-Scoped-Declarations header

Workstreams & sequencing

Recommended order:

  1. R1 + R4 — fast feedback loop for operators (logs + docs).
  2. R2 — improves daily debugging without designer work.
  3. C1 → C2 — unlocks generic designer.
  4. B1 → B2 — progressive UX on Code tab.
  5. B3 → B4 — full editing path.

Parallelism: R can proceed while C is drafted; B1–B2 can overlap R2**.


Open questions

  • Whether child workflows (workflow_call) should inherit parent scoped declarations in UI only — document behaviour (orchestrator already passes context).
  • Design-time warnings when a variables.* step binds a declared variable of the wrong type (today: runtime check only for payload_from: context:<name>).