scc-universal 1.2.1 → 1.3.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.
Files changed (47) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.cursor/agents/sf-agentforce-agent.md +88 -40
  3. package/.cursor/skills/prompt-optimizer/SKILL.md +21 -21
  4. package/.cursor/skills/sf-2gp-security-review/SKILL.md +167 -0
  5. package/.cursor/skills/sf-agentforce-development/SKILL.md +385 -348
  6. package/.cursor/skills/sf-cli-reference/SKILL.md +221 -0
  7. package/.cursor/skills/sf-harness-audit/SKILL.md +2 -2
  8. package/.cursor/skills/sf-quickstart/SKILL.md +1 -1
  9. package/.cursor-plugin/plugin.json +1 -1
  10. package/README.md +8 -38
  11. package/agents/sf-agentforce-agent.md +88 -40
  12. package/docs/ARCHITECTURE.md +4 -3
  13. package/docs/authoring-guide.md +1 -1
  14. package/docs/hook-development.md +1 -1
  15. package/examples/agentforce-action/README.md +4 -4
  16. package/examples/devops-pipeline/README.md +4 -4
  17. package/examples/integration-pattern/README.md +4 -4
  18. package/examples/platform-events/README.md +4 -4
  19. package/examples/security-audit/README.md +3 -3
  20. package/examples/visualforce-migration/README.md +4 -4
  21. package/manifests/install-modules.json +9 -3
  22. package/package.json +2 -2
  23. package/scripts/lib/install-executor.js +23 -12
  24. package/skills/_reference/AGENTFORCE_PATTERNS.md +433 -51
  25. package/skills/_reference/APPEXCHANGE_REVIEW.md +427 -0
  26. package/skills/_reference/SF_CLI_COMMANDS.md +812 -0
  27. package/skills/prompt-optimizer/SKILL.md +21 -21
  28. package/skills/sf-2gp-security-review/SKILL.md +168 -0
  29. package/skills/sf-agentforce-development/SKILL.md +385 -348
  30. package/skills/sf-cli-reference/SKILL.md +225 -0
  31. package/skills/sf-harness-audit/SKILL.md +2 -2
  32. package/skills/sf-quickstart/SKILL.md +1 -1
  33. package/.cursor/hooks/adapter.js +0 -81
  34. package/.cursor/hooks/after-file-edit.js +0 -26
  35. package/.cursor/hooks/after-mcp-execution.js +0 -12
  36. package/.cursor/hooks/after-shell-execution.js +0 -30
  37. package/.cursor/hooks/after-tab-file-edit.js +0 -12
  38. package/.cursor/hooks/before-mcp-execution.js +0 -11
  39. package/.cursor/hooks/before-read-file.js +0 -13
  40. package/.cursor/hooks/before-shell-execution.js +0 -29
  41. package/.cursor/hooks/before-submit-prompt.js +0 -23
  42. package/.cursor/hooks/pre-compact.js +0 -7
  43. package/.cursor/hooks/session-end.js +0 -10
  44. package/.cursor/hooks/session-start.js +0 -10
  45. package/.cursor/hooks/stop.js +0 -18
  46. package/.cursor/hooks/subagent-start.js +0 -10
  47. package/.cursor/hooks/subagent-stop.js +0 -10
@@ -1,24 +1,24 @@
1
1
  ---
2
2
  name: sf-agentforce-development
3
- description: "Agentforce AI agent development — topics, actions, Prompt Templates, testing. Use when building or testing Agentforce agents. Do NOT use for non-Agentforce Apex or Flow-only automation."
3
+ description: "Agentforce agent development — Agent Script, topics, actions, testing, metadata. Use when building Agentforce agents. Do NOT use for non-Agentforce Apex or Flow-only automation."
4
4
  origin: SCC
5
5
  user-invocable: false
6
6
  ---
7
7
 
8
8
  # Agentforce Development
9
9
 
10
- Procedures for building Agentforce AI agents on the Salesforce platform. Architecture details, action type reference, instruction guidelines, and context engineering principles live in the reference file.
10
+ Procedures for building Agentforce AI agents. Architecture, syntax reference, metadata types, instruction guidelines, and context engineering principles live in the reference file.
11
11
 
12
12
  @../_reference/AGENTFORCE_PATTERNS.md
13
13
 
14
14
  ## When to Use
15
15
 
16
- - Building Agentforce AI agents from scratch
16
+ - Building Agentforce AI agents with Agent Script (`.agent` files)
17
+ - Generating and publishing authoring bundles via CLI
17
18
  - Configuring agent topics, actions, or conversation instructions
18
19
  - Creating custom Apex actions or Flow actions for Agentforce
