Salesforce CRM - SDR Operations
Authentication: OAuth token-only. No password credentials required or supported.
Write Safety: All CRM writes require interactive YES confirmation. No bypass flags.
Audit: All operations logged to ~/.salesforce_skill_audit.log (treat as sensitive data).
Security Model
Every write operation requires 4 confirmations before touching Salesforce:
User prompt
→ 1. Object allowlist (only 5 permitted: Account, Contact, Lead, Opportunity, Task)
→ 2. Field allowlist (per-object restricted fields)
→ 3. Diff preview (shows OLD → NEW values with ⚠️ HIGH IMPACT warnings)
→ 4. Interactive confirmation (type YES - no bypass)
→ Salesforce API
→ 5. Audit log (sensitive data - protect this file)
Read operations (SOQL queries) never modify data but may return sensitive CRM information. Treat all query results as confidential.
Authentication Setup (OAuth Token-Only)
This skill uses OAuth tokens exclusively. Password-based authentication is NOT supported.
Step 1: Create Salesforce Connected App
- Setup > App Manager > New Connected App
- Enable OAuth Settings
- Callback URL:
https://login.salesforce.com/services/oauth2/success - Scopes: Select only
apiandrefresh_token(do NOT addfullorweb) - Save and note Client ID and Client Secret
Step 2: Get OAuth Access Token
Use OAuth 2.0 authorization code flow or password flow (via external tool) to obtain an access token.
Example using cURL (password flow - for initial setup only):
curl -X POST https://login.salesforce.com/services/oauth2/token \
-d "grant_type=password" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "username=integration-user@yourcompany.com" \
-d "password=YOUR_PASSWORD_AND_SECURITY_TOKEN"
Response contains access_token and instance_url.
Step 3: Set Environment Variables
# Store in your shell profile or secrets manager — never hardcode values
# SF_ACCESS_TOKEN → obtained from sf_auth.py or your OAuth flow
# SF_INSTANCE_URL → e.g. https://yourorg.my.salesforce.com
Security: Store these in a secrets manager or .env file. Never commit to version control.
Step 4: Create Least-Privilege Integration User
Never use a personal admin account.
- Setup > Users > New User
- Username:
sdr-skill-integration@yourcompany.com - Profile: "Minimum Access - Salesforce"
- API Only User: Yes
Step 5: Create Permission Set
Name: SDR_Skill_Integration
Object Permissions:
- Account: Read, Create, Edit (no Delete, no View All, no Modify All)
- Contact: Read, Create, Edit
- Lead: Read, Create, Edit
- Opportunity: Read, Edit (no Create, no Delete - prevents creating fake pipeline)
- Task: Read, Create, Edit
Field-Level Security (Opportunity - restrict to safe fields):
- ✅ StageName, CloseDate, Description, Type, LeadSource
- ✅ Custom R&D fields (R_D_Credit_Estimate__c, etc.)
- ❌ Amount (excluded - financial risk)
- ❌ Probability (excluded - forecast manipulation)
How to Use
Read Operations (Always Safe)
Check if "Acme Engineering" in California exists in Salesforce
Get full details for Account 001XX000003DHP0
Find 10 unscreened manufacturing companies in Texas
Find CEO and CFO for Account 001XX000003DHP0
Security: Query results may contain sensitive CRM data (emails, phone numbers, revenue, notes). Treat as confidential.
Write Operations (Require Confirmation)
Create Account for "Acme Engineering" - Industry: Engineering, Employees: 150
Update Account 001XX000003DHP0 - R_D_Screening_Status__c: Strong Candidate
Update Opportunity 006XX000005XYZ1 - StageName: Closed Won
Every write shows:
- Transparency notice (what objects are writable)
- Diff preview (OLD → NEW values)
- ⚠️ HIGH IMPACT warnings for forecast-affecting fields
- Interactive prompt: "Type YES to proceed"
No bypass flags. Every write requires manual confirmation.
Permitted Objects & Fields
| Object | Access | Writable Fields | Excluded (Too Risky) |
|---|---|---|---|
| Account | read/write | Name, Industry, Address, Phone, R&D screening fields | - |
| Contact | read/write | Name, Email, Phone, Title, Department | - |
| Lead | read/write | Name, Company, Status, Source, Email, Phone | - |
| Opportunity | read/write | StageName, CloseDate, Description, Type, R&D custom fields | Amount, Probability |
| Task | read/write | Subject, Date, Status, Priority, Description | - |
Opportunity Amount and Probability are intentionally excluded to prevent accidental revenue forecast corruption.
Audit Log Security
Location: ~/.salesforce_skill_audit.log
Contains sensitive data:
- Record IDs
- Field names and values (old + new)
- Timestamps
- User actions
Recommendations:
- Protect with file permissions:
chmod 600 ~/.salesforce_skill_audit.log - Define retention policy (e.g., rotate monthly)
- Exclude from backups if CRM data is highly sensitive
- Review regularly for unauthorized changes
Example entry:
{
"timestamp": "2026-05-07T00:00:00Z",
"action": "update",
"object": "Opportunity",
"record_id": "006XX0",
"old_values": {"StageName": "Prospecting"},
"new_values": {"StageName": "Closed Won"},
"result": "success"
}
SOQL Query Examples
Duplicate Detection (Read-Only)
SELECT Id, Name, Website, Owner.Name
FROM Account
WHERE Name LIKE '%Acme%'
AND BillingCountry = 'United States'
LIMIT 10
Get Screening Queue (Read-Only)
SELECT Id, Name, Industry, NumberOfEmployees, BillingState
FROM Account
WHERE R_D_Screening_Status__c = NULL
AND NumberOfEmployees >= 50
ORDER BY CreatedDate ASC
LIMIT 25
Find Decision Makers (Read-Only)
SELECT Id, Name, Title, Email, Phone
FROM Contact
WHERE AccountId = '001XX0'
AND (Title LIKE '%CEO%' OR Title LIKE '%CFO%')
Error Handling
| Error | Cause | Fix |
|---|---|---|
INVALID_FIELD | Field doesn't exist or wrong API name | Check __c suffix for custom fields |
DUPLICATE_VALUE | Duplicate rule triggered | Run duplicate check first |
INSUFFICIENT_ACCESS | Missing permissions | Contact Salesforce admin |
Object not permitted | Object not on allowlist | Use only: Account, Contact, Lead, Opportunity, Task |
Rejected fields | Field not on allowlist | Remove field or request allowlist update |
Upgrade Instructions
From v1.x or v2.0 to v2.1:
Step 1: Backup Current Skill
# Create timestamped backup
cp -r ~/.openclaw/skills/salesforce-crm-sdr \
~/.openclaw/skills/salesforce-crm-sdr.backup.$(date +%Y%m%d)
Step 2: Verify Backup
# Confirm backup exists before proceeding
ls -la ~/.openclaw/skills/salesforce-crm-sdr.backup.*
Step 3: Remove Old Version (User Confirmation Required)
# ⚠️ DESTRUCTIVE OPERATION - Confirm you want to delete the old skill
# Type the full command below ONLY if you verified the backup above:
read -p "Type 'DELETE' to remove old skill: " confirm
if [ "$confirm" = "DELETE" ]; then
rm -rf ~/.openclaw/skills/salesforce-crm-sdr
echo "✅ Old skill removed"
else
echo "❌ Cancelled - old skill preserved"
fi
Step 4: Install v2.1
cp -r salesforce-crm-sdr-final ~/.openclaw/skills/salesforce-crm-sdr
Step 5: Update Environment Variables
# Remove old password-based vars if present
unset SF_USERNAME SF_PASSWORD SF_SECURITY_TOKEN SF_CLIENT_ID SF_CLIENT_SECRET
# Obtain a fresh OAuth token and set env vars
# SF_CLIENT_ID, SF_CLIENT_SECRET, SF_USERNAME, SF_PASSWORD must be set first, then:
eval $(python3 scripts/sf_auth.py --export)
Step 6: Test
# Test read operation (safe)
python3 ~/.openclaw/skills/salesforce-crm-sdr/scripts/salesforce_query.py \
"SELECT Id, Name FROM Account LIMIT 5"
What's New in v2.1
| Change | Reason |
|---|---|
Removed salesforce_auth.py | Eliminated password-based auth confusion |
Removed --yes flag | All writes require interactive confirmation |
| Added user confirmation to delete commands | Prevents accidental skill deletion |
Declared credentials-type: oauth-token in metadata | ClawHub transparency |
| Added audit log security notice | Sensitive data protection guidance |
| Aligned all docs to OAuth-only | Consistent authentication model |
Support
Issues: https://github.com/sprx-tech/salesforce-crm-sdr/issues
Docs: See references/REFERENCE.md for quick reference
Security: Report vulnerabilities to security@sprx.tax
License: MIT
Version: 2.1.0
Last Updated: May 7, 2026