The Interaction Model
EdgeInteract defines a precise five-stage interaction lifecycle: Request → Deliver → Display → Respond → Acknowledge. Understanding this model is the foundation for using EdgeInteract correctly.
Overview of the Lifecycle
Every EdgeInteract interaction follows the same five-stage lifecycle regardless of type. The stages are sequential and each stage must complete before the next begins. If a stage fails (e.g., timeout), the pipeline terminates with an error message on the callback topic.
Request
Server code constructs an InteractionRequest object and calls IInteractionPublisher.PublishAsync(userId, request). The request is assigned a UUID interactionId and timestamped. Pre-send hooks run at this stage.
Deliver
EdgeInteract publishes the serialized request to the EdgeStream topic interactions.{userId}. EdgeStream fans out the message to all active WebSocket sessions for that user. The timeout clock starts ticking.
Display
The client's InteractionContainer receives the message, reads interactionType, and renders the appropriate UI component. The component receives the typed payload and a respond() callback.
Respond
The user takes action (clicks Approve, submits a form, selects options). The component calls respond(outcome, data). EdgeInteract publishes an InteractionResponse to interactions.callback.{interactionId}. Post-receive hooks run here.
Acknowledge
The server receives the response on the callback topic, processes it, and sends an InteractionAck back to the user's session. The UI dismisses the interaction component. The cycle is complete.
InteractionRequest Schema
The InteractionRequest object is the entry point to the pipeline. All fields are required unless marked optional:
| Field | Type | Description |
|---|---|---|
interactionId | string (UUID) | Auto-generated unique ID for this interaction instance |
type | string | Interaction type key: "approval", "confirmation", "form", "picker", "notification" |
targetUserId | string | The user ID of the intended recipient. Can also be a role key for fan-out. |
title | string | Short title shown in the UI component header |
description | string (optional) | Longer contextual description shown below the title |
payload | object | Type-specific payload — structure depends on type |
timeoutMs | number | Milliseconds before an InteractionTimeout is fired on the callback topic |
callbackTopic | string (optional) | Defaults to interactions.callback.{interactionId}. Override for custom routing. |
correlationId | string (optional) | Attach your workflow execution ID or any correlation key for tracing |
priority | "normal" | "high" (optional) | High-priority interactions appear at the top of the HIL inbox |
InteractionResponse Schema
The InteractionResponse is published by the client after the user acts. It is received by the server on the callback topic:
| Field | Type | Description |
|---|---|---|
interactionId | string | Matches the request's interactionId |
respondedBy | string | The user ID of the user who responded (matters for role-targeted interactions) |
outcome | string | Type-specific outcome: "approved", "rejected", "confirmed", "submitted", "selected", "acknowledged" |
data | object (optional) | Type-specific response data (form values, selected IDs, comments) |
timestamp | ISO 8601 string | When the user responded |
sessionId | string | The EdgeStream session ID of the responding session |
Timeout Behavior
Every interaction has a timeoutMs. When the timeout expires without a response:
- EdgeInteract publishes an
InteractionTimeoutmessage tointeractions.callback.{interactionId} - The message has
outcome: "timeout"and no data - The server's awaiting code receives this and should handle accordingly (escalate, retry, or fail the workflow branch)
- The UI component on the client receives a dismissal signal and removes the interaction from the inbox
outcome: "timeout" explicitly. Workflows that ignore timeout will hang indefinitely.
TypeScript Types
// Core types
interface InteractionRequest<TPayload = unknown> {
interactionId: string;
type: InteractionTypeKey;
targetUserId: string;
title: string;
description?: string;
payload: TPayload;
timeoutMs: number;
callbackTopic?: string;
correlationId?: string;
priority?: 'normal' | 'high';
}
interface InteractionResponse<TData = unknown> {
interactionId: string;
respondedBy: string;
outcome: string;
data?: TData;
timestamp: string;
sessionId: string;
}
interface InteractionTimeout {
interactionId: string;
outcome: 'timeout';
timestamp: string;
}
type InteractionTypeKey =
| 'approval'
| 'confirmation'
| 'form'
| 'picker'
| 'notification'
| string; // custom types
State Machine Summary
| State | Transitions To | Trigger |
|---|---|---|
pending | delivered | Request published to EdgeStream topic |
delivered | displayed | Client session receives the message |
delivered | timed_out | No session receives it within timeoutMs |
displayed | responded | User takes action, respond() called |
displayed | timed_out | User does not respond within timeoutMs |
responded | acknowledged | Server sends InteractionAck |