Back to skills
SKILL.md
2472 Grounding Multiagent B9a8d650
ASecurity> High-stakes enterprise agents cannot rely on training data. They must be **grounded in real-time business data** and coordinate with **specialized agents** for complex tasks. ---
- 9 stars
- 0 votes
- 0 copies
- 0 views
- Added October 11, 2026
Works with
Security analysis
100/100npx -y skills add tools-only/X-Skills --skill 2472-grounding-multiagent_b9a8d650 --agent claude-codeAre you the author of 2472 Grounding Multiagent B9a8d650?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-2472-grounding-multiagent-b9a8d650)<!-- Parent: sf-ai-agentscript/SKILL.md -->
# Data Grounding & Multi-Agent Guide
> High-stakes enterprise agents cannot rely on training data. They must be **grounded in real-time business data** and coordinate with **specialized agents** for complex tasks.
---
## Two Pillars
| Pillar | Icon | Description |
|--------|------|-------------|
| π½ **Retriever Actions** | Filter | Dynamic filtering ensures agents only see relevant data |
| π **Multi-Agent SOMA** | Branch | Primary agents delegate to expert agents |
---
## Retriever Actions
### Connecting Agents to Data Cloud
Retriever Actions connect your agent to Data Cloud Search Indexes, enabling context-aware knowledge retrieval.
**Capabilities:**
- β
Search Index wraps unstructured data (PDFs, docs, web pages)
- β
Chunking parses text, tables, and images into searchable segments
- β
Returns relevant chunks based on semantic similarity
- β
Integrated with Data Cloud for current data
### Basic Retriever Action
```yaml
actions:
fetch_refund_policy:
description: "Retrieve refund policy from knowledge base"
target: "retriever://RefundSOP_Retriever"
inputs:
query: string
outputs:
chunks: list[object]
relevance_scores: list[number]
```
### Retrieval Pipeline
```
ββββββββββββββ ββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ
β User Query β β β Dynamic Filter β β β Data Cloud Indexβ β β Relevant Chunks β β β LLM Response β
ββββββββββββββ ββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ
```
---
### Filtered Retrieval with Flows
> Agent Script cannot filter retrieval results inline. When you need filtered knowledge retrieval, wrap the retriever in a Flow.
**Problem**: Direct `retriever://` targets don't support inline filtering.
**Solution**: Use `flow://` to wrap the retriever with filter logic.
```yaml
# WRONG - No filtering capability
actions:
fetch_policy:
target: "retriever://RefundSOP_Index" # Can't filter!
# CORRECT - Flow handles filtering
actions:
fetch_regional_policy:
description: "Fetch policy filtered by customer region"
inputs:
query: string
customer_country: string
description: "Country code for regional filtering"
outputs:
chunks: list[object]
policy_region: string
target: "flow://GetRegionalRefundPolicy" # Flow filters internally
```
> β οΈ **Security Note**: Filtering in a Flow prevents accidental cross-region data exposure. The Flow enforces the filter - the LLM cannot bypass it.
---
### Safe Expressions
Agent Script uses a safe subset of Python for expressions:
**Allowed Operations:**
| Category | Operators |
|----------|-----------|
| **Comparison** | `==`, `!=` (not-equal), `>`, `<`, `>=`, `<=` |
| **Logical** | `and`, `or`, `not` |
| **String** | `contains`, `startswith`, `endswith` |
**Security Constraints:**
- β No `import` statements
- β No file access
- β No arbitrary code execution
```python
# Valid safe expressions:
@variables.risk_score > 80
@variables.country == "Germany"
@variables.is_vip and @variables.order_total > 100
not @variables.verified
# INVALID (security risk):
import os # NOT ALLOWED
eval(...) # NOT ALLOWED
open(...) # NOT ALLOWED
```
---
## The 6 Action Target Protocols
Every action uses a `target:` field to specify where to send the request.
| Protocol | Use When | Example |
|----------|----------|---------|
| `flow://` | Data operations, business logic | `target: "flow://GetOrderStatus"` |
| `apex://` | Custom calculations, validation | `target: "apex://RefundCalculator"` |
| `generatePromptResponse://` | Grounded LLM responses | `target: "generatePromptResponse://Summary"` |
| `retriever://` | RAG knowledge search | `target: "retriever://Policy_Index"` |
| `externalService://` | Third-party APIs | `target: "externalService://AddressAPI"` |
| `standardInvocableAction://` | Built-in SF actions | `target: "standardInvocableAction://email"` |
---
### Protocol 1: Salesforce Flow (`flow://`)
**Use Case**: Data operations, business logic, filtered retrieval
```yaml
actions:
get_order_status:
description: "Retrieves order details by order number"
inputs:
order_number: string
description: "The order ID to look up"
outputs:
status: string
tracking_number: string
target: "flow://GetOrderStatus"
```
---
### Protocol 2: Apex Class (`apex://`)
**Use Case**: Custom calculations, complex validation
```yaml
actions:
calculate_refund:
description: "Calculate refund amount based on policy rules"
inputs:
order_id: string
refund_reason: string
outputs:
refund_amount: currency
requires_approval: boolean
target: "apex://RefundCalculatorService"
```
---
### Protocol 3: Prompt Template (`generatePromptResponse://`)
**Use Case**: Grounded LLM responses, summarization
```yaml
actions:
summarize_case:
description: "Generate a summary of the customer case"
inputs:
"Input:caseId": id
description: "The Case record ID"
outputs:
promptResponse: string
is_displayable: True
target: "generatePromptResponse://Generate_Case_Summary"
```
> β οΈ Note: Input keys use quoted strings with colon notation (`"Input:caseId"`)
---
### Protocol 4: Data Cloud Retriever (`retriever://`)
**Use Case**: Knowledge base search, FAQ lookup
```yaml
actions:
search_knowledge:
description: "Search the knowledge base for relevant info"
inputs:
query: string
outputs:
chunks: list[object]
relevance_scores: list[number]
target: "retriever://RefundPolicy_Retriever"
```
---
### Protocol 5: External Service (`externalService://`)
**Use Case**: Third-party APIs via Named Credentials
```yaml
actions:
verify_address:
description: "Validate shipping address via external API"
inputs:
street: string
city: string
postal_code: string
outputs:
is_valid: boolean
normalized_address: object
target: "externalService://AddressValidation"
```
---
### Protocol 6: Standard Invocable (`standardInvocableAction://`)
**Use Case**: Built-in Salesforce actions (email, tasks, Chatter)
```yaml
actions:
send_email:
description: "Send confirmation email to customer"
inputs:
recipient_email: string
template_id: id
outputs:
success: boolean
target: "standardInvocableAction://emailSimple"
```
---
### Protocol Selection Guide
| If you need... | Use this protocol |
|----------------|-------------------|
| Complex data queries, record updates | `flow://` |
| Custom calculations, validation | `apex://` |
| LLM-generated summaries | `generatePromptResponse://` |
| Knowledge search, RAG | `retriever://` |
| External REST APIs | `externalService://` |
| Standard SF actions | `standardInvocableAction://` |
### Conditional Knowledge Retrieval Pattern
Use `available when` to route to different knowledge bases based on user context:
```yaml
topic knowledge_router:
description: "Route to appropriate knowledge base"
reasoning:
instructions: ->
| Let me find the right information for you.
actions:
search_premium_kb: @actions.search_premium_knowledge
description: "Search premium support articles"
available when @variables.customer_tier == "premium"
with query = ...
search_standard_kb: @actions.search_standard_knowledge
description: "Search standard support articles"
available when @variables.customer_tier != "premium"
with query = ...
```
> **Why this matters**: Different customer tiers may need access to different knowledge bases with different SLA guidance, pricing, or support procedures. The `available when` guard ensures the LLM can only search the appropriate knowledge base.
---
## Same Org Multi-Agent (SOMA)
When a primary agent encounters specialized needs, it can coordinate with expert agents.
### Two Coordination Patterns
| Pattern | Description | Return Behavior |
|---------|-------------|-----------------|
| π **Delegation** | Farm out, then return | β
Control returns to original agent |
| β‘οΈ **Handoff** | Transfer permanently | β No return - original agent exits |
---
### Pattern 1: Delegation
**Flow:**
```
βββββββββββ DELEGATE ββββββββββββββ RETURN βββββββββββ
β Primary β ββββββββββββββΆ β Specialist β ββββββββββββΆ β Primary β
βββββββββββ ββββββββββββββ βββββββββββ
```
**Use Cases:**
- Tax questions β Compliance Agent
- Technical issues β Support Specialist
- Order changes β Fulfillment Agent
**Implementation:**
```yaml
# Delegation uses topic reference (NOT @utils.transition)
# Parent orchestrates β child returns control
reasoning:
actions:
ask_compliance: @topic.compliance
description: "Consult compliance specialist on tax questions"
# β
Returns to this topic after specialist finishes
ask_refund_help: @topic.refund_specialist
description: "Consult refund specialist for calculations"
# β
Control returns to continue conversation
```
---
### Pattern 2: Handoff
**Flow:**
```
βββββββββββ HANDOFF ββββββββββ NO RETURN
β Primary β βββββββββββββΆ β Target β βββββββββββββΆ β
βββββββββββ ββββββββββ
```
**Use Cases:**
- Escalation to human agent
- Domain boundary (Sales β Support)
- Fraud detection requiring specialized handling
**Implementation:**
```yaml
# Permanent handoff - conversation leaves this agent
reasoning:
actions:
escalate_to_human: @utils.escalate
description: "Transfer to live support"
# Conversation ends for this agent
```
---
### Delegation vs Handoff Decision
| Use This | When You Need |
|----------|---------------|
| `@topic.X` (in reasoning.actions) | Temporary delegation β control returns |
| `@utils.transition to @topic.X` | Permanent handoff β no return |
| `@utils.escalate` | Permanent handoff to human |
| `@agent.X` (Connections) | Permanent handoff to another agent |
> **KEY INSIGHT**: The difference is whether the original agent continues after the specialist finishes.
### SOMA Limitations (Community-Confirmed)
| Limitation | Description | Workaround |
|-----------|-------------|------------|
| Single action per supervision call | Delegated topic can only execute ONE action before returning | Break complex operations into separate delegation calls |
| `related_agent` nodes may fail | SOMA configuration with related agent references can cause "Node does not have corresponding topic" errors | Use `@topic.X` delegation within same agent instead |
| No cross-agent variable sharing | Delegated agents cannot read/write parent agent's variables | Pass data through action inputs/outputs |
---
## Variable Configuration for Grounding
### Linked Variables for Session Context
```yaml
variables:
# WRONG - mutable allows modification
CustomerCountry: mutable string = ""
# CORRECT - linked preserves session data
CustomerCountry: linked string
source: @session.Country
```
**Why This Matters:**
- `mutable string = ""` starts empty - filter won't work
- `linked string` pulls from session - filter gets real value
---
### Debug Exercise: Wrong Policy Applied
**Symptom**: German customer received US refund policy
**Root Cause Trace:**
| Step | Wrong Implementation | Correct Implementation |
|------|---------------------|------------------------|
| 1. Session Start | `CustomerCountry: ""` | `CustomerCountry: "Germany"` |
| 2. Filter | `Region == ""` | `Region == "Germany"` |
| 3. Knowledge Fetch | US_Refund_Policy | EU_Refund_Policy_GDPR |
| 4. Refund | $10 credit | Full refund (β¬45.99) |
**Fix**: Change `mutable string = ""` to `linked string` with `source: @session.Country`
---
## Best Practices
### 1. Always Filter Regional Data
Never return unfiltered results for region-specific policies.
### 2. Use Flows for Complex Filtering
Agent Script can't filter inline - wrap retrievers in Flows.
### 3. Validate Session Variables
Ensure linked variables have sources - empty values cause wrong retrievals.
### 4. Choose Delegation vs Handoff Carefully
- `@topic.X` (delegation) β returns control to parent topic
- `@utils.transition to @topic.X` (handoff) β permanent, no return
### 5. Use `available when` for Sensitive Protocols
Guard external service calls with verification checks.
```yaml
actions:
call_payment_api: @actions.charge_card
target: "externalService://PaymentGateway"
available when @variables.customer_verified == True
```
Attribution
Comments
Loading commentsβ¦
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.