Flow Studio
Injecting Resume Data
The actor's response data is merged into ExecutionMemory as the output of the suspended node. Downstream nodes access it exactly as they would any other node's output — via GetNodeOutput or $output.nodeId in expressions.
Merge Operation
// HILResumeService merges response data into the restored ExecutionMemory
private void MergeResumeData(
ExecutionMemory memory,
string suspendedNodeId,
object responseData)
{
// responseData becomes the node's output in the memory map
memory.nodeOutputs[suspendedNodeId] = responseData;
}
// After merge, the engine continues from the HIL node's appropriate output port
// The port is selected based on the response (e.g., decision="Approved" → approved port)
Accessing Resume Data in Downstream Nodes
// In a C# executor downstream of the HIL node:
var approvalOutput = ctx.ExecutionMemory.GetNodeOutput<ApprovalOutput>("approvalNode1");
var decision = approvalOutput.Decision; // Approved or Rejected
var comment = approvalOutput.Comment;
var decidedBy = approvalOutput.ActorId;
var decidedAt = approvalOutput.DecidedAt;
// In an expression (for node config):
// $output.approvalNode1.decision
// $output.approvalNode1.comment
Typed Output Models
// ApprovalOutput — set as the suspended node's output on resume
public class ApprovalOutput
{
public ApprovalDecision Decision { get; set; } // Approved | Rejected
public string? Comment { get; set; }
public string ActorId { get; set; }
public DateTimeOffset DecidedAt { get; set; }
}
// UserFormOutput — the submitted form field values
public class UserFormOutput : Dictionary<string, object>
{
// Dynamic — keys are form field names, values are submitted values
}
// ReviewOutput
public class ReviewOutput
{
public bool Acknowledged { get; set; }
public string? Comment { get; set; }
public string ActorId { get; set; }
public DateTimeOffset ReviewedAt { get; set; }
}
Port Selection on Resume
The engine selects the appropriate output port based on the resume data:
// ApprovalPortResolver
public string ResolvePort(ApprovalOutput output)
{
return output.Decision == ApprovalDecision.Approved ? "approved" : "rejected";
}
// UserFormPortResolver
public string ResolvePort(UserFormOutput output)
{
return "submitted"; // always single port for form submission
}