19
- - Authoring or reviewing prompt templates for agent responses
20
- - Testing, debugging, or evaluating agent behavior in Agent Builder
21
- - Reviewing Agentforce limits or security requirements
20
+ - Testing agents with YAML test specs, CLI, or Testing Center
21
+ - Deploying agent metadata (GenAi types) to orgs
22
22
 
23
23
  ---
24
24
 
@@ -32,419 +32,456 @@ Procedures for building Agentforce AI agents on the Salesforce platform. Archite
32
32
 
33
33
  ---
34
34
 
35
- ## Topics: Defining Scope and Instructions
35
+ ## Development Approaches
36
36
 
37
- Topics are the primary organisational unit for agent capabilities.
37
+ | | Agent Script (Recommended) | Classic Setup |
38
+ |---|---|---|
39
+ | **API version** | v65+ | v60+ |
40
+ | **Surface** | `.agent` files in VS Code + CLI | Agentforce Builder UI |
41
+ | **Source control** | Yes — diffable `.agent` files | No — UI-only |
42
+ | **CI/CD** | Full: validate → publish → test → activate | Limited: deploy GenAi metadata |
43
+ | **When to use** | All new agents; teams needing code review | Orgs on API < v65; admin-managed simple agents |
38
44
 
45
+ **Default to Agent Script** for all new development.
46
+
47
+ ---
48
+
49
+ ## Agent Script Development
50
+
51
+ ### File Structure
52
+
53
+ ```
54
+ force-app/main/default/aiAuthoringBundles/My_Agent/
55
+ My_Agent.agent # Agent Script file
56
+ My_Agent.bundle-meta.xml # Metadata XML
39
57
  ```
40
- Topic Name: Case Management
41
- Description: Handles customer service case creation, updating, and
42
- status inquiries. Covers support tickets and complaints.
43
58
 
44
- Instructions:
45
- - Verify customer identity before accessing case details
46
- - Create a new case if no existing open case matches the issue
47
- - Escalate to a human agent if the customer is frustrated or issue is technical
48
- - Summarise the resolution when closing a case
49
-
50
- Guardrails:
51
- - Do not discuss competitor products
52
- - Do not make promises about resolution timelines
53
- - Recommend contacting billing for billing disputes (out of scope)
59
+ ### CLI Workflow
60
+
61
+ ```bash
62
+ # Generate authoring bundle (from spec or --no-spec for boilerplate)
63
+ sf agent generate authoring-bundle --spec specs/agentSpec.yaml \
64
+ --name "My Agent" --api-name My_Agent
65
+
66
+ # Edit .agent file in VS Code (syntax highlighting + validation)
67
+ # Validate Publish Preview Activate
68
+ sf agent validate authoring-bundle --target-org MySandbox
69
+ sf agent publish authoring-bundle --target-org MySandbox
70
+ sf agent preview --target-org MySandbox
71
+ sf agent activate --api-name My_Agent --target-org MySandbox
72
+ ```
73
+
74
+ ### Complete Example
75
+
76
+ ```
77
+ config:
78
+ developer_name: "Service_Agent"
79
+ agent_label: "Customer Service Agent"
80
+
81
+ variables:
82
+ customer_email: mutable string = ""
83
+ is_verified: mutable boolean = False
84
+ session_lang: linked string
85
+ source: "EndUserLanguage"
86
+
87
+ system:
88
+ instructions: |
89
+ You are a customer service agent. Be friendly and concise.
90
+ Always verify identity before accessing account data.
91
+ messages:
92
+ welcome: "Hello! How can I help you today?"
93
+ error: "I apologize. Let me transfer you to a team member."
94
+
95
+ start_agent topic_selector:
96
+ description: "Routes messages to the appropriate topic"
97
+ reasoning:
98
+ instructions: ->
99
+ | Analyze the message and determine the best topic.
100
+ actions:
101
+ verify: @utils.transition to @topic.identity
102
+ description: "Verify customer identity"
103
+ orders: @utils.transition to @topic.order_management
104
+ description: "Help with order status or modifications"
105
+
106
+ topic identity:
107
+ description: "Verifies customer identity via email lookup"
108
+ reasoning:
109
+ instructions: ->
110
+ if @variables.is_verified == True:
111
+ | Customer is already verified.
112
+ transition to @topic.order_management
113
+ | Ask for their email address to verify identity.
114
+ actions:
115
+ lookup:
116
+ action: @actions.lookup_customer
117
+ description: "Look up customer by email"
118
+ inputs:
119
+ email: ...
120
+ set:
121
+ is_verified: output.found
122
+
123
+ after_reasoning: ->
124
+ if @variables.is_verified == True:
125
+ transition to @topic.order_management
126
+
127
+ topic order_management:
128
+ description: "Helps customers check order status"
129
+ reasoning:
130
+ instructions: ->
131
+ if @variables.is_verified == False:
132
+ transition to @topic.identity
133
+ | Help the customer with their order inquiry.
134
+ actions:
135
+ get_order:
136
+ action: @actions.get_order_details
137
+ description: "Retrieve order details by order number"
138
+ inputs:
139
+ order_number: ...
140
+ customer_email: @variables.customer_email
141
+ ```
142
+
143
+ ### Key Patterns
144
+
145
+ **Deterministic** (`->`) — guaranteed execution:
146
+
147
+ ```
148
+ -> if @variables.is_verified == False:
149
+ transition to @topic.identity
150
+ ```
151
+
152
+ **LLM prompts** (`|`) — accumulated and sent to model:
153
+
154
+ ```
155
+ | Help the customer with their order.
156
+ | Be concise and provide the order number.
157
+ ```
158
+
159
+ **Deterministic action** (`run`) — bypasses LLM:
160
+
161
+ ```
162
+ -> run @actions.get_recent_orders with
163
+ customer_id: @variables.customer_id
164
+ set
165
+ recent_orders: result
54
166
  ```
