HilPresentationReplyEnvelope
Browser → Server · Version 1.3 · Phase 2 (Resumption)
Structure
HilPresentationReplyEnvelope
├── EngageSessionID int — echoed from request session
├── CorrelationID string — echoed from Session.CorrelationID
├── ReplyToID string? — echoed from Session.ReplyToID
│
├── Responders[] { ActorID, ActorType, DisplayName, ResponderRole }
│
├── Decision "approved" | "rejected" | "submitted" | "replied" | ...
├── ActionName "approveOrder" | "cancelOrder" | "submitForReview" | ...
├── DecidedAt ISO 8601 UTC
├── Channel "web" | "slack" | "email" | "mobile" | "api"
│
├── Actions[] audit trail
│ └── { ActionType, ActionName, ActionLabel, PerformedBy, PerformedAt, ActionData{} }
│
├── Payload
│ ├── DataSteps[] per-step (EnableSteppedDataReturn=true, default)
│ │ └── { StepOrder, PresentationType, ActionName, Data{}, CompletedAt }
│ ├── Data{} merged flat bag (EnableFlatDataReturn=true, default)
│ ├── ReplyText? chat typed field
│ ├── ThreadID?
│ ├── Comment? approval typed field
│ ├── Reason? rejection / escalation reason
│ └── Raw? JsonElement fallback
└── Metadata{}
Decision vs ActionName
Decision = standard routing token (node selects output port). ActionName = domain-specific button key echoed from Actions[].ActionKey in the request. They may be identical ("approved") or differ (ActionKey:"approveOrder" → Decision "approved").| Field | Purpose | Examples |
|---|---|---|
Decision | Standard routing token — node executor selects output port | approved, rejected, submitted, replied |
ActionName | Domain-specific named action — business context, echoed from request | approveOrder, cancelOrder, submitForReview, requestRevision |
Payload — DataSteps vs Data
| Field | Controlled by | Default | Best for |
|---|---|---|---|
DataSteps[] | EnableSteppedDataReturn | true | Multi-step flows, full traceability — which data came from which step and which action triggered it |
Data{} | EnableFlatDataReturn | true | Single-step flows, legacy consumers expecting a simple flat key-value bag |
ReplyText | Always populated | — | Chat interactions — typed convenience, no parsing needed |
Comment | Always populated | — | Approval decisions with notes |
Reason | Always populated | — | Rejections and escalations with structured reason |
HilReplyStep — ActionName binding
DataSteps[N].ActionName ties the named action directly to the data submitted at that step. Example: step 2 completed via "submitForReview" → { StepOrder:2, ActionName:"submitForReview", Data:{Rating:"4",...} }. The server knows both what was entered and what the actor intended.StepOrderintMatches
HilPresentation.Order from the request.PresentationTypestringMirrors the request's
PresentationType: "form", "chat", "approval", "info".ActionNamestringNamed action that completed this step. Empty for intermediate navigations (e.g., “next” between steps).
Data{}DictionaryKey-value data for this step. Form: field→value. Chat:
ReplyText→string. Approval: Comment→string. Info: empty.CompletedAtstringISO 8601 UTC timestamp when this step was completed.
Responder Roles
| ResponderRole | Meaning |
|---|---|
primary | The main actor who performed the interaction (default, 99% of cases) |
delegate | Acting on behalf of the assignee |
co-signer | Required co-approver |
witness | Observed the interaction for audit purposes |
Standard Decisions
| Decision | Used by | ActionType (audit) |
|---|---|---|
approved | Approval, Chat | approve |
rejected | Approval, Chat | reject |
submitted | Form, FormTrigger | submit |
replied | Chat, ChatTrigger, ChatReceive | reply |
escalated | Approval | escalate |
cancelled | All | cancel |
abstained | Approval | abstain |
C# Model
C#
public class HilPresentationReplyEnvelope
{
public int EngageSessionID { get; set; }
public string CorrelationID { get; set; } = string.Empty;
public string? ReplyToID { get; set; }
public List<HilPresentationReplyResponder> Responders { get; set; } = new();
public string Decision { get; set; } = string.Empty;
public string ActionName { get; set; } = string.Empty;
public string DecidedAt { get; set; } = string.Empty;
public string Channel { get; set; } = string.Empty;
public List<HilPresentationReplyAction> Actions { get; set; } = new();
public HilPresentationReplyPayload Payload { get; set; } = new();
public Dictionary<string, object> Metadata { get; set; } = new();
}
public class HilPresentationReplyPayload
{
public List<HilReplyStep> DataSteps { get; set; } = new();
public Dictionary<string, object> Data { get; set; } = new();
public string? ReplyText { get; set; }
public string? ThreadID { get; set; }
public string? Comment { get; set; }
public string? Reason { get; set; }
public JsonElement? Raw { get; set; }
}
public class HilReplyStep
{
public int StepOrder { get; set; }
public string PresentationType { get; set; } = string.Empty;
public string ActionName { get; set; } = string.Empty;
public Dictionary<string, object> Data { get; set; } = new();
public string CompletedAt { get; set; } = string.Empty;
}
public class HilPresentationReplyResponder
{
public string ActorID { get; set; } = string.Empty;
public string ActorType { get; set; } = "user";
public string? DisplayName { get; set; }
public string ResponderRole { get; set; } = "primary";
}