mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-08-07 16:04:41 +08:00
109 lines
4.8 KiB
Plaintext
109 lines
4.8 KiB
Plaintext
# Procedural Instructions Pattern
|
|
# Run a required read-only action before the model handles the current turn.
|
|
#
|
|
# ★ When To Use This Pattern:
|
|
# - The response must use fresh external context on every reasoning turn
|
|
# - A trusted action result deterministically changes the available response
|
|
# - Stale cached data would be worse than the extra read-only action call
|
|
#
|
|
# ★ Do Not Use This Pattern:
|
|
# - For optional lookups the model should call only when the user asks
|
|
# - To cache external facts for the rest of a conversation
|
|
# - To represent dialogue stages, current intent, or questions already asked
|
|
#
|
|
# The mutable values below are a turn-scoped bridge from trusted action output
|
|
# to deterministic instructions. The same block resets and overwrites them on
|
|
# every reasoning turn; there is no conversation-long `data_loaded` latch.
|
|
|
|
system:
|
|
instructions: |
|
|
Help customers with their current account-support request. Use the
|
|
freshly loaded account result for account facts. If no account is
|
|
found, explain that limitation without inventing customer details.
|
|
messages:
|
|
welcome: "Hello! How can I help with your account today?"
|
|
error: "I couldn't retrieve the account context. Please try again."
|
|
|
|
access:
|
|
default_agent_user: "agent@company.salesforce.com"
|
|
|
|
config:
|
|
developer_name: "Fresh_Account_Context_Agent"
|
|
agent_label: "Fresh Account Context Agent"
|
|
description: "Demonstrates a required read-only action inside procedural instructions"
|
|
|
|
variables:
|
|
ContactId: linked string
|
|
source: @MessagingEndUser.ContactId
|
|
description: "Trusted contact identifier used by the account lookup"
|
|
|
|
account_found: mutable boolean = False
|
|
description: "Reset and overwritten from lookup output on every reasoning turn; read by the response branches"
|
|
customer_name: mutable string = ""
|
|
description: "Reset and overwritten from lookup output on every reasoning turn; used only in the current response"
|
|
customer_tier: mutable string = ""
|
|
description: "Reset and overwritten from lookup output on every reasoning turn; used only in the current response"
|
|
|
|
language:
|
|
default_locale: "en_US"
|
|
|
|
start_agent account_support:
|
|
label: "Account Support"
|
|
description: "Handles account questions using freshly loaded customer context"
|
|
|
|
actions:
|
|
load_customer:
|
|
description: "Read the current customer profile for this turn"
|
|
inputs:
|
|
contact_id: string
|
|
description: "Trusted contact ID to look up"
|
|
is_required: True
|
|
outputs:
|
|
found: boolean
|
|
description: "Whether a matching customer profile was found"
|
|
name: string
|
|
description: "Current customer display name"
|
|
tier: string
|
|
description: "Current customer service tier"
|
|
target: "flow://Get_Customer_Profile"
|
|
|
|
reasoning:
|
|
instructions: ->
|
|
# Reset first so an empty or failed lookup cannot reuse prior facts.
|
|
set @variables.account_found = False
|
|
set @variables.customer_name = ""
|
|
set @variables.customer_tier = ""
|
|
|
|
# This read-only lookup runs on every reasoning turn. Its outputs
|
|
# overwrite the turn-scoped bridge values above.
|
|
run @actions.load_customer
|
|
with contact_id=@variables.ContactId
|
|
set @variables.account_found = @outputs.found
|
|
set @variables.customer_name = @outputs.name
|
|
set @variables.customer_tier = @outputs.tier
|
|
|
|
if @variables.account_found == False:
|
|
| Explain that no current account profile was found. Ask the
|
|
user to verify their channel identity or request a human.
|
|
else if @variables.customer_tier == "vip":
|
|
| Address {!@variables.customer_name} by name and provide
|
|
priority help for the latest account-support request.
|
|
else:
|
|
| Address {!@variables.customer_name} by name and help with the
|
|
latest account-support request.
|
|
|
|
actions:
|
|
escalate_to_human: @utils.escalate
|
|
description: "Transfer when the user explicitly requests a human or the account cannot be resolved"
|
|
|
|
# ★ Procedural vs. Declarative Actions
|
|
#
|
|
# `run @actions.load_customer` above is procedural: the runtime executes it
|
|
# before assembling the model-visible response instructions.
|
|
#
|
|
# An action exposed only under `reasoning.actions` is declarative: the model
|
|
# decides whether to call it for the current request.
|
|
#
|
|
# Prefer declarative actions for optional work. Use procedural execution only
|
|
# when the fresh result is required on every pass through the block.
|