55
167
 
56
168
  ---
57
169
 
58
- ## Custom Apex Actions -- @InvocableMethod
170
+ ## Action Types
59
171
 
60
- ### Complete Example
172
+ ### Apex @InvocableMethod
173
+
174
+ Apex actions are built by `sf-apex-agent` using patterns from `sf-apex-constraints`. Key Agentforce-specific requirements for `@InvocableMethod` actions:
175
+
176
+ - **Labels/descriptions are critical** — the LLM reads these to decide routing. Keep in sync between Apex annotations and Builder action config
177
+ - **InvocableVariable descriptions** must specify data type and format: `"accountId — 18-digit Account record ID"`
178
+ - **Return result objects** (not void) — agent needs structured confirmation to continue reasoning
179
+ - **Use `Database` class** (partial success) not DML verbs (all-or-nothing)
180
+ - **Varied verb names** across actions: "Locate", "Retrieve", "Calculate" — not "Get X", "Get Y"
181
+ - **Decompose** complex actions to avoid CPU timeout (10s sync limit)
182
+ - **Long-running work**: enqueue Queueable, return requestId for status tracking
183
+
184
+ ### MCP Server
61
185
 
62
- ```apex
63
- public with sharing class CaseManagementAction {
64
-
65
- @InvocableMethod(
66
- label='Create Support Case'
67
- description='Creates a new support case for a customer.
68
- Requires accountId and subject.'
69
- category='Case Management'
70
- )
71
- public static List<CreateCaseResult> createSupportCase(
72
- List<CreateCaseRequest> requests) {
73
- List<CreateCaseResult> results = new List<CreateCaseResult>();
74
- List<Case> casesToInsert = new List<Case>();
75
-
76
- for (CreateCaseRequest req : requests) {
77
- casesToInsert.add(new Case(
78
- AccountId = req.accountId,
79
- ContactId = req.contactId,
80
- Subject = req.subject,
81
- Description = req.description,
82
- Priority = req.priority != null ? req.priority : 'Medium',
83
- Status = 'New',
84
- Origin = 'Agentforce'
85
- ));
86
- }
87
-
88
- List<Database.SaveResult> saveResults =
89
- Database.insert(casesToInsert, false, AccessLevel.USER_MODE);
90
-
91
- Set<Id> successIds = new Set<Id>();
92
- for (Database.SaveResult sr : saveResults) {
93
- if (sr.isSuccess()) successIds.add(sr.getId());
94
- }
95
-
96
- Map<Id, Case> caseMap = new Map<Id, Case>(
97
- [SELECT Id, CaseNumber FROM Case WHERE Id IN :successIds]
98
- );
99
-
100
- for (Database.SaveResult sr : saveResults) {
101
- CreateCaseResult result = new CreateCaseResult();
102
- if (sr.isSuccess()) {
103
- result.caseId = sr.getId();
104
- result.caseNumber = caseMap.get(sr.getId())?.CaseNumber;
105
- result.success = true;
106
- result.message = 'Case created: ' + result.caseNumber;
107
- } else {
108
- result.success = false;
109
- result.message = 'Failed: ' + sr.getErrors()[0].getMessage();
110
- }
111
- results.add(result);
112
- }
113
- return results;
114
- }
115
-
116
- public class CreateCaseRequest {
117
- @InvocableVariable(label='Account ID'
118
- description='Salesforce Account ID of the customer'
119
- required=true)
120
- public Id accountId;
121
-
122
- @InvocableVariable(label='Contact ID'
123
- description='Contact ID raising the case' required=false)
124
- public Id contactId;
125
-
126
- @InvocableVariable(label='Subject'
127
- description='Brief issue description (max 255 chars)'
128
- required=true)
129
- public String subject;
130
-
131
- @InvocableVariable(label='Description'
132
- description='Detailed issue description' required=false)
133
- public String description;
134
-
135
- @InvocableVariable(label='Priority'
136
- description='Low, Medium, High, Critical' required=false)
137
- public String priority;
138
- }
139
-
140
- public class CreateCaseResult {
141
- @InvocableVariable(label='Case ID')
142
- public Id caseId;
143
-
144
- @InvocableVariable(label='Case Number')
145
- public String caseNumber;
146
-
147
- @InvocableVariable(label='Success')
148
- public Boolean success;
149
-
150
- @InvocableVariable(label='Message')
151
- public String message;
152
- }
153
- }
186
+ External tools exposed to Agentforce via Model Context Protocol (JSON-RPC 2.0 over HTTP/SSE).
187
+
188
+ - **Setup**: Register server in MCP Server Registry (Setup > MCP Servers). Tools appear in Agentforce Asset Library
189
+ - **Auth**: OAuth 2.0 with Integration User. Principle of least privilege. FLS and sharing rules enforced
190
+ - **Rate limit**: ~50 requests/min/server
191
+ - **Tool discovery**: On connection, server returns schema with tool names, descriptions, required/optional parameters, return types
192
+ - **Prebuilt servers**: Salesforce DX MCP Server (deploy, test, scratch orgs), Heroku Platform, MuleSoft
193
+ - **Hosted MCP (Pilot)**: Fully managed cloud endpoints — zero infrastructure. Pre-built for core CRM and B2C Commerce APIs
194
+
195
+ ### Named Query (GA)
196
+
197
+ Parameterized SOQL exposed as REST API endpoint and agent action. No Apex or Flow required.
198
+
199
+ ```
200
+ Query Name: GetRecentOrders
201
+ SOQL: SELECT Id, Name, Status__c, CreatedDate
202
+ FROM Order__c
203
+ WHERE AccountId = :accountId
204
+ ORDER BY CreatedDate DESC LIMIT 5
154
205
  ```
155
206
 
156
- ### @InvocableMethod Best Practices
207
+ - Auto-creates REST endpoint: `/services/data/v66.0/named/query/GetRecentOrders?accountId=001xx...`
208
+ - Activate in API Catalog, then add as agent action
209
+ - **Limitation**: Input parameters only in WHERE and LIMIT clauses. Cannot edit after agent action activation without deactivation
210
+
211
+ ### AuraEnabled Methods (Beta)
212
+
213
+ Reuse existing `@AuraEnabled` controller methods as agent actions:
214
+
215
+ 1. Generate OpenAPI spec: VS Code → "SFDX: Create OpenAPI Document from This Class" → creates `.yaml` + `.externalServiceRegistration-meta.xml`
216
+ 1. Optionally add `x-sfdc: publishAsAgentAction: true` for auto-creation
217
+ 1. Deploy to API Catalog
218
+ 1. Add as agent action (category: "AuraEnabled Method (Beta)")
219
+
220
+ ### Apex Citations
221
+
222
+ Source attribution in agent responses. Two approaches:
157
223
 
158
- ```apex
159
- // Good label and description — LLM uses these to decide when to call
160
- @InvocableMethod(
161
- label='Get Account Recent Cases'
162
- description='Retrieves the 5 most recent open cases for an account.
163
- Use when customer asks about open tickets or case status.'
164
- category='Case Management'
165
- )
224
+ | Class | Behavior | Use When |
225
+ |---|---|---|
226
+ | `AiCopilot.GenAiCitationInput` | Supplies sources to reasoning engine; engine auto-places inline numbered citations | Default — let the engine decide placement |
227
+ | `AiCopilot.GenAiCitationOutput` | Direct control over citation placement; bypasses reasoning engine | Predetermined citation logic needed |
228
+
229
+ Supported sources: knowledge articles, PDF files, external web pages. Requires agent created after May 2025. Action must return both generated response and citation metadata.
230
+
231
+ ### Lightning Types
232
+
233
+ Custom LWC components for rich conversational UI in agent responses.
166
234
 
