Skip to content

Python: fix(declarative): treat omitted workflow inputs as blank in PowerFx - #9730

Draft
Naveen Chatlapalli (1aifanatic) wants to merge 1 commit into
microsoft:mainfrom
1aifanatic:contrib/python-declarative-missing-inputs-blank
Draft

Naveen Chatlapalli (1aifanatic) wants to merge 1 commit into
microsoft:mainfrom
1aifanatic:contrib/python-declarative-missing-inputs-blank

Conversation

@1aifanatic

Copy link
Copy Markdown
Contributor

Motivation & Context

=If(IsBlank(inputs.name), "World", inputs.name) never applies its default when the caller omits name, so the simple_workflow sample prints Hello, ! for workflow.run({}). PowerFx fails to compile inputs.name when the inputs record has no such field, and DeclarativeWorkflowState.eval() returns None for the whole expression. Details and an input matrix are in #9729.

Description & Review Guide

  • What are the major changes?
    • _bind_missing_input_references() finds inputs.<name> / Workflow.Inputs.<name> references in the formula. Any input the caller did not supply is bound to blank (None) in that evaluation's PowerFx symbols, for both aliases. Workflow state is not modified, and other undefined names keep the existing None behavior. The regex follows the existing _ENV_REFERENCE_RE approach for Env.<name>.
    • New parametrized test test_if_with_isblank_when_input_is_missing, next to test_if_with_isblank, which only covered {"name": ""}. It checks both aliases and that the missing key is not written to state.
    • The simple_workflow sample now prints the outputs of its second ("Alice") run, which were discarded.
  • What is the impact of these changes? An omitted input now evaluates the same as an input passed as None. Expressions that previously evaluated to None only because an input was absent now evaluate normally with that input blank.
  • What do you want reviewers to focus on? Whether blank is the semantics you want for omitted inputs. An alternative is binding only inputs declared in the workflow's inputs: schema, but simple_workflow does not declare its inputs.

Verification, with the .NET 10 runtime for PowerFx:

main this PR
new test (both aliases) assert None == 'World' passes
simple_workflow sample Hello, !, then no output for Alice Hello, World!, Hello, Alice!
packages/declarative/tests all pass

Pyright on _declarative_base.py reports 0 errors. Mypy reports the same 5 errors before and after (none on the changed lines). ruff check and ruff format --check pass.

Related Issue

Fixes #9729

AI Assistance

  • No material AI assistance was used.
  • This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.

AI assistance details: Claude Code helped find the bug by running the declarative samples locally, trace it to DeclarativeWorkflowState.eval(), implement the fix and test, and draft this description and the linked issue.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

🤖 Generated with Claude Code

…owerFx

When a caller omits an input that a formula references, PowerFx fails to
compile inputs.<name> / Workflow.Inputs.<name> ("Name isn't valid") and
eval() returns None for the whole expression. That breaks the documented
default pattern =If(IsBlank(inputs.name), "World", inputs.name): the
simple_workflow sample printed "Hello, !" for workflow.run({}).

Bind referenced-but-missing inputs to blank for that evaluation only, the
same result as passing the input as None, without writing them to state.
Also print the simple_workflow sample's second run, which was discarded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 18:36
@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Oct 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Reference discovery matches literal and comment text while missing valid quoted and whitespace-separated references.

2 open issues
What changed in this PR

This PR addresses #9729 by binding omitted workflow inputs as blank during PowerFx evaluation, allowing default expressions to run without modifying workflow state.

Changes:

  • Adds evaluation-only blank bindings for references through both input aliases.
  • Tests omitted-input defaults and verifies state remains unchanged.
  • Prints the custom-name run’s outputs in the simple workflow sample.
File Description
python/​samples/​03-workflows/​declarative/​simple_workflow/​main.py Prints outputs from the “Alice” run.
python/​packages/​declarative/​tests/​test_powerfx_yaml_compatibility.py Adds missing-input regression tests for both aliases.
python/​packages/​declarative/​agent_framework_declarative/​_workflows/​_declarative_base.py Discovers missing input references and binds evaluation-only blanks.

Review effort: Balanced



_ENV_REFERENCE_RE = re.compile(r"\bEnv\.([A-Za-z_][A-Za-z0-9_]*)")
_INPUT_REFERENCE_RE = re.compile(r"(?<![\w.])(?:inputs|Workflow\.Inputs)\.([A-Za-z_][A-Za-z0-9_]*)")
if not isinstance(inputs, Mapping):
return symbols
input_values = cast(Mapping[str, Any], inputs)
missing = {name for name in _INPUT_REFERENCE_RE.findall(formula) if name not in input_values}

This branch was previously deployed

1 inactive deployment
github-app-auth — 1f187633 Deployed Oct 26, 2026 by 1aifanatic via team_check #7569
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: Python: [Bug]: Declarative workflow IsBlank defaults ignore inputs the caller omitted

2 participants