You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
The task run: script is meant to run embedded as part of the workflow definition #1180
Java SDK reference implementation was broken because of #1129
This happened:
Unfortunately this PR breaks SDK Java reference implementation for scripts.
The PR was assuming that a script implementation will consist on an external call to the os script command , which as the Java implemenation proof, is not necesarily true.
We should partially revert it.
We should remove stdin argument for script call, and revert back script arguments from list to map (since both JS and Python supports named arguments). Then we restore the deleted script example (that was a clear indication of breakign backward compatibilitty that should have prevented the merge) and remove the script example that was added.
We can keep new stdin argument for shell and container (it is optional and a nice addition).
I expected this:
No response
Is there a workaround?
No response
Anything else?
No response
Area(s)
No response
Community Notes
Please vote by adding a 👍 reaction to the issue to help us prioritize.
If you are interested to work on this issue, please leave a comment.name: Bug Report 🐞
This is the proposed diff
Note that stdin is removed for Script, because as mentioned in slack it is of dubious utility for scripts, but it can be kept.
What needs to be restored (because it breaks current implementation) is the arguments to be a map rather than a list. Note that a map can be converted to a list so other implementations will still work with reasonable trivial changes, while the opposite is not true (converting a list to map should be based on arg position, which is really ugly),
Besides that, having a map allows user to define narrower jq expressions, which improves user experience, as shown in previous comment.
diff --git a/schema/workflow.yaml b/schema/workflow.yaml
index 88c92bd..b997524 100644
--- a/schema/workflow.yaml
+++ b/schema/workflow.yaml
@@ -877,16 +877,11 @@
type: string
title: ScriptLanguage
description: The language of the script to run.
- stdin:
- type: string
- title: ScriptStdin
- description: A runtime expression, if any, to the script as standard input (stdin).
arguments:
- type: array
+ type: object
title: ScriptArguments
- description: A list of the arguments, if any, to the script as argv
- items:
- type: string
+ description: A key/value mapping of the arguments, if any, to use when running the configured script.
+ additionalProperties: true
environment:
type: object
title: ScriptEnvironment
@@ -929,11 +924,10 @@
title: ShellStdin
description: A runtime expression, if any, to the shell command as standard input (stdin).
arguments:
- type: array
+ type: object
title: ShellArguments
- description: A list of the arguments, if any, to the shell command as argv
- items:
- type: string
+ description: A list of the arguments of the shell command to run.
+ additionalProperties: true
environment:
type: object
title: ShellEnvironment
The author's motivation was to align the spec with a CLI/OS execution model:
Arguments as string[] map directly to argv (positional CLI arguments)
stdin provides a clean separation between data input (piped via stdin) and arguments
Avoids "injection of code into scripts" — data goes through stdin, not embedded in script code
Makes scripts "portable" — they work the same way inside and outside the workflow engine
Why This Breaks the Java SDK (and the Spec Philosophy)
@fjtirado makes a strong case that the change was misguided for scripts specifically:
Scripts are not CLIs. The PR assumed scripts are invoked as external OS commands (like node script.js arg1 arg2). But the Java SDK embeds script execution — JavaScript runs via GraalJS, Python via Jython/subprocess. Named arguments map naturally to language features:
JS: arguments map entries become named variables accessible in the script (e.g., console.log(greetings) — see console-log-args.yaml)
A map is strictly more expressive than a list. You can always convert {a: 1, b: 2} to ["a", "1", "b", "2"], but you can't go the other way without convention-based parsing. The old map format let users write focused jq expressions like '--user': '${.user}' with clear semantics.
The deleted example was a red flag. The old run-script-with-arguments.yaml used arguments: {message: "${ .message }"} and console.log(message) — direct named variable access. PR feat: baseline run:script, run:container and run:shell to support stdin and argv #1129 deleted it because it no longer fit the new array model, which should have signaled backward incompatibility.
stdin for scripts is dubious. For embedded script engines (GraalJS, Jython), there's no real stdin pipe. It only makes sense when scripts are executed as OS subprocesses.
Proposed Fix
Property
Script
Shell
Container
arguments
Revert to object (map)
Revert to object (map)
Keep as array (makes sense for CMD argv)
stdin
Remove (dubious for embedded engines)
Keep (useful for piping data)
Keep (useful for piping data)
For container, keeping arguments as an array makes sense — containers genuinely receive argv via their entrypoint/CMD. But for scripts and shell commands, the map format is more expressive and better matches how SDK implementations actually work.
The example run-script-with-stdin-and-arguments.yaml should be replaced with the restored original run-script-with-arguments.yaml, and run-shell-stdin-and-arguments.yaml should be updated to use the map format for arguments (while keeping stdin).
changed the title [-]Partially revert https://github.com/open-workflow-specification/specification/pull/1129[/-][+]The task `run: script` is meant to run embedded as part of the workflow definition[/+]on Aug 4, 2026
I think there is a major issue with the statement that a map is "strictly more expressive than a list".
A map and an array model two different things.
A map works well for named bindings:
arguments:
message: Hellocount: 3
But it cannot naturally represent positional / unnamed arguments:
script.sh input.txt output.txt
or:
grep -r foo .
With an object, you would have to invent semantics such as:
arguments:
input: input.txtoutput: output.txt
At that point, the runtime has to decide how those keys map to argument order. That is no longer an argv model, but an implementation-specific binding convention.
It also breaks down for cases where order matters, where the same option appears multiple times, or where arguments are unnamed:
There is no natural, lossless object representation for that.
So this claim:
You can always convert {a: 1, b: 2} to ["a", "1", "b", "2"], but you can't go the other way
is misleading. You can serialize a map into an array by defining a convention, but that does not mean the two representations have equivalent semantics. Likewise, an arbitrary argv cannot be represented as a map without inventing names, conventions, or potentially losing ordering and duplicates.
I think the real conceptual distinction should be:
arguments: array → invocation arguments / argv
named bindings / variables → script execution context, and arguably a separate property
For shell, I would be even more strongly against reverting arguments to an object. Shell commands are inherently ordered, and an array is the natural representation:
A map would make common CLI patterns awkward or impossible.
So I think the proposed fix should be reconsidered: preserving named script bindings may make sense, but that does not necessarily justify changing arguments back to an object.
@fjtirado I re-read our Slack PMs, and I believe you're right - that is indeed what we had settled on.
It also further specializes the script task, which would otherwise be little more than a shorthand for a shell task.
Activity
fjtirado commentedon Aug 4, 2026
For references, see how Map of arguments are handled in SDK reference implementation (and why this should have not been changed)
For JS and Python, they are used as named arguments, as supported by the languages
JS implementation is embedded
https://github.com/open-workflow-specification/sdk-java/blob/main/impl/javascript/src/main/java/io/serverlessworkflow/impl/executors/script/js/JavaScriptScriptTaskRunner.java#L77
And it can run this example
https://github.com/open-workflow-specification/sdk-java/blob/main/impl/test/src/test/resources/workflows-samples/run-script/console-log-args.yaml
Python one is base command line, but still it can handle named args gracefullly
https://github.com/open-workflow-specification/sdk-java/blob/main/impl/python/src/main/java/io/serverlessworkflow/impl/executors/script/python/PythonScriptTaskRunner.java#L55-L64
For shell, we are compounding name=value as shell argument, if value is present
https://github.com/open-workflow-specification/sdk-java/blob/main/impl/core/src/main/java/io/serverlessworkflow/impl/executors/RunShellExecutor.java#L54-L60
So you can have only key ones
https://github.com/open-workflow-specification/sdk-java/blob/main/impl/test/src/test/resources/workflows-samples/run-shell/echo-with-args-only-key.yaml
or key-value ones
https://github.com/open-workflow-specification/sdk-java/blob/main/impl/test/src/test/resources/workflows-samples/run-shell/echo-with-args-key-value-jq.yaml (so the key part is fixed and the value result of an argument evalution, heavily improving user experience)
fjtirado commentedon Aug 4, 2026
This is the proposed diff
Note that stdin is removed for Script, because as mentioned in slack it is of dubious utility for scripts, but it can be kept.
What needs to be restored (because it breaks current implementation) is the arguments to be a map rather than a list. Note that a map can be converted to a list so other implementations will still work with reasonable trivial changes, while the opposite is not true (converting a list to map should be based on arg position, which is really ugly),
Besides that, having a map allows user to define narrower jq expressions, which improves user experience, as shown in previous comment.
ricardozanini commentedon Aug 4, 2026
Disclaimer: I used AI to organize my ideas before submiting a PR.
Assessment of Issue #1180
What PR #1129 Changed
PR #1129 by @hirenr made three changes to
run:scriptandrun:shell:argumentsfromobject(map) toarray(string list) — for script, shell, and containerstdin— a new string property on all three (script, shell, container)run-script-with-arguments.yamlexample — which used map-based arguments — and replaced it with a new stdin+argv examplePR #1129 Author's Rationale
The author's motivation was to align the spec with a CLI/OS execution model:
string[]map directly toargv(positional CLI arguments)stdinprovides a clean separation between data input (piped via stdin) and argumentsWhy This Breaks the Java SDK (and the Spec Philosophy)
@fjtirado makes a strong case that the change was misguided for scripts specifically:
Scripts are not CLIs. The PR assumed scripts are invoked as external OS commands (like
node script.js arg1 arg2). But the Java SDK embeds script execution — JavaScript runs via GraalJS, Python via Jython/subprocess. Named arguments map naturally to language features:argumentsmap entries become named variables accessible in the script (e.g.,console.log(greetings)— seeconsole-log-args.yaml)--key=valueor positional flags (seeecho-with-args-key-value-jq.yaml)A map is strictly more expressive than a list. You can always convert
{a: 1, b: 2}to["a", "1", "b", "2"], but you can't go the other way without convention-based parsing. The old map format let users write focused jq expressions like'--user': '${.user}'with clear semantics.The deleted example was a red flag. The old
run-script-with-arguments.yamlusedarguments: {message: "${ .message }"}andconsole.log(message)— direct named variable access. PR feat: baseline run:script, run:container and run:shell to support stdin and argv #1129 deleted it because it no longer fit the new array model, which should have signaled backward incompatibility.stdinfor scripts is dubious. For embedded script engines (GraalJS, Jython), there's no real stdin pipe. It only makes sense when scripts are executed as OS subprocesses.Proposed Fix
argumentsobject(map)object(map)array(makes sense for CMD argv)stdinFor container, keeping
argumentsas an array makes sense — containers genuinely receive argv via their entrypoint/CMD. But for scripts and shell commands, the map format is more expressive and better matches how SDK implementations actually work.The example
run-script-with-stdin-and-arguments.yamlshould be replaced with the restored originalrun-script-with-arguments.yaml, andrun-shell-stdin-and-arguments.yamlshould be updated to use the map format for arguments (while keeping stdin).[-]Partially revert https://github.com/open-workflow-specification/specification/pull/1129[/-][+]The task `run: script` is meant to run embedded as part of the workflow definition[/+][Fix open-workflow-specification#1180] Partially revert run task chan…
[Fix open-workflow-specification#1180] Partially revert run task chan…
[Fix open-workflow-specification#1180] Partially revert run task chan…
[Fix open-workflow-specification#1180] Partially revert run task chan…
cdavernas commentedon Sep 27, 2026
I think there is a major issue with the statement that a map is "strictly more expressive than a list".
A map and an array model two different things.
A map works well for named bindings:
But it cannot naturally represent positional / unnamed arguments:
or:
grep -r foo .With an object, you would have to invent semantics such as:
At that point, the runtime has to decide how those keys map to argument order. That is no longer an
argvmodel, but an implementation-specific binding convention.It also breaks down for cases where order matters, where the same option appears multiple times, or where arguments are unnamed:
There is no natural, lossless object representation for that.
So this claim:
is misleading. You can serialize a map into an array by defining a convention, but that does not mean the two representations have equivalent semantics. Likewise, an arbitrary
argvcannot be represented as a map without inventing names, conventions, or potentially losing ordering and duplicates.I think the real conceptual distinction should be:
arguments: array→ invocation arguments /argvFor
shell, I would be even more strongly against revertingargumentsto an object. Shell commands are inherently ordered, and an array is the natural representation:A map would make common CLI patterns awkward or impossible.
So I think the proposed fix should be reconsidered: preserving named script bindings may make sense, but that does not necessarily justify changing
argumentsback to an object.fjtirado commentedon Sep 28, 2026
I agree,
For shell, argument should be a list,
For scripts, that usually support named args,we should use a map.
cdavernas commentedon Sep 28, 2026
@fjtirado I re-read our Slack PMs, and I believe you're right - that is indeed what we had settled on.
It also further specializes the script task, which would otherwise be little more than a shorthand for a shell task.
[Fix open-workflow-specification#1180] Revert arguments from array ba…