167
- // Return a result object (agent needs confirmation), not void
168
- // Bulkify — agent runtime may batch calls
169
235
  ```
236
+ lightningTypes/
237
+ flightResponse/
238
+ schema.json # JSON Schema for validation
239
+ lightningDesktopGenAi/ # Channel: Employee Agent
240
+ renderer.json # Output LWC component
241
+ enhancedWebChat/ # Channel: Service Agent (Enhanced Chat v2)
242
+ renderer.json
243
+ flightFilter/
244
+ schema.json
245
+ lightningDesktopGenAi/
246
+ editor.json # Input LWC component
247
+ ```
248
+
249
+ - LWC targets: `lightning__AgentforceInput` (editor), `lightning__AgentforceOutput` (renderer)
250
+ - **Constraint**: Custom Lightning Types only override UI for actions using **Apex classes** as input/output
251
+ - Editor LWC must include `handleInputChange()` dispatching `valuechange` event
252
+
253
+ ### Adaptive Response Formats
254
+
255
+ Rich responses without custom LWC development (Service Agents on messaging channels):
256
+
257
+ | Format | UI | Fields |
258
+ |---|---|---|
259
+ | **Rich Choice** | Carousel, buttons, list selector | Title, description, link, image per tile |
260
+ | **Rich Link** | Media card | Link title, URL, image, description |
261
+
262
+ Determined automatically by returned data structure from Apex or Flow actions.
170
263
 
