Activity inputs should be expression-evaluated before scheduling activities
#462 opened on 2026/06/01
Repository metrics
- Stars
- (183 個のスター)
- PR merge metrics
- (PR metrics pending)
説明
Summary
Activity-backed tasks currently receive unresolved expression strings in their activity input payloads.
For example, this workflow:
do:
- fork:
fork:
compete: false
branches:
- grpc:
call: grpc
with:
proto:
endpoint: file:///go/app/examples/external-calls/grpc/basic/proto/basic/v1/basic.proto
service:
name: providers.v1.BasicService
host: grpc
port: 3000
method: Command1
arguments:
input: ${ $env.GRPC_INPUT }
results in the gRPC activity receiving:
{
"arguments": {
"input": "${ $env.GRPC_INPUT }"
}
}
The expression is then evaluated by the activity implementation rather than by the workflow before the activity is scheduled.
Why this is a problem
This creates a few rough edges:
-
Activity inputs in Temporal history are harder to inspect
The recorded activity input contains the unresolved expression rather than the concrete value passed to the external system.
That makes debugging harder because it is not obvious what value the activity actually used.
-
Expression validation may miss activity input expressions
If expressions inside
withpayloads are not collected and validated before execution, then invalid, unsupported or non-deterministic expressions may only fail at runtime. -
Expression evaluation responsibility is split
Some expression handling happens in the workflow layer, but activity-backed calls may also perform their own interpolation.
This makes behaviour harder to reason about and risks inconsistent handling across activity types such as
http,grpc,callandrun. -
Potential determinism gap
In principle, a non-idempotent expression could be passed into an activity payload and evaluated outside the normal deterministic validation path.
This may be unlikely in common usage, but it weakens the boundary Zigflow is trying to enforce.
Expected behaviour
Before scheduling any activity-backed task, Zigflow should evaluate expressions in the task's with payload using the workflow expression context.
The activity should receive a fully resolved input payload.
For example, if:
arguments:
input: ${ $env.GRPC_INPUT }
and GRPC_INPUT=hello, the activity input should contain:
{
"arguments": {
"input": "hello"
}
}
not:
{
"arguments": {
"input": "${ $env.GRPC_INPUT }"
}
}
Scope
This likely applies to most or all activity-backed task types, including:
httpgrpccallrun- any other task type that schedules a Temporal activity using a
withpayload
Suggested implementation
Move expression evaluation for activity input payloads into the workflow/task execution layer, before the activity is scheduled.
Activity implementations should receive concrete resolved input and should not need to perform generic Zigflow expression interpolation themselves.
The implementation should also ensure expressions inside activity with payloads are included in expression collection and determinism validation.
Acceptance criteria
- Expressions inside activity
withpayloads are collected during validation. - Invalid expressions inside activity
withpayloads failzigflow validate. - Non-deterministic expressions inside activity
withpayloads are rejected where appropriate. - Activity inputs recorded in Temporal history contain resolved values, not unresolved
${ ... }strings. - Activity implementations no longer need to perform generic expression interpolation on their own input payloads.
- Existing examples using environment-backed activity inputs continue to work.
- Tests cover at least one
grpcand onehttpactivity input expression.