@salesforce/afv-skills 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/skills/agentforce-development/SKILL.md +427 -0
- package/skills/agentforce-development/assets/README-legacy.md +89 -0
- package/skills/agentforce-development/assets/agent-spec-template.md +90 -0
- package/skills/agentforce-development/assets/agents/README.md +45 -0
- package/skills/agentforce-development/assets/agents/hello-world.agent +60 -0
- package/skills/agentforce-development/assets/agents/multi-topic.agent +105 -0
- package/skills/agentforce-development/assets/agents/production-faq.agent +101 -0
- package/skills/agentforce-development/assets/agents/production-faq.bundle-meta.xml +4 -0
- package/skills/agentforce-development/assets/agents/simple-qa.agent +72 -0
- package/skills/agentforce-development/assets/apex/models-api-queueable.cls +225 -0
- package/skills/agentforce-development/assets/bundle-meta.xml +23 -0
- package/skills/agentforce-development/assets/components/apex-action.agent +52 -0
- package/skills/agentforce-development/assets/components/error-handling.agent +58 -0
- package/skills/agentforce-development/assets/components/escalation-setup.agent +169 -0
- package/skills/agentforce-development/assets/components/flow-action.agent +66 -0
- package/skills/agentforce-development/assets/components/n-ary-conditions.agent +110 -0
- package/skills/agentforce-development/assets/components/topic-with-actions.agent +40 -0
- package/skills/agentforce-development/assets/deterministic-routing.agent +166 -0
- package/skills/agentforce-development/assets/escalation-pattern.agent +209 -0
- package/skills/agentforce-development/assets/flow-action-lookup.agent +115 -0
- package/skills/agentforce-development/assets/hub-and-spoke.agent +104 -0
- package/skills/agentforce-development/assets/invocable-apex-template.cls +187 -0
- package/skills/agentforce-development/assets/local-info-agent-annotated.agent +355 -0
- package/skills/agentforce-development/assets/metadata/basic-prompt-template.promptTemplate-meta.xml +109 -0
- package/skills/agentforce-development/assets/metadata/genai-function-apex.xml +92 -0
- package/skills/agentforce-development/assets/metadata/genai-function-flow.xml +57 -0
- package/skills/agentforce-development/assets/metadata/genai-plugin.xml +72 -0
- package/skills/agentforce-development/assets/metadata/http-callout-flow.flow-meta.xml +348 -0
- package/skills/agentforce-development/assets/metadata/record-grounded-prompt.promptTemplate-meta.xml +136 -0
- package/skills/agentforce-development/assets/minimal-starter.agent +42 -0
- package/skills/agentforce-development/assets/patterns/README.md +254 -0
- package/skills/agentforce-development/assets/patterns/action-callbacks.agent +178 -0
- package/skills/agentforce-development/assets/patterns/advanced-input-bindings.agent +141 -0
- package/skills/agentforce-development/assets/patterns/bidirectional-routing.agent +156 -0
- package/skills/agentforce-development/assets/patterns/critical-input-collection.agent +244 -0
- package/skills/agentforce-development/assets/patterns/delegation-routing.agent +89 -0
- package/skills/agentforce-development/assets/patterns/lifecycle-events.agent +127 -0
- package/skills/agentforce-development/assets/patterns/llm-controlled-actions.agent +184 -0
- package/skills/agentforce-development/assets/patterns/multi-step-workflow.agent +282 -0
- package/skills/agentforce-development/assets/patterns/open-gate-routing.agent +286 -0
- package/skills/agentforce-development/assets/patterns/procedural-instructions.agent +273 -0
- package/skills/agentforce-development/assets/patterns/prompt-template-action.agent +188 -0
- package/skills/agentforce-development/assets/patterns/system-instruction-overrides.agent +293 -0
- package/skills/agentforce-development/assets/prompt-rag-search.agent +131 -0
- package/skills/agentforce-development/assets/template-multi-topic.agent +160 -0
- package/skills/agentforce-development/assets/template-single-topic.agent +81 -0
- package/skills/agentforce-development/assets/verification-gate.agent +208 -0
- package/skills/agentforce-development/references/action-prompt-templates.md +164 -0
- package/skills/agentforce-development/references/actions-reference.md +592 -0
- package/skills/agentforce-development/references/agent-access-guide.md +72 -0
- package/skills/agentforce-development/references/agent-design-and-spec-creation.md +1010 -0
- package/skills/agentforce-development/references/agent-metadata-and-lifecycle.md +575 -0
- package/skills/agentforce-development/references/agent-script-core-language.md +1218 -0
- package/skills/agentforce-development/references/agent-topic-map-diagrams.md +323 -0
- package/skills/agentforce-development/references/agent-user-setup.md +526 -0
- package/skills/agentforce-development/references/agent-validation-and-debugging.md +803 -0
- package/skills/agentforce-development/references/known-issues.md +353 -0
- package/skills/agentforce-development/references/minimal-examples.md +67 -0
- package/skills/agentforce-development/references/production-gotchas.md +279 -0
- package/skills/agentforce-development/references/salesforce-cli-for-agents.md +393 -0
- package/skills/agentforce-development/references/version-history.md +23 -0
- package/skills/generate-permission-set/SKILL.md +174 -0
- package/skills/salesforce-custom-application/SKILL.md +1 -2
- package/skills/salesforce-custom-field/SKILL.md +0 -4
- package/skills/salesforce-custom-tab/SKILL.md +84 -8
- package/skills/salesforce-experience-lwr-site/SKILL.md +196 -0
- package/skills/salesforce-experience-lwr-site/docs/bootstrap-template-byo-lwr.md +224 -0
- package/skills/salesforce-experience-lwr-site/docs/configure-content-brandingSet.md +131 -0
- package/skills/salesforce-experience-lwr-site/docs/configure-content-route.md +232 -0
- package/skills/salesforce-experience-lwr-site/docs/configure-content-themeLayout.md +141 -0
- package/skills/salesforce-experience-lwr-site/docs/configure-content-view.md +233 -0
- package/skills/salesforce-experience-lwr-site/docs/configure-guest-sharing-rules.md +42 -0
- package/skills/salesforce-experience-lwr-site/docs/handle-component-and-region-ids.md +27 -0
- package/skills/salesforce-experience-lwr-site/docs/handle-ui-components.md +215 -0
- package/skills/salesforce-flow/SKILL.md +2 -2
- package/skills/salesforce-fragment/SKILL.md +85 -10
- package/skills/salesforce-lightning-app-build/SKILL.md +102 -10
- package/skills/apex-class/SKILL.md +0 -253
- package/skills/apex-class/examples/AccountDeduplicationBatch.cls +0 -148
- package/skills/apex-class/examples/AccountSelector.cls +0 -193
- package/skills/apex-class/examples/AccountService.cls +0 -201
- package/skills/apex-class/templates/abstract.cls +0 -128
- package/skills/apex-class/templates/batch.cls +0 -125
- package/skills/apex-class/templates/domain.cls +0 -102
- package/skills/apex-class/templates/dto.cls +0 -108
- package/skills/apex-class/templates/exception.cls +0 -51
- package/skills/apex-class/templates/interface.cls +0 -25
- package/skills/apex-class/templates/queueable.cls +0 -92
- package/skills/apex-class/templates/schedulable.cls +0 -75
- package/skills/apex-class/templates/selector.cls +0 -92
- package/skills/apex-class/templates/service.cls +0 -69
- package/skills/apex-class/templates/utility.cls +0 -97
- package/skills/apex-test-class/SKILL.md +0 -101
- package/skills/apex-test-class/references/assertion-patterns.md +0 -209
- package/skills/apex-test-class/references/async-testing.md +0 -276
- package/skills/apex-test-class/references/mocking-patterns.md +0 -219
- package/skills/apex-test-class/references/test-data-factory.md +0 -176
- package/skills/deployment-readiness-check/SKILL.md +0 -257
- package/skills/deployment-readiness-check/assets/deployment_checklist.md +0 -286
- package/skills/deployment-readiness-check/references/rollback_procedures.md +0 -308
- package/skills/deployment-readiness-check/scripts/check_metadata.sh +0 -207
- package/skills/salesforce-experience-site/SKILL.md +0 -178
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Escalation Pattern Template
|
|
2
|
+
# ===========================
|
|
3
|
+
#
|
|
4
|
+
# This template demonstrates the complete escalation pattern with:
|
|
5
|
+
# - Multi-channel connection blocks (messaging, voice, web)
|
|
6
|
+
# - Graceful handoff with escalation messages
|
|
7
|
+
# - Pre-escalation data gathering
|
|
8
|
+
# - OmniChannel routing configuration
|
|
9
|
+
#
|
|
10
|
+
# Pattern: Multi-channel escalation with context preservation
|
|
11
|
+
# Use when: Any agent that needs human handoff capabilities
|
|
12
|
+
|
|
13
|
+
system:
|
|
14
|
+
messages:
|
|
15
|
+
welcome: "Hello! I'm here to help. If I can't assist you, I can connect you with a specialist."
|
|
16
|
+
error: "I apologize, something went wrong. Let me connect you with someone who can help."
|
|
17
|
+
instructions: "You are a helpful agent. When you cannot resolve an issue, escalate to a human agent with full context."
|
|
18
|
+
|
|
19
|
+
config:
|
|
20
|
+
agent_name: "EscalationPatternAgent"
|
|
21
|
+
agent_label: "Escalation Demo Agent"
|
|
22
|
+
description: "Agent demonstrating complete escalation patterns"
|
|
23
|
+
default_agent_user: "agent@yourorg.com" # REQUIRED: Change to valid Einstein Agent User
|
|
24
|
+
|
|
25
|
+
# ============================================================
|
|
26
|
+
# CONNECTION BLOCKS (Multi-Channel Escalation)
|
|
27
|
+
# ============================================================
|
|
28
|
+
|
|
29
|
+
connections:
|
|
30
|
+
# Messaging channel (SMS, WhatsApp, etc.)
|
|
31
|
+
connection messaging:
|
|
32
|
+
escalation_message: "One moment, I'm transferring our conversation to a specialist who can better assist you."
|
|
33
|
+
outbound_route_type: "OmniChannelFlow"
|
|
34
|
+
outbound_route_name: "<flow://Escalate_Messaging_To_Agent>"
|
|
35
|
+
adaptive_response_allowed: False
|
|
36
|
+
|
|
37
|
+
# Voice channel
|
|
38
|
+
connection voice:
|
|
39
|
+
escalation_message: "Please hold while I transfer you to a specialist. They will have full context of our conversation."
|
|
40
|
+
outbound_route_type: "Queue"
|
|
41
|
+
outbound_route_name: "Customer_Support_Queue"
|
|
42
|
+
adaptive_response_allowed: True
|
|
43
|
+
|
|
44
|
+
# Web chat channel
|
|
45
|
+
connection web:
|
|
46
|
+
escalation_message: "Connecting you with a live agent now. They'll be with you shortly."
|
|
47
|
+
outbound_route_type: "OmniChannelFlow"
|
|
48
|
+
outbound_route_name: "<flow://Web_Chat_Escalation_Flow>"
|
|
49
|
+
adaptive_response_allowed: False
|
|
50
|
+
|
|
51
|
+
variables:
|
|
52
|
+
# Customer context
|
|
53
|
+
customer_name: mutable string = ""
|
|
54
|
+
description: "Customer's name for personalization"
|
|
55
|
+
customer_issue: mutable string = ""
|
|
56
|
+
description: "Summary of customer's issue"
|
|
57
|
+
issue_category: mutable string = ""
|
|
58
|
+
description: "Category of issue for routing"
|
|
59
|
+
|
|
60
|
+
# Escalation state
|
|
61
|
+
escalation_reason: mutable string = ""
|
|
62
|
+
description: "Reason for escalation"
|
|
63
|
+
attempts_before_escalation: mutable number = 0
|
|
64
|
+
description: "Number of resolution attempts"
|
|
65
|
+
ready_to_escalate: mutable boolean = False
|
|
66
|
+
description: "Whether pre-escalation data is gathered"
|
|
67
|
+
|
|
68
|
+
start_agent entry:
|
|
69
|
+
description: "Entry point - greet and assess needs"
|
|
70
|
+
reasoning:
|
|
71
|
+
instructions: |
|
|
72
|
+
Greet the customer and understand their needs.
|
|
73
|
+
Try to help directly, escalate if needed.
|
|
74
|
+
actions:
|
|
75
|
+
go_support: @utils.transition to @topic.support
|
|
76
|
+
description: "Help with support issue"
|
|
77
|
+
|
|
78
|
+
# ============================================================
|
|
79
|
+
# SUPPORT TOPIC (With Escalation Triggers)
|
|
80
|
+
# ============================================================
|
|
81
|
+
|
|
82
|
+
topic support:
|
|
83
|
+
description: "Attempt to resolve issue, escalate if unable"
|
|
84
|
+
reasoning:
|
|
85
|
+
instructions: ->
|
|
86
|
+
# POST-ACTION: Check if escalation was triggered
|
|
87
|
+
if @variables.ready_to_escalate == True:
|
|
88
|
+
transition to @topic.pre_escalation
|
|
89
|
+
|
|
90
|
+
# Track attempts
|
|
91
|
+
| I'm here to help you with your issue.
|
|
92
|
+
|
|
93
|
+
if @variables.attempts_before_escalation >= 2:
|
|
94
|
+
| It seems like I'm having trouble resolving this.
|
|
95
|
+
| Would you like me to connect you with a specialist?
|
|
96
|
+
|
|
97
|
+
actions:
|
|
98
|
+
# Attempt resolution
|
|
99
|
+
try_resolve: @actions.Attempt_Resolution
|
|
100
|
+
description: "Try to resolve the issue"
|
|
101
|
+
with issue = ... # LLM extracts from conversation
|
|
102
|
+
set @variables.customer_issue = @outputs.issue_summary
|
|
103
|
+
set @variables.issue_category = @outputs.category
|
|
104
|
+
set @variables.attempts_before_escalation = @variables.attempts_before_escalation + 1
|
|
105
|
+
|
|
106
|
+
# User-initiated escalation
|
|
107
|
+
request_human: @utils.setVariables
|
|
108
|
+
description: "I'd like to speak with a human"
|
|
109
|
+
with escalation_reason = "Customer requested human agent"
|
|
110
|
+
with ready_to_escalate = True
|
|
111
|
+
|
|
112
|
+
# Agent-initiated escalation (after failed attempts)
|
|
113
|
+
escalate_complex: @utils.setVariables
|
|
114
|
+
description: "Connect me with a specialist"
|
|
115
|
+
available when @variables.attempts_before_escalation >= 2
|
|
116
|
+
with escalation_reason = "Unable to resolve after multiple attempts"
|
|
117
|
+
with ready_to_escalate = True
|
|
118
|
+
|
|
119
|
+
# ============================================================
|
|
120
|
+
# PRE-ESCALATION TOPIC (Gather Context)
|
|
121
|
+
# ============================================================
|
|
122
|
+
|
|
123
|
+
topic pre_escalation:
|
|
124
|
+
description: "Gather information before escalating"
|
|
125
|
+
reasoning:
|
|
126
|
+
instructions: ->
|
|
127
|
+
# Ensure we have customer name for personalization
|
|
128
|
+
if @variables.customer_name == "":
|
|
129
|
+
| Before I transfer you, may I have your name so the specialist can address you properly?
|
|
130
|
+
else:
|
|
131
|
+
| Thank you, {!@variables.customer_name}. Let me prepare the transfer.
|
|
132
|
+
|
|
133
|
+
# Display summary of what we'll share
|
|
134
|
+
if @variables.customer_name != "" and @variables.customer_issue != "":
|
|
135
|
+
| I'll share the following with the specialist:
|
|
136
|
+
| - Your issue: {!@variables.customer_issue}
|
|
137
|
+
| - Category: {!@variables.issue_category}
|
|
138
|
+
| - Reason for transfer: {!@variables.escalation_reason}
|
|
139
|
+
|
|
|
140
|
+
| Ready to connect you now.
|
|
141
|
+
transition to @topic.escalation
|
|
142
|
+
|
|
143
|
+
actions:
|
|
144
|
+
# Capture customer name
|
|
145
|
+
save_name: @utils.setVariables
|
|
146
|
+
description: "Save customer name"
|
|
147
|
+
available when @variables.customer_name == ""
|
|
148
|
+
with customer_name = ... # LLM extracts name from response
|
|
149
|
+
|
|
150
|
+
# Proceed to escalation
|
|
151
|
+
proceed: @utils.transition to @topic.escalation
|
|
152
|
+
description: "Proceed with transfer"
|
|
153
|
+
available when @variables.customer_name != ""
|
|
154
|
+
|
|
155
|
+
# Cancel escalation
|
|
156
|
+
cancel_escalation: @utils.setVariables
|
|
157
|
+
description: "Actually, let me try again with the bot"
|
|
158
|
+
with ready_to_escalate = False
|
|
159
|
+
with escalation_reason = ""
|
|
160
|
+
run @utils.transition to @topic.support
|
|
161
|
+
|
|
162
|
+
# ============================================================
|
|
163
|
+
# ESCALATION TOPIC (Handoff)
|
|
164
|
+
# ============================================================
|
|
165
|
+
|
|
166
|
+
topic escalation:
|
|
167
|
+
description: "Execute escalation to human agent"
|
|
168
|
+
reasoning:
|
|
169
|
+
instructions: ->
|
|
170
|
+
# Log escalation context (this gets passed to human agent)
|
|
171
|
+
run @actions.Log_Escalation_Context
|
|
172
|
+
with customer_name = @variables.customer_name
|
|
173
|
+
with issue_summary = @variables.customer_issue
|
|
174
|
+
with category = @variables.issue_category
|
|
175
|
+
with reason = @variables.escalation_reason
|
|
176
|
+
with attempt_count = @variables.attempts_before_escalation
|
|
177
|
+
|
|
178
|
+
| Transferring you now. Thank you for your patience!
|
|
179
|
+
|
|
180
|
+
actions:
|
|
181
|
+
# The actual escalation - uses connection block configuration
|
|
182
|
+
handoff: @utils.escalate
|
|
183
|
+
description: "Transfer to human agent"
|
|
184
|
+
|
|
185
|
+
# ============================================================
|
|
186
|
+
# OPTIONAL: SPECIALIZED ESCALATION QUEUES
|
|
187
|
+
# ============================================================
|
|
188
|
+
|
|
189
|
+
topic escalate_billing:
|
|
190
|
+
description: "Escalate specifically to billing team"
|
|
191
|
+
reasoning:
|
|
192
|
+
instructions: |
|
|
193
|
+
I'm connecting you with our billing specialists.
|
|
194
|
+
They'll be able to help with your account questions.
|
|
195
|
+
actions:
|
|
196
|
+
# Note: In production, you'd configure this action
|
|
197
|
+
# to route to a specific billing queue
|
|
198
|
+
billing_handoff: @utils.escalate
|
|
199
|
+
description: "Transfer to billing team"
|
|
200
|
+
|
|
201
|
+
topic escalate_technical:
|
|
202
|
+
description: "Escalate specifically to technical support"
|
|
203
|
+
reasoning:
|
|
204
|
+
instructions: |
|
|
205
|
+
I'm connecting you with our technical support team.
|
|
206
|
+
They specialize in resolving complex technical issues.
|
|
207
|
+
actions:
|
|
208
|
+
tech_handoff: @utils.escalate
|
|
209
|
+
description: "Transfer to technical support"
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Flow Action Lookup Template
|
|
2
|
+
# ============================
|
|
3
|
+
#
|
|
4
|
+
# This template demonstrates the pattern for calling Flow actions
|
|
5
|
+
# that return complex data types (SObjects, lists, custom types).
|
|
6
|
+
#
|
|
7
|
+
# Pattern: Data lookup and display using Flow actions
|
|
8
|
+
# Use when: Fetching records from Salesforce (Cases, Orders, Accounts)
|
|
9
|
+
#
|
|
10
|
+
# CRITICAL: When defining Flow action outputs in Agentforce Assets:
|
|
11
|
+
# - For SObject returns: complex_data_type_name = "lightning__recordInfoType"
|
|
12
|
+
# - For list[string]: complex_data_type_name = "lightning__textType"
|
|
13
|
+
# - For currency: complex_data_type_name = "lightning__currencyType"
|
|
14
|
+
|
|
15
|
+
system:
|
|
16
|
+
messages:
|
|
17
|
+
welcome: "Hello! I can help you look up order information."
|
|
18
|
+
error: "I apologize, something went wrong retrieving your data."
|
|
19
|
+
instructions: "You are a customer service agent helping users look up their orders."
|
|
20
|
+
|
|
21
|
+
config:
|
|
22
|
+
agent_name: "FlowActionLookupAgent"
|
|
23
|
+
agent_label: "Order Lookup Agent"
|
|
24
|
+
description: "Agent demonstrating Flow action patterns with complex data types"
|
|
25
|
+
default_agent_user: "agent@yourorg.com" # REQUIRED: Change to valid Einstein Agent User
|
|
26
|
+
|
|
27
|
+
variables:
|
|
28
|
+
# Customer context (from session)
|
|
29
|
+
customer_id: linked string
|
|
30
|
+
source: @session.customerId
|
|
31
|
+
description: "Customer ID from session context"
|
|
32
|
+
|
|
33
|
+
# Order data (populated by Flow action)
|
|
34
|
+
order_id: mutable string = ""
|
|
35
|
+
description: "Current order being viewed"
|
|
36
|
+
order_status: mutable string = ""
|
|
37
|
+
description: "Order status from lookup"
|
|
38
|
+
order_total: mutable string = ""
|
|
39
|
+
description: "Order total amount"
|
|
40
|
+
order_date: mutable string = ""
|
|
41
|
+
description: "Order date"
|
|
42
|
+
|
|
43
|
+
# Error handling
|
|
44
|
+
lookup_error: mutable boolean = False
|
|
45
|
+
description: "Whether lookup encountered an error"
|
|
46
|
+
|
|
47
|
+
start_agent entry:
|
|
48
|
+
description: "Entry point - welcome and route to order lookup"
|
|
49
|
+
reasoning:
|
|
50
|
+
instructions: |
|
|
51
|
+
Welcome the customer and offer to help with order lookups.
|
|
52
|
+
actions:
|
|
53
|
+
go_lookup: @utils.transition to @topic.order_lookup
|
|
54
|
+
description: "Start order lookup"
|
|
55
|
+
|
|
56
|
+
# ============================================================
|
|
57
|
+
# ORDER LOOKUP TOPIC (Flow Action Pattern)
|
|
58
|
+
# ============================================================
|
|
59
|
+
|
|
60
|
+
topic order_lookup:
|
|
61
|
+
description: "Look up order details using Flow action"
|
|
62
|
+
reasoning:
|
|
63
|
+
instructions: ->
|
|
64
|
+
# POST-ACTION CHECK: Display results if order was found
|
|
65
|
+
if @variables.order_status != "":
|
|
66
|
+
| **Order Details**
|
|
67
|
+
| - Order ID: {!@variables.order_id}
|
|
68
|
+
| - Status: {!@variables.order_status}
|
|
69
|
+
| - Total: {!@variables.order_total}
|
|
70
|
+
| - Date: {!@variables.order_date}
|
|
71
|
+
|
|
|
72
|
+
| Is there anything else you'd like to know about this order?
|
|
73
|
+
|
|
74
|
+
# ERROR CHECK: Handle lookup failures
|
|
75
|
+
if @variables.lookup_error == True:
|
|
76
|
+
| I couldn't find that order. Please check the order ID and try again.
|
|
77
|
+
set @variables.lookup_error = False
|
|
78
|
+
|
|
79
|
+
# INITIAL STATE: Ask for order ID
|
|
80
|
+
if @variables.order_id == "":
|
|
81
|
+
| What order would you like me to look up?
|
|
82
|
+
| Please provide your order ID.
|
|
83
|
+
|
|
84
|
+
actions:
|
|
85
|
+
# Flow action with SObject return type
|
|
86
|
+
# In Agentforce Assets, set outputs.order_record complex_data_type_name = "lightning__recordInfoType"
|
|
87
|
+
lookup_order: @actions.Get_Order_Details
|
|
88
|
+
description: "Look up order by ID"
|
|
89
|
+
with order_id = ... # LLM extracts from user message
|
|
90
|
+
include_in_progress_indicator: True
|
|
91
|
+
progress_indicator_message: "Looking up your order..."
|
|
92
|
+
set @variables.order_id = @outputs.order_id
|
|
93
|
+
set @variables.order_status = @outputs.status
|
|
94
|
+
set @variables.order_total = @outputs.total_amount
|
|
95
|
+
set @variables.order_date = @outputs.order_date
|
|
96
|
+
# Error handling: check if lookup failed
|
|
97
|
+
if @outputs.found == False:
|
|
98
|
+
set @variables.lookup_error = True
|
|
99
|
+
|
|
100
|
+
# Flow action returning a list of strings
|
|
101
|
+
# In Agentforce Assets, set outputs.product_names complex_data_type_name = "lightning__textType"
|
|
102
|
+
get_items: @actions.Get_Order_Line_Items
|
|
103
|
+
description: "Get list of items in the order"
|
|
104
|
+
available when @variables.order_id != ""
|
|
105
|
+
with order_id = @variables.order_id
|
|
106
|
+
|
|
107
|
+
clear_search: @utils.setVariables
|
|
108
|
+
description: "Search for a different order"
|
|
109
|
+
with order_id = ""
|
|
110
|
+
with order_status = ""
|
|
111
|
+
with order_total = ""
|
|
112
|
+
with order_date = ""
|
|
113
|
+
|
|
114
|
+
escalate_now: @utils.escalate
|
|
115
|
+
description: "Transfer to human agent"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Hub-and-Spoke Architecture Template
|
|
2
|
+
# ====================================
|
|
3
|
+
#
|
|
4
|
+
# This template demonstrates the Hub-and-Spoke pattern where a central
|
|
5
|
+
# topic_selector (hub) routes conversations to specialized topics (spokes).
|
|
6
|
+
#
|
|
7
|
+
# Pattern: Multi-purpose agents handling distinct request types
|
|
8
|
+
# Use when: Users may have different intents (orders, support, returns)
|
|
9
|
+
|
|
10
|
+
system:
|
|
11
|
+
messages:
|
|
12
|
+
welcome: "Welcome! I can help with orders, returns, or general support."
|
|
13
|
+
error: "I apologize, something went wrong. Let me try again."
|
|
14
|
+
instructions: "You are a customer service agent for an e-commerce company."
|
|
15
|
+
|
|
16
|
+
config:
|
|
17
|
+
agent_name: "HubAndSpokeAgent"
|
|
18
|
+
agent_label: "Customer Service Agent"
|
|
19
|
+
description: "Multi-purpose agent with hub-and-spoke architecture"
|
|
20
|
+
default_agent_user: "agent@yourorg.com" # REQUIRED: Change to valid Einstein Agent User
|
|
21
|
+
|
|
22
|
+
variables:
|
|
23
|
+
customer_id: linked string
|
|
24
|
+
source: @session.customerId
|
|
25
|
+
description: "Customer ID from session"
|
|
26
|
+
order_id: mutable string = ""
|
|
27
|
+
description: "Current order being discussed"
|
|
28
|
+
issue_resolved: mutable boolean = False
|
|
29
|
+
description: "Whether the issue has been resolved"
|
|
30
|
+
|
|
31
|
+
# ============================================================
|
|
32
|
+
# HUB: Central Router
|
|
33
|
+
# ============================================================
|
|
34
|
+
|
|
35
|
+
start_agent topic_selector:
|
|
36
|
+
description: "Route to appropriate topic based on user intent"
|
|
37
|
+
reasoning:
|
|
38
|
+
instructions: |
|
|
39
|
+
Determine what the customer needs and route accordingly:
|
|
40
|
+
- Order questions → orders topic
|
|
41
|
+
- Return/refund requests → returns topic
|
|
42
|
+
- General questions → support topic
|
|
43
|
+
actions:
|
|
44
|
+
check_order: @utils.transition to @topic.orders
|
|
45
|
+
description: "Customer wants to check order status"
|
|
46
|
+
process_return: @utils.transition to @topic.returns
|
|
47
|
+
description: "Customer wants to return or refund"
|
|
48
|
+
general_help: @utils.transition to @topic.support
|
|
49
|
+
description: "General support questions"
|
|
50
|
+
|
|
51
|
+
# ============================================================
|
|
52
|
+
# SPOKE: Orders Topic
|
|
53
|
+
# ============================================================
|
|
54
|
+
|
|
55
|
+
topic orders:
|
|
56
|
+
description: "Handle order status and tracking inquiries"
|
|
57
|
+
reasoning:
|
|
58
|
+
instructions: ->
|
|
59
|
+
| Help the customer with their order inquiry.
|
|
60
|
+
|
|
61
|
+
if @variables.order_id != "":
|
|
62
|
+
| Current order: {!@variables.order_id}
|
|
63
|
+
|
|
64
|
+
actions:
|
|
65
|
+
lookup_order: @actions.get_order_status
|
|
66
|
+
description: "Look up order details"
|
|
67
|
+
with order_id = @variables.order_id
|
|
68
|
+
back_to_hub: @utils.transition to @topic.topic_selector
|
|
69
|
+
description: "Return to main menu"
|
|
70
|
+
|
|
71
|
+
# ============================================================
|
|
72
|
+
# SPOKE: Returns Topic
|
|
73
|
+
# ============================================================
|
|
74
|
+
|
|
75
|
+
topic returns:
|
|
76
|
+
description: "Handle return and refund requests"
|
|
77
|
+
reasoning:
|
|
78
|
+
instructions: ->
|
|
79
|
+
| Help the customer with their return or refund request.
|
|
80
|
+
| Verify the order details before processing.
|
|
81
|
+
|
|
82
|
+
actions:
|
|
83
|
+
start_return: @actions.initiate_return
|
|
84
|
+
description: "Start a return process"
|
|
85
|
+
process_refund: @actions.process_refund
|
|
86
|
+
description: "Process a refund"
|
|
87
|
+
back_to_hub: @utils.transition to @topic.topic_selector
|
|
88
|
+
description: "Return to main menu"
|
|
89
|
+
|
|
90
|
+
# ============================================================
|
|
91
|
+
# SPOKE: Support Topic
|
|
92
|
+
# ============================================================
|
|
93
|
+
|
|
94
|
+
topic support:
|
|
95
|
+
description: "Handle general support questions"
|
|
96
|
+
reasoning:
|
|
97
|
+
instructions: |
|
|
98
|
+
Help the customer with general questions.
|
|
99
|
+
If the question requires specialized help, route appropriately.
|
|
100
|
+
actions:
|
|
101
|
+
escalate: @utils.escalate
|
|
102
|
+
description: "Transfer to human agent"
|
|
103
|
+
back_to_hub: @utils.transition to @topic.topic_selector
|
|
104
|
+
description: "Return to main menu"
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invocable Apex template for Agent Script action backing logic.
|
|
3
|
+
*
|
|
4
|
+
* Wire this class to an Agent Script action with:
|
|
5
|
+
* target: "apex://{{ClassName}}"
|
|
6
|
+
*
|
|
7
|
+
* The @InvocableVariable field names on Request and Result become the
|
|
8
|
+
* action's input and output names in the .agent file. They must match
|
|
9
|
+
* character-for-character — including case.
|
|
10
|
+
*
|
|
11
|
+
* STUB USAGE: To create a minimal stub for unblocking deployment,
|
|
12
|
+
* delete the business logic in execute() and return hardcoded values.
|
|
13
|
+
* Do not add mock data, conditional logic, or JSON serialization to
|
|
14
|
+
* stubs — keep them minimal.
|
|
15
|
+
*
|
|
16
|
+
* Replace all {{placeholders}} before use.
|
|
17
|
+
*/
|
|
18
|
+
public with sharing class {{ClassName}} {
|
|
19
|
+
|
|
20
|
+
// ─── INVOCABLE METHOD ────────────────────────────────────────────
|
|
21
|
+
//
|
|
22
|
+
// Must be: static, accept List<Request>, return List<Result>.
|
|
23
|
+
// This signature supports bulkification when the action is called
|
|
24
|
+
// for multiple records in a single transaction.
|
|
25
|
+
|
|
26
|
+
@InvocableMethod(
|
|
27
|
+
label='{{ActionLabel}}'
|
|
28
|
+
description='{{ActionDescription}}'
|
|
29
|
+
)
|
|
30
|
+
public static List<Result> execute(List<Request> requests) {
|
|
31
|
+
List<Result> results = new List<Result>();
|
|
32
|
+
|
|
33
|
+
// ── Bulkification: collect IDs first, query once ──
|
|
34
|
+
// Avoids SOQL-in-loop governor limit issues.
|
|
35
|
+
Set<Id> recordIds = new Set<Id>();
|
|
36
|
+
for (Request req : requests) {
|
|
37
|
+
if (req.recordId != null) {
|
|
38
|
+
recordIds.add(req.recordId);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ── USER_MODE ──
|
|
43
|
+
// `USER_MODE` enforces the running user's FLS/CRUD permissions.
|
|
44
|
+
// For service agents, the running user is the Einstein Agent User.
|
|
45
|
+
// If the user lacks read access to queried objects, queries return
|
|
46
|
+
// 0 rows with NO error — a silent failure. Verify object permissions
|
|
47
|
+
// before relying on `USER_MODE` queries.
|
|
48
|
+
|
|
49
|
+
// Static SOQL (Preferred): Use `WITH USER_MODE` clause:
|
|
50
|
+
Map<Id, {{SObjectName}}> recordsById = new Map<Id, {{SObjectName}}>();
|
|
51
|
+
if (!recordIds.isEmpty()) {
|
|
52
|
+
recordsById = new Map<Id, {{SObjectName}}>(
|
|
53
|
+
[SELECT Id, Name
|
|
54
|
+
FROM {{SObjectName}}
|
|
55
|
+
WHERE Id IN :recordIds
|
|
56
|
+
WITH USER_MODE]
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Dynamic SOQL (Optional): Use `AccessLevel.USER_MODE` parameter. DO NOT use `WITH USER_MODE` clause!
|
|
61
|
+
// WARNING! `WITH USER_MODE` inside a dynamic string causes:
|
|
62
|
+
// System.QueryException: unexpected token: 'WITH'
|
|
63
|
+
//
|
|
64
|
+
// WRONG:
|
|
65
|
+
// String q = 'SELECT Id, Name FROM {{SObjectName}} WHERE Id IN :recordIds WITH USER_MODE';
|
|
66
|
+
// recordsById = new Map<Id, {{SObjectName}}>(Database.query(q));
|
|
67
|
+
//
|
|
68
|
+
// RIGHT:
|
|
69
|
+
// String q = 'SELECT Id, Name FROM {{SObjectName}} WHERE Id IN :recordIds';
|
|
70
|
+
// recordsById = new Map<Id, {{SObjectName}}>(Database.query(q, AccessLevel.USER_MODE));
|
|
71
|
+
|
|
72
|
+
// ── Process each request ──
|
|
73
|
+
for (Request req : requests) {
|
|
74
|
+
Result r = new Result();
|
|
75
|
+
try {
|
|
76
|
+
{{SObjectName}} record = recordsById.get(req.recordId);
|
|
77
|
+
if (record == null) {
|
|
78
|
+
r = errorResult('Record not found: ' + req.recordId);
|
|
79
|
+
} else {
|
|
80
|
+
// TODO: Replace with actual business logic
|
|
81
|
+
r.isSuccess = true;
|
|
82
|
+
r.outputMessage = 'Processed: ' + record.Name;
|
|
83
|
+
r.outputRecordId = record.Id;
|
|
84
|
+
}
|
|
85
|
+
} catch (Exception e) {
|
|
86
|
+
r = errorResult(e.getMessage());
|
|
87
|
+
}
|
|
88
|
+
results.add(r);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return results;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ─── REQUEST WRAPPER ─────────────────────────────────────────────
|
|
95
|
+
//
|
|
96
|
+
// Each @InvocableVariable becomes an action input in Agent Script.
|
|
97
|
+
// The field name here must exactly match the input name in the
|
|
98
|
+
// .agent file's action definition.
|
|
99
|
+
//
|
|
100
|
+
// Supported types: Boolean, Date, DateTime, Decimal, Double,
|
|
101
|
+
// Integer, Long, String, Id, Time, SObject types, List<T>
|
|
102
|
+
|
|
103
|
+
public class Request {
|
|
104
|
+
@InvocableVariable(
|
|
105
|
+
label='Record ID'
|
|
106
|
+
description='ID of the record to process'
|
|
107
|
+
required=true
|
|
108
|
+
)
|
|
109
|
+
public Id recordId;
|
|
110
|
+
|
|
111
|
+
@InvocableVariable(
|
|
112
|
+
label='Operation Type'
|
|
113
|
+
description='Type of operation to perform'
|
|
114
|
+
required=false
|
|
115
|
+
)
|
|
116
|
+
public String operationType;
|
|
117
|
+
|
|
118
|
+
@InvocableVariable(
|
|
119
|
+
label='Amount'
|
|
120
|
+
description='Numeric amount for calculations'
|
|
121
|
+
required=false
|
|
122
|
+
)
|
|
123
|
+
public Decimal amount;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ─── RESULT WRAPPER ──────────────────────────────────────────────
|
|
127
|
+
//
|
|
128
|
+
// Each @InvocableVariable becomes an action output in Agent Script.
|
|
129
|
+
// The field name here must exactly match the output name in the
|
|
130
|
+
// .agent file's action definition.
|
|
131
|
+
//
|
|
132
|
+
// Always include isSuccess and errorMessage for consistent error
|
|
133
|
+
// handling. The agent can check isSuccess to decide what to tell
|
|
134
|
+
// the user.
|
|
135
|
+
|
|
136
|
+
public class Result {
|
|
137
|
+
@InvocableVariable(
|
|
138
|
+
label='Is Success'
|
|
139
|
+
description='Whether the operation completed successfully'
|
|
140
|
+
)
|
|
141
|
+
public Boolean isSuccess;
|
|
142
|
+
|
|
143
|
+
@InvocableVariable(
|
|
144
|
+
label='Error Message'
|
|
145
|
+
description='Error message if operation failed'
|
|
146
|
+
)
|
|
147
|
+
public String errorMessage;
|
|
148
|
+
|
|
149
|
+
@InvocableVariable(
|
|
150
|
+
label='Output Message'
|
|
151
|
+
description='Human-readable result for the agent to relay'
|
|
152
|
+
)
|
|
153
|
+
public String outputMessage;
|
|
154
|
+
|
|
155
|
+
@InvocableVariable(
|
|
156
|
+
label='Output Record ID'
|
|
157
|
+
description='ID of the processed or created record'
|
|
158
|
+
)
|
|
159
|
+
public Id outputRecordId;
|
|
160
|
+
|
|
161
|
+
@InvocableVariable(
|
|
162
|
+
label='Output Value'
|
|
163
|
+
description='Primary result value'
|
|
164
|
+
)
|
|
165
|
+
public String outputValue;
|
|
166
|
+
|
|
167
|
+
@InvocableVariable(
|
|
168
|
+
label='Output Amount'
|
|
169
|
+
description='Numeric result for calculations'
|
|
170
|
+
)
|
|
171
|
+
public Decimal outputAmount;
|
|
172
|
+
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ── Error factory ──────────────────────────────────────────────────
|
|
176
|
+
//
|
|
177
|
+
// Centralizes error construction so every failure path sets both
|
|
178
|
+
// isSuccess = false and errorMessage consistently. Defined on the
|
|
179
|
+
// outer class because Apex prohibits static methods in inner classes.
|
|
180
|
+
|
|
181
|
+
private static Result errorResult(String message) {
|
|
182
|
+
Result r = new Result();
|
|
183
|
+
r.isSuccess = false;
|
|
184
|
+
r.errorMessage = message;
|
|
185
|
+
return r;
|
|
186
|
+
}
|
|
187
|
+
}
|