171
264
  ---
172
265
 
173
- ## Flow Actions for Agentforce
266
+ ## Flow Actions
174
267
 
175
- Use Flow actions when logic involves declarative orchestration, screen interactions, or non-developer maintenance.
268
+ Use when logic involves declarative orchestration or non-developer maintenance.
176
269
 
177
270
  ```
178
- Flow: Update_Account_Segment (Autolaunched Flow)
179
- Variables:
180
- - accountId (Input, Text, Required)
181
- - newSegment (Input, Text, Required)
182
- - result (Output, Text)
183
-
184
- Steps:
185
- 1. Get Records: Account WHERE Id = {accountId}
186
- 2. Decision: Is segment different from current?
187
- 3. Update Records: Account.Segment__c = {newSegment}
188
- 4. Assignment: result = "Segment updated to " + {newSegment}
271
+ Flow: Update_Account_Segment (Autolaunched)
272
+ Variables: accountId (Input), newSegment (Input), result (Output)
273
+ Steps: Get Record Decision → Update Record → Assign result
189
274
  ```
190
275
 
191
- Add the Flow to an Agentforce topic as an action in Setup.
276
+ Add to topics in Setup or reference in Agent Script `reasoning.actions`.
192
277
 
193
278
  ---
194
279
 
195
280
  ## Prompt Templates
196
281
 
