Audit and rebalance Salesforce lead assignments using a Claude Code skill

low complexityCost: Usage-based
Compatible agents

This skill works with any agent that supports the Claude Code skills standard, including Claude Code, Claude Cowork, OpenAI Codex, and Google Antigravity.

Prerequisites

Prerequisites
  • Claude Code or another AI coding agent installed
  • Salesforce instance with API access enabled
  • Slack app with chat:write permission (optional, for rebalance notifications)
Environment Variables
# Your Salesforce instance URL (e.g. https://yourorg.my.salesforce.com)
SALESFORCE_INSTANCE_URL=your_value_here
# Salesforce OAuth access token or session token with Lead read/write permissions
SALESFORCE_ACCESS_TOKEN=your_value_here
# Slack bot token (xoxb-...) with chat:write permission — optional, for posting rebalance summaries
SLACK_BOT_TOKEN=your_value_here

Why a Claude Code skill?

Lead rebalancing is inherently conversational. You don't want the same script running blindly — you want to ask questions first:

  • "Show me lead distribution for the last 7 days"
  • "Which reps have more than 20% above average?"
  • "Rebalance leads across the team and notify everyone in Slack"
  • "Move all of Alice's leads to Bob — she's out this week"

The agent reads API reference files, builds the right SOQL query for your request, calculates the redistribution, and updates Salesforce — all without you writing code. Unlike the Flow or n8n approaches, this handles bulk reassignment of existing records naturally.

How it works

The skill has three parts:

  1. SKILL.md — instructions telling the agent the audit and rebalance workflow
  2. references/ — API documentation for Salesforce SOQL queries, sObject PATCH, and Slack chat.postMessage
  3. templates/ — the rep roster with Salesforce User IDs and Slack User IDs

When you invoke the skill, the agent reads these files, writes a script that follows the patterns, executes it, and reports the results.

What is a Claude Code skill?

An Claude Code skill is a directory of reference files and instructions that teach an AI coding agent how to complete a specific task. Unlike traditional automation that runs the same code every time, a skill lets the agent adapt — it can modify SOQL filters, change the time window, handle rep roster changes, and explain what it did, all based on your natural-language request. The agent generates and runs code on the fly using the API patterns in the reference files.

Step 1: Create the skill directory

mkdir -p .claude/skills/rebalance-sf-leads/{templates,references}

Step 2: Write the SKILL.md file

Create .claude/skills/rebalance-sf-leads/SKILL.md:

---
name: rebalance-sf-leads
description: Audit and rebalance Salesforce lead assignments across the sales team. Queries recent leads, reports distribution, and optionally redistributes evenly with Slack notifications.
disable-model-invocation: true
allowed-tools: Bash, Read
---
 
## Workflow
 
