# Multi-Step Workflow Pattern # Sequence externally meaningful steps without mirroring the conversation into # a current_step counter or focus latch. # # Use this pattern only when later actions must be blocked until earlier # external actions succeed. Ordinary question-and-answer sequences should rely # on conversation history and slot filling instead. # # State contract: # - Every mutable value is written from an action result. # - Every mutable value has an action binding, availability guard, or # completion instruction as a consumer. # - A failed action leaves the next action unavailable. # - Cancellation or a change of intent exits immediately without erasing # already completed external work. # # This is a COMPLETE template - customize action contracts and metadata. system: instructions: | You are an account onboarding assistant. Help users complete the externally required setup actions in order. Use the latest information in the conversation when filling action inputs. If the user cancels or changes intent, leave onboarding immediately and do not invoke another onboarding action. messages: welcome: "Welcome! I can help you set up your account." error: "I couldn't complete that step. Nothing later in setup has been unlocked." access: default_agent_user: "agent@company.salesforce.com" config: developer_name: "Onboarding_Agent" agent_label: "Onboarding Assistant" description: "Completes externally ordered account onboarding actions" variables: EndUserId: linked string source: @MessagingSession.MessagingEndUserId description: "Messaging End User ID" RoutableId: linked string source: @MessagingSession.Id description: "Messaging Session ID" created_customer_id: mutable string = "" description: "Canonical customer ID returned by successful account creation" account_created: mutable boolean = False description: "Trusted success result from account creation" profile_saved: mutable boolean = False description: "Trusted success result from the profile update" preferences_saved: mutable boolean = False description: "Trusted success result from saving notification preferences" verification_sent: mutable boolean = False description: "Trusted success result from sending a verification code" onboarding_complete: mutable boolean = False description: "Trusted result from verifying the customer-provided code" language: default_locale: "en_US" start_agent onboarding: label: "Account Onboarding" description: "Completes account creation, profile, preferences, and verification in external-system order" actions: create_account: description: "Create a customer account after the user supplies an email address and full name" inputs: email: string description: "Customer email address" is_required: True name: string description: "Customer full name" is_required: True outputs: customer_id: string description: "Canonical ID of the created customer" success: boolean description: "Whether account creation succeeded" target: "flow://Create_Customer_Account" update_profile: description: "Save the optional phone number for the created customer" inputs: customer_id: string description: "Canonical customer ID" is_required: True phone: string description: "Phone number, or an empty value when the user skips it" is_required: False outputs: success: boolean description: "Whether the profile update succeeded" target: "flow://Update_Customer_Profile" set_preferences: description: "Save the user's chosen notification method after the profile is saved" inputs: customer_id: string description: "Canonical customer ID" is_required: True notification_method: string description: "Notification method: email, sms, or both" is_required: True outputs: success: boolean description: "Whether the preferences were saved" target: "flow://Set_Customer_Preferences" send_verification: description: "Send a verification code after notification preferences are saved" inputs: customer_id: string description: "Canonical customer ID" is_required: True method: string description: "Delivery method chosen in the conversation" is_required: True outputs: success: boolean description: "Whether a verification code was sent" target: "flow://Send_Verification_Code" verify_code: description: "Verify the code supplied by the user after a code was sent" inputs: customer_id: string description: "Canonical customer ID" is_required: True code: string description: "Verification code entered by the user" is_required: True outputs: verified: boolean description: "Whether the code was valid" target: "flow://Verify_Customer_Code" reasoning: instructions: -> if @variables.account_created == False: | Ask for the user's email address and full name, then create the account. If creation fails, explain the failure and retry only when the user asks. else if @variables.profile_saved == False: | Ask for an optional phone number, or let the user skip it, then save the profile. Do not continue if saving fails. else if @variables.preferences_saved == False: | Ask whether notifications should use email, sms, or both, then save that choice. Do not continue if saving fails. else if @variables.verification_sent == False: | Send a verification code using the notification method most recently chosen in the conversation. Do not claim a code was sent unless the action succeeds. else if @variables.onboarding_complete == False: | Ask for the verification code and verify it. If verification fails, say so and allow another attempt. else: | Confirm that onboarding is complete and provide customer ID {!@variables.created_customer_id}. Do not repeat any completed action. | If the user cancels or asks for unrelated help, use leave_onboarding before invoking another onboarding action. actions: create_customer: @actions.create_account with email=... with name=... set @variables.created_customer_id = @outputs.customer_id set @variables.account_created = @outputs.success available when @variables.account_created == False save_profile: @actions.update_profile with customer_id=@variables.created_customer_id with phone=... set @variables.profile_saved = @outputs.success available when @variables.account_created == True available when @variables.profile_saved == False save_preferences: @actions.set_preferences with customer_id=@variables.created_customer_id with notification_method=... set @variables.preferences_saved = @outputs.success available when @variables.profile_saved == True available when @variables.preferences_saved == False deliver_verification: @actions.send_verification with customer_id=@variables.created_customer_id with method=... set @variables.verification_sent = @outputs.success available when @variables.preferences_saved == True available when @variables.verification_sent == False complete_verification: @actions.verify_code with customer_id=@variables.created_customer_id with code=... set @variables.onboarding_complete = @outputs.verified available when @variables.verification_sent == True available when @variables.onboarding_complete == False leave_onboarding: @utils.transition to @subagent.general_help description: "Cancel onboarding or handle a new, unrelated request without changing completed external work" subagent general_help: label: "General Help" description: "Handles cancellation and requests outside account onboarding" reasoning: instructions: -> | Acknowledge that onboarding is paused. Address the user's latest request if it is within general account support. Do not invoke an onboarding action unless the user explicitly asks to resume. actions: resume_onboarding: @utils.transition to @subagent.onboarding description: "Resume onboarding from the last successful external action" # Review checklist: # - No current_step counter duplicates the action-result flags. # - User-provided email, name, phone, preference, and code use slot filling. # - Exact customer ID persists only because later actions bind it. # - Every later action is unavailable until the preceding external result is # successful. # - Cancellation remains reachable on every onboarding turn.