197
- ### Creating a Flex Prompt Template
198
-
199
282
  ```
200
283
  Template Name: Case Summary for Agent
201
- Template Type: Flex (general purpose)
284
+ Template Type: Flex
202
285
  Grounding: Case record
203
286
 
204
- Template Body:
205
- You are a helpful customer service assistant.
287
+ Body:
206
288
  Summarise the following case for a support representative.
207
-
208
- Case Details:
209
289
  - Case Number: {!$Input:Case.CaseNumber}
210
290
  - Subject: {!$Input:Case.Subject}
211
291
  - Status: {!$Input:Case.Status}
212
- - Priority: {!$Input:Case.Priority}
213
292
  - Customer: {!$Input:Case.Account.Name}
214
- - Description: {!$Input:Case.Description}
215
293
 
216
- Provide:
217
- 1. A 2-sentence summary of the issue
218
- 2. Recommended next action
219
- 3. Estimated complexity: Low/Medium/High
220
- ```
221
-
222
- ### Using Prompt Templates in Apex
223
-
224
- > Note: The ConnectApi surface for Einstein/Agentforce changes rapidly. Verify exact class/method names against the ConnectApi Apex Reference for your target API version (v66.0 Spring '26).
225
-
226
- ```apex
227
- public with sharing class PromptTemplateAction {
228
-
229
- @InvocableMethod(
230
- label='Generate Case Summary'
231
- description='Generates an AI summary using Einstein Prompt Template'
232
- )
233
- public static List<SummaryResult> generateCaseSummary(
234
- List<SummaryRequest> requests) {
235
- List<SummaryResult> results = new List<SummaryResult>();
236
-
237
- for (SummaryRequest req : requests) {
238
- try {
239
- ConnectApi.EinsteinPromptTemplateGenerationsRepresentation
240
- response = ConnectApi.EinsteinLLM
241
- .generateMessagesForPromptTemplate(
242
- 'Case_Summary_for_Agent',
243
- new Map<String, String>{
244
- 'Input:Case' => req.caseId
245
- },
246
- new Map<String, ConnectApi
247
- .EinsteinPromptTemplateGenerationsInput>()
248
- );
249
-
250
- SummaryResult result = new SummaryResult();
251
- result.summary = response.generations[0].text;
252
- result.success = true;
253
- results.add(result);
254
- } catch (Exception e) {
255
- SummaryResult result = new SummaryResult();
256
- result.success = false;
257
- result.errorMessage = e.getMessage();
258
- results.add(result);
259
- }
260
- }
261
- return results;
262
- }
263
-
264
- public class SummaryRequest {
265
- @InvocableVariable(label='Case ID' required=true)
266
- public Id caseId;
267
- }
268
-
269
- public class SummaryResult {
270
- @InvocableVariable(label='Summary')
271
- public String summary;
272
- @InvocableVariable(label='Success')
273
- public Boolean success;
274
- @InvocableVariable(label='Error Message')
275
- public String errorMessage;
276
- }
277
- }
294
+ Provide: 1) 2-sentence summary 2) Recommended next action 3) Complexity: Low/Medium/High
278
295
  ```
279
296
 
280
297
  ---
281
298
 
282
- ## Mixing Deterministic Logic with LLM Actions (Spring '26)
299
+ ## Testing
300
+
301
+ Apex unit tests for `@InvocableMethod` actions are handled by `sf-apex-agent` using `sf-testing-constraints`. This section covers **agent-level testing** — verifying topic routing, action execution, and response quality.
302
+
303
+ ### Agent Test Spec (YAML)
304
+
305
+ ```yaml
306
+ name: Service_Agent_Tests
307
+ description: End-to-end tests for Customer Service Agent
308
+ subjectType: AGENT
309
+ subjectName: Service_Agent
310
+ subjectVersion: v1
311
+ testCases:
312
+ - utterance: "What's the status of order #12345?"
313
+ expectedTopic: Order_Management
314
+ expectedActions:
315
+ - get_order_details
316
+ expectedOutcome: "Agent provides order status details including shipping info"
317
+ contextVariables:
318
+ - name: EndUserLanguage
319
+ value: en
320
+ metrics:
321
+ - topic_sequence_match
322
+ - action_sequence_match
323
+ - bot_response_rating
324
+ - coherence
325
+ - completeness
326
+ - conciseness
327
+ - latency
328
+
329
+ - utterance: "I need to file a complaint about my delivery"
330
+ expectedTopic: Case_Management
331
+ expectedActions:
332
+ - create_support_case
333
+ expectedOutcome: "Agent creates a case and provides the case number"
334
+ metrics:
335
+ - topic_sequence_match
336
+ - action_sequence_match
337
+ - bot_response_rating
338
+ - instructionAdherence
339
+
340
+ - utterance: "Hola, necesito ayuda con mi pedido"
341
+ expectedTopic: Order_Management
342
+ contextVariables:
343
+ - name: EndUserLanguage
344
+ value: es
345
+ metrics:
346
+ - topic_sequence_match
347
+ - coherence
348
+ ```
283
349
 
284
- Agentforce supports mixing deterministic actions (Apex, Flow) with LLM-driven prompt actions within a single topic.
350
+ ### Multi-Turn Conversation Testing
351
+
352
+ ```yaml
353
+ testCases:
354
+ - utterance: "I want to return my order"
355
+ expectedTopic: Order_Management
356
+ conversationHistory:
357
+ - role: user
358
+ message: "Hi, I need help"
359
+ - role: agent
360
+ message: "Hello! How can I help you today?"
361
+ topic: topic_selector
362
+ - role: user
363
+ message: "I have a problem with order #12345"
364
+ - role: agent
365
+ message: "I found order #12345. It was delivered on March 15."
366
+ topic: Order_Management
367
+ metrics:
368
+ - topic_sequence_match
369
+ - action_sequence_match
370
+ ```
285
371
 
286
- > Configuration is done in the Agentforce Builder UI. The pseudo-code below illustrates the architectural pattern.
372
+ ### Custom Evaluations
287
373
 
374
+ ```yaml
375
+ testCases:
376
+ - utterance: "What's the weather in SF?"
377
+ customEvaluations:
378
+ - label: Temperature Check
379
+ jsonPathExpression: $.actions[0].result.temperature
380
+ comparisonOperator: greaterThan
381
+ expectedValue: "0"
288
382
  ```
289
- Topic: CaseTriage
290
-
291
- Step 1 (Deterministic — Apex):
292
- Call: EscalateCaseAction
293
- Condition: case.Priority == 'Critical'
294
383
 
295
- Step 2 (Deterministic — Apex):
296
- Call: GetKnowledgeArticles
297
- Input: case.Subject
298
- -> Grounds the LLM with relevant articles
384
+ ### CLI Test Workflow
299
385
 
300
- Step 3 (LLM — Prompt Template):
301
- Template: Case_Resolution_Suggestion
302
- Grounding: case record + articles from Step 2
386
+ ```bash
387
+ # Generate test spec from agent definition
388
+ sf agent generate test-spec --output-file specs/testSpec.yaml
303
389
 
304
- Step 4 (Deterministic Apex):
305
- Call: LogAgentInteraction
306
- -> Audit trail logged regardless of LLM output
307
- ```
390
+ # Create test in org from YAML spec
391
+ sf agent test create --spec specs/testSpec.yaml --target-org MySandbox
308
392
 
309
- Use when: compliance rules need deterministic execution, multi-step processes mix AI judgment with guaranteed logic, or audit trails must separate deterministic decisions from AI content.
393
+ # Run tests synchronously with JUnit output (CI-friendly)
394
+ sf agent test run --api-name Service_Agent_Tests --wait 10 \
395
+ --result-format junit --output-dir ./test-results \
396
+ --target-org MySandbox
310
397
 
311
- ---
398
+ # View results
399
+ sf agent test results --test-id <id> --target-org MySandbox
312
400
 
313
- ## Testing Agentforce
314
-
315
- ### Unit Testing Apex Actions
316
-
317
- ```apex
318
- @IsTest
319
- public class CaseManagementActionTest {
320
-
321
- @TestSetup
322
- static void setup() {
323
- Account acc = new Account(Name='Test Account');
324
- insert acc;
325
- Contact con = new Contact(LastName='Doe', AccountId=acc.Id);
326
- insert con;
327
- }
328
-
329
- @IsTest
330
- static void testCreateCase_validInput_createsCase() {
331
- Account acc = [SELECT Id FROM Account LIMIT 1];
332
- Contact con = [SELECT Id FROM Contact LIMIT 1];
333
-
334
- CaseManagementAction.CreateCaseRequest req =
335
- new CaseManagementAction.CreateCaseRequest();
336
- req.accountId = acc.Id;
337
- req.contactId = con.Id;
338
- req.subject = 'Cannot access portal';
339
- req.priority = 'High';
340
-
341
- Test.startTest();
342
- List<CaseManagementAction.CreateCaseResult> results =
343
- CaseManagementAction.createSupportCase(
344
- new List<CaseManagementAction.CreateCaseRequest>{req});
345
- Test.stopTest();
346
-
347
- System.assert(results[0].success);
348
- System.assertNotEquals(null, results[0].caseId);
349
-
350
- Case created = [SELECT Status, Origin, Priority
351
- FROM Case WHERE Id = :results[0].caseId];
352
- System.assertEquals('Agentforce', created.Origin);
353
- System.assertEquals('High', created.Priority);
354
- }
355
-
356
- @IsTest
357
- static void testCreateCase_bulk_createsMultipleCases() {
358
- Account acc = [SELECT Id FROM Account LIMIT 1];
359
-
360
- List<CaseManagementAction.CreateCaseRequest> requests =
361
- new List<CaseManagementAction.CreateCaseRequest>();
362
- for (Integer i = 0; i < 200; i++) {
363
- CaseManagementAction.CreateCaseRequest req =
364
- new CaseManagementAction.CreateCaseRequest();
365
- req.accountId = acc.Id;
366
- req.subject = 'Bulk test case ' + i;
367
- requests.add(req);
368
- }
369
-
370
- Test.startTest();
371
- List<CaseManagementAction.CreateCaseResult> results =
372
- CaseManagementAction.createSupportCase(requests);
373
- Test.stopTest();
374
-
375
- Integer successCount = 0;
376
- for (CaseManagementAction.CreateCaseResult r : results) {
377
- if (r.success) successCount++;
378
- }
379
- System.assertEquals(200, successCount);
380
- }
381
- }
401
+ # List all agent tests
402
+ sf agent test list --target-org MySandbox
382
403
  ```
383
404
 
384
- ---
405
+ ### Testing REST API (CI Integration)
385
406
 
386
- ## SF CLI Agent Commands (Spring '26)
407
+ ```
408
+ # Start test run
409
+ POST /services/data/v63.0/einstein/ai-evaluations/runs
410
+ Body: { "aiEvaluationDefinitionName": "Service_Agent_Tests" }
411
+ Response: { "runId": "0Xx..." }
412
+
413
+ # Poll status
414
+ GET /services/data/v63.0/einstein/ai-evaluations/runs/{runId}
415
+ Response: { "status": "NEW | IN_PROGRESS | COMPLETED | ERROR" }
416
+
417
+ # Get results
418
+ GET /services/data/v63.0/einstein/ai-evaluations/runs/{runId}/results
419
+ Response: { "testCases": [...], "testResults": [...] }
420
+ ```
387
421
 
388
- ```bash
389
- # Activate an agent
390
- sf agent activate --name "Sales Assistant" --target-org MySandbox
422
+ Auth: OAuth 2.0 via External Client App (JWT with consumer key/secret).
391
423
 
392
- # Run automated agent tests
393
- sf agent test run --target-org MySandbox --output-dir test-results/
424
+ ### Testing Tools Summary
394
425
 
395
- # Resume a paused test job
396
- sf agent test resume --job-id <jobId> --target-org MySandbox
426
+ | Tool | Purpose |
427
+ |---|---|
428
+ | **Agent Builder Preview** | Real-time conversational testing (simulated or live mode) |
429
+ | **Agentforce Testing Center** | Bulk test execution; auto-generates test cases from knowledge |
430
+ | **CLI (`sf agent test`)** | Headless testing, JUnit output, CI pipeline integration |
431
+ | **VS Code Agent Panel** | View/run tests + Agent Preview pane + Apex Replay Debugger |
432
+ | **Testing REST API** | Programmatic test execution from external CI systems |
433
+ | **Agent Grid (Beta)** | Spreadsheet-like rapid testing with real CRM data |
397
434
 
398
- # Get test results
399
- sf agent test results --job-id <jobId> --result-format human
435
+ ---
400
436
 
401
- # Generate starter agent spec
402
- sf agent generate agent-spec \
403
- --agent-type custom \
404
- --output-dir force-app/main/agents \
405
- --target-org MySandbox
437
+ ## Metadata & Deployment
438
+
439
+ ```
440
+ force-app/main/default/
441
+ aiAuthoringBundles/My_Agent/ # .agent + .bundle-meta.xml
442
+ bots/My_Agent/ # .bot-meta.xml
443
+ botVersions/My_Agent.v1/ # .botVersion-meta.xml
444
+ genAiPlannerBundles/My_Agent/ # .genAiPlannerBundle-meta.xml
445
+ genAiPlugins/Topic_Name/ # .genAiPlugin-meta.xml
446
+ genAiFunctions/Action_Name/ # .genAiFunction-meta.xml + input/output schema.json
447
+ aiEvaluationDefinitions/ # .aiEvaluationDefinition-meta.xml
406
448
  ```
407
449
 
408
- ---
450
+ **Deploy order**: Bot/BotVersion → GenAiPromptTemplate → GenAiFunction → GenAiPlugin → GenAiPlannerBundle → AiAuthoringBundle → AiEvaluationDefinition → Activate
409
451
 
410
- ## Security: Data Access in AI Context
411
-
412
- ```apex
413
- // Enforce sharing in Agentforce Apex actions
414
- public with sharing class SecureAgentAction {
415
-
416
- @InvocableMethod(label='Get Customer Orders')
417
- public static List<OrderResult> getOrders(List<OrderRequest> requests) {
418
- // Collect ALL accountIds — runtime may batch multiple requests
419
- Set<Id> accountIds = new Set<Id>();
420
- for (OrderRequest req : requests) {
421
- accountIds.add(req.accountId);
422
- }
423
-
424
- // USER_MODE enforces CRUD/FLS and sharing rules
425
- List<Order__c> orders = [
426
- SELECT Id, Name, Status__c, Amount__c, AccountId
427
- FROM Order__c
428
- WHERE AccountId IN :accountIds
429
- WITH USER_MODE
430
- LIMIT 50
431
- ];
432
-
433
- // Build results grouped by AccountId...
434
- }
435
- }
436
- ```
452
+ **Retrieve**: `sf project retrieve start --metadata "AiAuthoringBundle:My_Agent*"`
453
+
454
+ ---
437
455
 
438
- ### PII Considerations
456
+ ## Security
439
457
 
440
- - Use field-level security to control what the agent can access
458
+ - Always use `with sharing` and `AccessLevel.USER_MODE` / `WITH USER_MODE`
441
459
  - Ground Prompt Templates only with fields the user's profile can read
442
460
  - Review agent conversations in Setup > Agent Conversations
443
461
 
444
462
  ---
445
463
 
464
+ ## Classic Topics (Pre-Agent Script)
465
+
466
+ For orgs on API < v65, configure topics in Agentforce Builder UI:
467
+
468
+ ```
469
+ Topic: Case Management
470
+ Description: Handles case creation, updating, and status inquiries.
471
+ Scope WILL: Case creation, status checks, escalation
472
+ Scope WILL NOT: Billing disputes, resolution timeline promises
473
+ Instructions:
474
+ 1. Verify customer identity before accessing case details
475
+ 2. Create a new case if no existing open case matches
476
+ 3. Escalate if customer is frustrated or issue is complex
477
+ ```
478
+
479
+ All instruction guidelines and context engineering principles from the reference apply identically.
480
+
481
+ ---
482
+
446
483
  ## Related
447
484
 
448
- - Agent: `sf-agentforce-agent` -- for interactive, in-depth guidance
485
+ - Agent: `sf-agentforce-agent` for interactive guidance
449
486
  - Constraints: sf-apex-constraints
450
487
  - Reference: @../_reference/AGENTFORCE_PATTERNS.md