reassign-deactivated-owners
Reassign contacts and companies from deactivated team members to active owners.
Skill by tomgranot
Chalk Labs
Need help deploying reassign-deactivated-owners?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/tomgranot-reassign-deactivated-owners
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: backend, sales
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Python package
Network hosts it talks to 2
api.hubapi.com· found in codecodeload.github.com· found in install command
Files it touches
~/.claude/skills/reassign-deactivated-owners
What's inside
- Skill name
reassign-deactivated-owners- Description
- Reassign contacts and companies from deactivated team members to active owners. Fully automated via the HubSpot Owners API and Batch Update API. Includes territory analysis for informed reassignment decisions.
- License
- MIT
- Metadata
- author: tomgranot · version: 1.1 · category: database-hygiene
- Instructions
- 510 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
- Instructions call the network
Agent Skills spec issues
- body: 510 lines (spec recommends under 500)
Files (4)
- SKILL.md
- after.py · scripts/
- before.py · scripts/
- execute.py · scripts/
SKILL.md (first lines)
# Reassign Contacts From Deactivated Owners
## Purpose
When team members leave an organization, their HubSpot-owned contacts and companies become orphaned. Leads are not being worked, accounts are not being managed, and any automation that relies on Contact owner or Company owner routes to dead ends. This skill identifies deactivated owners, analyzes their contact portfolios, and batch-reassigns ownership via the API.
## Prerequisites
- A HubSpot service key (`HUBSPOT_ACCESS_TOKEN` in `.env`; an existing legacy private app token also works) with `crm.objects.contacts.read`, `crm.objects.contacts.write`, `crm.objects.companies.read`, `crm.objects.companies.write`, and `crm.objects.owners.read` scopes
- Python 3.10+ with `uv` for package management
- A `.env` file containing `HUBSPOT_ACCESS_TOKEN`
- A decision from team leadership on the reassignment strategy (see Plan stage)
## Scripts
Script paths are relative to this skill's directory. Run them from your project directory so `.env`, `data/`, and `reports/` resolve there: prefix each path with wherever this skill is installed (`skills/reassign-deactivated-owners/` in a clone of the repo).
| Stage | Script | Run with |
|-------|--------|----------|
| Before | [`scripts/before.py`](./scripts/before.py) | `uv run scripts/before.py` |
| Execute | [`scripts/execute.py`](./scripts/execute.py) | `uv run scripts/execute.py` |
| After | [`scripts/after.py`](./scripts/after.py) | `uv run scripts/after.py` |
`before.py` lists deactivated owners and counts their records, exporting the CSV baseline. `execute.py` batch-reassigns to the configured target owner. `after.py` verifies zero records remain with deactivated owners.
## CRITICAL: Retrieving Deactivated Owners
The Owners API requires the `archived=true` parameter to retrieve deactivated users. The default endpoint only returns active owners. This is the most commonly missed detail.
```python
# CORRECT - returns deactivated/archived owners
requests.get(f"{BASE}/crm/v3/owners", headers=headers,
params={"limit": 500, "archived": "true"})
# DEFAULT - returns only active owners
requests.get(f"{BASE}/crm/v3/owners", headers=headers,
params={"limit": 500})
```
Deactivated owners have `"archived": true` in their response object.
## Interview: Gather Requirements
Before executing, collect the following information from the user:
**Q1: Who should contacts from [deactivated user X] be reassigned to?**
- Run the Before State script first to identify deactivated users and their contact counts, then ask this question for each deactivated user found
- Examples: "Assign Jane Doe's 500 contacts to John Smith", "Distribute evenly across the sales team", "Assign all to the Marketing Team user"
- Default: No default -- this requires an explicit business decision for each deactivated user
**Q2: Should unowned contacts be assigned to a default user? If so, who?**
- Examples: "Yes, assign to our Integration User", "Yes, round-robin across the sales team", "No, leave them unowned for now"
- Default: No -- unowned contacts are a separate strategic decision from deactivated-owner contacts
## Execution Pattern
This skill follows a 4-stage execution pattern: **Plan -> Before -> Execute -> After**.
### Stage 1: Plan
Before writing any code, confirm with the user:
1. **Reassignment strategy** -- one of three options:
- **Option A (Unassign)**: Set owner to blank. Best if no one is actively working these contacts and the team wants to start fresh with new assignment rules.
- **Option B (Distribute to active team members)**: Round-robin across current reps. Best if there are active reps who should work these leads.
- **Option C (Assign to shared owner)**: Assign to a single placeholder user (e.g., "Integration User" or "Marketing Team"). Good middle ground.
2. **Territory analysis**: Before reassigning, the user may want to analyze the portfolio of each deactivated owner (customer %, lifecycle distribution, industry breakdown) to make informed decisions about who gets which contacts.
3. **Unassigned contacts**: Ask whether the user also wants to address contacts that have no owner at all. This is a separate strategic decision.
4. **Preserve historical ownership**: Ask whether to create a "Previous Owner" custom property to retain a record of the original assignment.
### Stage 2: Before
Discover all deactivated owners and analyze their contact/company portfolios.
```python
"""
Before State: Identify deactivated owners and their contact/company counts.
"""
import os
import csv
import time
import requests
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.environ["HUBSPOT_ACCESS_TOKEN"]
BASE = "https://api.hubapi.com"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
# --- Step 1: Get all owners (active + deactivated) ---
print("Fetching owners...")
# Active owners
resp_active = requests.get(
f"{BASE}/crm/v3/owners", headers=headers, params={"limit": 500},
)
resp_active.raise_for_status()
active_owners = resp_active.json().get("results", [])
# CRITICAL: Use archived=true for deactivated owners
resp_archived = requests.get(
f"{BASE}/crm/v3/owners", headers=headers,
params={"limit": 500, "archived": "true"},
)
resp_archived.raise_for_status()
deactivated_owners = resp_archived.json().get("results", [])
print(f"Active owners: {len(active_owners)}")
print(f"Deactivated owners: {len(deactivated_owners)}")
print("\nActive owners:")
for o in active_owners:From TomGranot/hubspot-admin-skills, MIT.
More from TomGranot/hubspot-admin-skills
- 0.675score
sandbox-self-test
tomgranot
Verify the entire toolkit against a disposable HubSpot developer test account or sandbox that you bring: seed synthetic fixtures, run every scripted skill's…
SkillAFreshness: A★ 77Claude Code +9 - 0.675score
hubspot-audit
tomgranot
Run a full, read-only HubSpot portal audit covering both the marketing and sales sides: database, deliverability, engagement, owners, pipelines, deal quality…
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
create-icp-tiers
tomgranot
Classify companies into Ideal Customer Profile (ICP) tiers based on firmographic data (industry + employee count).
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
suppress-global-unsubscribes
tomgranot
Identify and suppress globally unsubscribed contacts to ensure legal compliance and reduce billing.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
new-contact-hygiene-workflow
tomgranot
Build a HubSpot workflow that auto-enriches and stages new contacts upon creation.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
merge-duplicate-companies
tomgranot
Identify duplicate company records by domain and name, export audit CSVs for review, and guide merging.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
bounce-monitoring-workflow
tomgranot
Build a workflow to protect sender reputation through automated bounce monitoring.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
lifecycle-progression-workflow
tomgranot
Build workflows to automate contact progression through the sales funnel: Lead to MQL to SQL to Opportunity to Customer.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
build-smart-lists
tomgranot
Create foundational segmented lists for marketing and sales operations via the Lists API, plus advanced UI-built segments: a master sendable list, ICP-based…
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
cleanup-deals
tomgranot
Find past-due, stale, incomplete, unexplained-loss, and likely test deals, then route each owner's flagged deals to them as one review task.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
assign-unowned-contacts
tomgranot
Assign an owner to marketing contacts that have no owner.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
delete-no-email-contacts
tomgranot
Delete contacts with no email address from a HubSpot CRM instance.
SkillAFreshness: A★ 77Claude Code +9
Signals
- Stars
- 77
- Forks
- 18
- Open issues
- 0
- Last commit (this folder)
- Oct 12, 2026 (21 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- Version
- 1.1
- License
- MIT
- Website
- hubspot.granot.io
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from tomgranot
- 0.675score
hubspot-audit
tomgranot
Run a full, read-only HubSpot portal audit covering both the marketing and sales sides: database, deliverability, engagement, owners, pipelines, deal quality…
SkillAFreshness: A★ 77Claude Code +9 - 0.675score
sandbox-self-test
tomgranot
Verify the entire toolkit against a disposable HubSpot developer test account or sandbox that you bring: seed synthetic fixtures, run every scripted skill's…
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
merge-duplicate-companies
tomgranot
Identify duplicate company records by domain and name, export audit CSVs for review, and guide merging.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
suppress-global-unsubscribes
tomgranot
Identify and suppress globally unsubscribed contacts to ensure legal compliance and reduce billing.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
assign-unowned-contacts
tomgranot
Assign an owner to marketing contacts that have no owner.
SkillAFreshness: A★ 77Claude Code +9 - 0.672score
lifecycle-progression-workflow
tomgranot
Build workflows to automate contact progression through the sales funnel: Lead to MQL to SQL to Opportunity to Customer.
SkillAFreshness: A★ 77Claude Code +9
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get reassign-deactivated-owners running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
reassign-deactivated-owners skill. Agent Mart. https://agentmart.dev/skills/tomgranot-reassign-deactivated-owners (last updated 2026-10-24)