1. Read `references/salesforce-api.md` for SOQL query and sObject update patterns
2. Read `references/slack-api.md` for posting rebalance notifications
3. Read `templates/rep-roster.md` for the team roster with Salesforce and Slack IDs
4. Query Salesforce for Leads created in the requested time window (default: last 7 days), filtered to reps in the roster
5. Group leads by OwnerId and count per rep
6. Report the current distribution: leads per rep, ideal per rep, and max imbalance
7. If the user asks to rebalance, redistribute leads evenly using round-robin across the roster
8. PATCH each reassigned Lead's OwnerId in Salesforce
9. Post a summary to Slack (#sales-ops) and DM each rep with their updated lead list
10. Print final distribution
 
## Rules
 
- Default to audit-only mode — show the distribution without making changes
- Only rebalance when the user explicitly asks
- Skip leads not assigned to reps in the roster (e.g., queue-owned leads)
- Rate limit: 200ms between Salesforce PATCH calls to stay within API limits
- If SLACK_BOT_TOKEN is not set, skip Slack notifications
- Use environment variables: SALESFORCE_INSTANCE_URL, SALESFORCE_ACCESS_TOKEN, SLACK_BOT_TOKEN

Step 3: Add reference and template files

Create references/salesforce-api.md:

# Salesforce REST API Reference
 
## Query records with SOQL
 
```
GET {SALESFORCE_INSTANCE_URL}/services/data/v59.0/query?q={SOQL}
Authorization: Bearer {SALESFORCE_ACCESS_TOKEN}
```
 
Example SOQL — find recent leads assigned to specific reps:
```sql
SELECT Id, Name, Email, Company, OwnerId, CreatedDate
FROM Lead
WHERE CreatedDate >= 2024-01-01T00:00:00Z
AND OwnerId IN ('005xx0000012345','005xx0000023456')
ORDER BY CreatedDate ASC
```
 
Response:
```json
{
  "totalSize": 84,
  "records": [
    {
      "Id": "00Q5e000001abc",
      "Name": "Jane Smith",
      "Email": "jane@acme.com",
      "Company": "Acme Inc",
      "OwnerId": "005xx0000012345",
      "CreatedDate": "2024-01-15T14:30:00.000+0000"
    }
  ]
}
```
 
## Update a Lead
 
```
PATCH {SALESFORCE_INSTANCE_URL}/services/data/v59.0/sobjects/Lead/{LeadId}
Authorization: Bearer {SALESFORCE_ACCESS_TOKEN}
Content-Type: application/json
```
 
Request body:
```json
{
  "OwnerId": "005xx0000023456"
}
```
 
Successful response: HTTP 204 No Content.
 
Notes:
- OwnerId accepts both User IDs (005...) and Queue IDs (00G...)
- Access token expires per session timeout. Use refresh tokens for scheduled runs
- SOQL strings must be URL-encoded when passed as query params
- Salesforce enforces 15,000 API calls per 24-hour period on Enterprise Edition

Create references/slack-api.md:

# Slack API Reference
 
## Post a message
 
```
POST https://slack.com/api/chat.postMessage
Authorization: Bearer {SLACK_BOT_TOKEN}
Content-Type: application/json
```
 
Request body (channel message):
```json
{
  "channel": "#sales-ops",
  "text": "Lead rebalance complete — 84 leads redistributed",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*Lead Rebalance Complete*\n84 leads redistributed across 4 reps:\n\n*Alice*: 21 leads\n*Bob*: 21 leads\n*Carol*: 21 leads\n*Dave*: 21 leads"
      }
    }
  ]
}
```
 
Request body (DM to a user):
```json
{
  "channel": "U01AAAA",
  "text": "Your leads have been rebalanced — you now have 21 leads"
}
```
 
Notes:
- To DM a user, set `channel` to their Slack User ID (starts with U)
- The bot must have `chat:write` scope
- The bot must be added to the target channel for channel messages
- `text` is the fallback shown in notifications; `blocks` render in the Slack client

Create templates/rep-roster.md:

# Rep Roster
 
Replace the placeholder IDs below with your actual Salesforce User IDs and Slack User IDs.
 
| Name | Salesforce User ID | Slack User ID | Active |
|------|-------------------|---------------|--------|
| Alice Smith | 005xx0000012345 | U01AAAA | yes |
| Bob Jones | 005xx0000023456 | U02BBBB | yes |
| Carol Chen | 005xx0000034567 | U03CCCC | yes |
| Dave Kim | 005xx0000045678 | U04DDDD | yes |
 
## How to find IDs
 
- **Salesforce User ID**: Setup → Users → click a user → the 18-character ID is in the URL (starts with `005`)
- **Slack User ID**: Click a user's profile in Slack → More → Copy member ID (starts with `U`)
 
## Rules
 
1. Only include reps who should receive leads in the rotation
2. Set Active to "no" for reps who are out of office — the agent will skip them
3. The rebalance distributes leads evenly across all active reps

Step 4: Test the skill

# In Claude Code
/rebalance-sf-leads

Start with an audit:

"Show me lead distribution for the last 7 days"

The agent will query Salesforce, count leads per rep, and display the current distribution without making any changes.

Step 5: Schedule it (optional)

Option A: Cron + CLI

# Audit every Monday morning (report only, no rebalance)
0 9 * * 1 cd /path/to/project && claude -p "Run /rebalance-sf-leads — show lead distribution for the last 7 days." --allowedTools 'Bash,Read' 2>&1 >> /var/log/sf-rebalance.log

Option B: GitHub Actions

name: Salesforce Lead Distribution Audit
on:
  schedule:
    - cron: '0 14 * * 1'  # 9 AM ET Monday = 2 PM UTC
  workflow_dispatch: {}
jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: anthropics/claude-code-action@v1
        with:
          prompt: "Run /rebalance-sf-leads — show lead distribution for the last 7 days."
          allowed_tools: "Bash,Read"
        env:
          SALESFORCE_INSTANCE_URL: ${{ secrets.SALESFORCE_INSTANCE_URL }}
          SALESFORCE_ACCESS_TOKEN: ${{ secrets.SALESFORCE_ACCESS_TOKEN }}
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

Option C: Cowork Scheduled Tasks

Claude Desktop's Cowork supports built-in scheduled tasks. Open a Cowork session, type /schedule, and configure the cadence — hourly, daily, weekly, or weekdays only. Each scheduled run has full access to your connected tools, plugins, and MCP servers.

Scheduled tasks only run while your computer is awake and Claude Desktop is open. If a run is missed, Cowork executes it automatically when the app reopens. For always-on scheduling, use GitHub Actions (Option B) instead. Available on all paid plans (Pro, Max, Team, Enterprise).

Troubleshooting

When to use this approach

  • A rep leaves or joins the team and you need to redistribute their leads
  • Lead assignments have drifted out of balance over the quarter
  • You want a weekly audit of lead distribution without setting up dashboards
  • You need a one-time bulk reassignment before turning on always-on routing

When to switch to a dedicated tool

  • You need real-time assignment on Lead creation (use Salesforce Flow or n8n)
  • You want always-on round-robin without human involvement
  • Multiple team members need to manage the rep roster through a visual interface

Common questions

Does the agent rebalance automatically or ask first?

By default, the agent only audits — it shows the current distribution and reports imbalances. You must explicitly ask it to rebalance (e.g., "go ahead and redistribute evenly"). This is controlled by the "audit-only by default" rule in SKILL.md.

Can I rebalance a specific rep's leads?

Yes. Tell the agent: "Move all of Alice's leads to the rest of the team" or "Redistribute leads from Alice and Bob evenly across Carol and Dave." The agent adjusts the SOQL query and redistribution logic accordingly.

How many Salesforce API calls does a rebalance use?

1 call for the SOQL query + 1 PATCH call per reassigned lead. For 100 leads where 60 need reassignment, that's 61 API calls. Salesforce Enterprise allows 15,000 API calls per 24-hour period, so even large rebalances are well within limits.

Cost

  • Salesforce: API usage included in your plan (15,000 calls/day on Enterprise).
  • Slack: Free tier supports bot messaging.
  • Claude Code: Usage-based pricing per conversation.
  • GitHub Actions: Free tier covers weekly scheduled runs.

Looking to scale your AI operations?

We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.