Skip to content
Back to skills

Inbound From Domain

ASecurity

Route an inbound lead from its email domain in seconds: corporate, free-mail, disposable, or personal-looking, then a route card. Use when the user says: \"who just filled in this form\", \"route this inbound\", \"is this a real company\", \"triage this lead\". Never writes the CRM. For finding more contacts, see waterfall-email.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
ai-agentspythongobashapi

Works with

  • api

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned November 11, 2026

npx -y skills add cmj-hub/gtm-operator-skills --skill inbound-from-domain --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Inbound From Domain?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Inbound From Domain
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/cmj-hub-inbound-from-domain/badge)](https://www.skillsdirectory.com/skills/cmj-hub-inbound-from-domain)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: inbound-from-domain
description: "Route an inbound lead from its email domain in seconds: corporate, free-mail, disposable, or personal-looking, then a route card. Use when the user says: \"who just filled in this form\", \"route this inbound\", \"is this a real company\", \"triage this lead\". Never writes the CRM. For finding more contacts, see waterfall-email."
argument-hint: "[email or draft | score]"
allowed-tools: Read Write(./gtm/**) Bash(python3 ${CLAUDE_SKILL_DIR}/scripts/score.py:*)
license: MIT
models: ""
---

# Inbound from domain

Enrich inbound from the email domain. Route in seconds. The free pack stops at the route card — it does not write the CRM.

The build guide teaches a human. This pack teaches an agent.

## Start

If `$ARGUMENTS` is `score`, run the scorer on `gtm/inbound.json` and report each line. Otherwise `$ARGUMENTS` names an inbound email or is empty; work through the checklist below. The draft lives at `gtm/inbound.json`; create `gtm/` if missing. On bare invocation with no draft, load `inbound-from-domain-kickoff` first.

## What you hold

Write one JSON route card:

```json
{
  "email": "alex@northwind.io",
  "domain": "northwind.io",
  "kind": "corporate",
  "company_guess": "Northwind",
  "evidence": [
    "Domain is not on the free-mail list",
    "Company-shaped second-level name"
  ],
  "route": "high-touch",
  "crm_write": false
}
```

1. `email`. The inbound address.
2. `domain`. The part after `@`, lowercased.
3. `kind`. One of: `corporate`, `free-mail`, `disposable`, `personal-looking`.
4. `company_guess`. Short name from the domain when `kind` is `corporate`.
5. `evidence`. One or more checkable facts that drove the kind (free-mail list hit, disposable list hit, company-shaped domain).
6. `route`. One of: `high-touch`, `self-serve`, `need-more`, `personal`, `disqualify`.
7. `crm_write`. Always `false` in this pack.

## Kinds

| Kind | Meaning | Typical route |
| --- | --- | --- |
| `corporate` | Company domain, not free-mail | `high-touch` or `self-serve` |
| `free-mail` | gmail, outlook, icloud, and peers | `personal` or `need-more` |
| `disposable` | Temp / throwaway inbox | `disqualify` |
| `personal-looking` | Ambiguous non-free domain | `need-more` |

## Routes

| Route | When |
| --- | --- |
| `high-touch` | Corporate domain that looks like a company worth a human look |
| `self-serve` | DIY / seat-shaped inbound on a real domain |
| `need-more` | Ambiguous; ask one clarifying question before routing |
| `personal` | Free-mail; treat as a person, not a logo |
| `disqualify` | Disposable, clear out, or seller-risk you already know |

## Banned patterns

Copy these. Do not soften them.

- **No CRM write-back in the free pack.** `crm_write` stays `false`. The route card is the artifact. A human owns the CRM upsert.
- **Free-mail is not Build.** Do not route `gmail.com` (and peers) to `high-touch`.
- **Disposable is disqualify.** Do not keep a temp inbox alive as `need-more`.
- **Evidence is required.** A kind with no checkable fact is a guess, not enrichment.

| Passes | Refused |
| --- | --- |
| corporate + high-touch + crm_write false | crm_write true |
| free-mail + personal + crm_write false | free-mail + high-touch |
| disposable + disqualify + crm_write false | disposable + need-more |

## Checklist

Copy this list and tick it in order.

- [ ] 1. Take the inbound `email` and extract `domain`.
- [ ] 2. Classify `kind` from the domain (free-mail list, disposable list, or company-shaped).
- [ ] 3. Write `evidence` — one fact you could show a teammate.
- [ ] 4. Set `company_guess` when `kind` is `corporate`.
- [ ] 5. Pick `route`. Set `crm_write: false`.
- [ ] 6. Write the object to `gtm/inbound.json` (create `gtm/` if missing).
- [ ] 7. Run `python3 ${CLAUDE_SKILL_DIR}/scripts/score.py --file gtm/inbound.json`.

Go back to step 2 if step 7 exits 1. Stop when it exits 0. The last line hands the route card to a human — this pack does not write the CRM.

The scorer runs from this skill's directory (`${CLAUDE_SKILL_DIR}`). Use `--stdin` to pipe the object, and `--json` for one result object (`ok`, `verdict`, `reasons`, `fixes` parallel to `reasons`, `next`).

## Run

```bash
python3 ${CLAUDE_SKILL_DIR}/scripts/score.py --file ${CLAUDE_SKILL_DIR}/examples/inbound-good.json
python3 ${CLAUDE_SKILL_DIR}/scripts/score.py --file ${CLAUDE_SKILL_DIR}/examples/inbound-crm-write.json
```

| File | Exit | Why |
| --- | --- | --- |
| `examples/inbound-good.json` | 0 | Corporate domain → high-touch, no CRM write. |
| `examples/inbound-freemail.json` | 0 | Free-mail → personal, held. |
| `examples/inbound-disposable.json` | 0 | Disposable → disqualify. |
| `examples/inbound-crm-write.json` | 1 | CRM write-back banned. |
| `examples/inbound-freemail-build.json` | 1 | Free-mail routed to Build. |

Exit 2 means the input could not be read: missing file, not UTF-8, broken JSON, or not an object. A broken JSON does not echo the raw input.

## Works with the suite

Part of the GTM operator suite (`/plugin marketplace add cmj-hub/gtm-operator-skills`).

- **Writes:** `gtm/inbound.json` only. Never touches `brand-config.json`. Never writes a CRM.
- **Before this:** a form, reply, or lead with an email. qualify-before-enrich when list ICP fields fail before any paid lookup.
- **After this:** a human reviews the route card and updates the CRM.
- **Not this pack:** live Firecrawl / firmographic APIs, existing-customer CRM lookup, or auto-reply send. Those are out of scope for this pack.

If a companion pack is not installed, name it and its install line (`/plugin install <name>@gtm-operator-skills`); do not do its job inline.

Python 3 standard library only. No network. No paid API. No CRM write-back.

Files in this skill

  • SKILL.md5.6 KB
  • examples/inbound-crm-write.json227 B
  • examples/inbound-disposable.json203 B
  • examples/inbound-freemail-build.json188 B
  • examples/inbound-freemail.json186 B
  • examples/inbound-good.json268 B
  • scripts/score.py11.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.