文档

stalled-deal-nudge

试用

Flag stalled deals and nudge each rep with a drafted follow-up: every Monday each rep gets one Slack digest of their open deals that went quiet, with how long since the last logged activity, the line that activity left off on, why the deal is worth a touch now, and a follow-up drafted for them to send. Triggers: "flag deals that went quiet", "weekly stalled deal report in slack", "nudge reps on deals with no activity", "which open deals have gone cold", "remind reps to follow up on stuck opportunities", "draft follow-ups for stalled deals weekly". Cargo project, defineAgent, native deal, account and activity models, SQL, Slack postMessage, workspace context, ledger model; adapts to HubSpot, Salesforce or Attio. Skip when: you want the week's GTM work ranked against initiatives, which is weekly-planning; or you want one account researched now, which is research-account.

它能做什么

**State: to-be-approved.** Deploy-verified against a live workspace: yes, on 2026-10-04, on native models seeded with five deals (four open, one closed) and four activities: the selection returned the two deals quiet 24 and 33 days plus the one never touched, and excluded the deal touched the day b…

技能文档

Stalled-deal nudge

State: to-be-approved. Deploy-verified against a live workspace: yes, on 2026-10-04, on native models seeded with five deals (four open, one closed) and four activities: the selection returned the two deals quiet 24 and 33 days plus the one never touched, and excluded the deal touched the day before and the closed one; one digest per owner landed in Slack with one deal_nudges row per deal carrying its ts; a re-run once the ledger was readable posted nothing and wrote nothing. Treat Done when below as the acceptance test and review cargo-ai cdk plan before deploying. Make no outcome claim for this skill until it is approved.

The outcome

An open deal stops dying in silence. Every Monday morning one agent finds the open deals with no logged activity in the last fourteen days and posts one digest per owner to a locked Slack channel. For each deal:

  • How quiet: days since the last logged activity, and how many Mondays running it has been flagged.
  • Last: the line the last note, meeting or call left off on, quoted with its date.
  • Why now: one sentence grounded in that deal, such as a close date about to slip, a next step nobody took, or an objection left unanswered.
  • Draft: a follow-up of at most four sentences that picks up from the quoted line, for the owner to send. The agent never sends it.

The worked example runs on Cargo native models, with no CRM connector: gtm_opportunities (the standard deal schema), gtm_accounts, and gtm_activities, one row per logged email, meeting, call or note. Last activity is computed in SQL as the latest occurred_at per deal, not read off a roll-up property, so "quiet for N days" is a query anyone can read. With deals in HubSpot, Salesforce or Attio, the models are swapped for connector-backed ones and the agent does not change (crm-backed below). A ledger records each deal nudged per ISO week: a re-run the same Monday posts nothing, and a failed post is retried the next run. A native write takes a few minutes to become readable, through SQL and search_records alike, so a re-run within those minutes does not see the ledger yet and posts again; the Monday cadence never comes close. The agent reads the deal models and never writes them.

Example

Every Monday, tell each rep which of their open deals went quiet and draft the follow-up.

Illustrative output, fictional records:

:hourglass: *Stalled deals · Dana Ruiz · 2026-W41*
_2 open deals with no logged activity in 14+ days._

*Fabrikam — Platform* — Proposal, $64,000, closes Oct 31 · quiet 19 days, flagged 1 Monday running
Last: Sep 17 "Send the security questionnaire and we'll take it to procurement."
Why now: The close date is three weeks out and the questionnaire that unblocks procurement never went.
Draft: > Hi Lee, attaching the completed security questionnaire you asked for on the 17th.
       > If procurement needs anything else to keep the Oct 31 date, send it my way today.

*Northwind — Expansion* — Discovery, $22,000, closes Nov 20 · quiet 16 days
Last: Sep 20 "Let's regroup once the Q4 budget is set."
Why now: Q4 budgets were due Oct 1, so the regroup they asked for is now.
Draft: > Hi Priya, you mentioned regrouping once Q4 budget was set. Is this week good?

Five owners had stalled deals, so five digests landed and eleven rows were added to deal_nudges; a second run that Monday posted nothing.

Put it in your project

This folder is a worked example: real CDK resources written for some other company. The job is to end up with the code your company would have written, in your project, and an agent does the adapting. If the cargo-cdk skill is in your session it carries the long form of this; if not, this is enough.

  1. Install it — the CLI does the copy. From inside the CDK project, cargo-ai cdk add cookbook/stalled-deal-nudge writes this example to infra/stalled-deal-nudge/ and this procedure to .claude/skills/stalled-deal-nudge/. No project yet? cargo-ai cdk init --cookbook stalled-deal-nudge && cd && npm install does both. If you are reading this from the project's .claude/skills/, the install already happened — start at step 2. On a CLI too old to have add, copy this folder in as a sibling of what is there by hand; everything below is unchanged.
  2. Reconcile it with what is already declared. If the project already has a Slack or Anthropic connector, or gtm_opportunities, gtm_accounts or gtm_activities models, rewire the imports to the existing one and drop the copy; two resources with one slug is a collision at deploy. If the deals live in a CRM, apply crm-backed now, before the first deploy.
  3. Point Slack at your channel and name the owners. Authorize the Slack connector if the workspace does not have one (cargo-ai cdk add connector/slack). Set channelId in infra/agents/nudger.ts to a channel id (C…) from that connector's channel autocomplete, and invite the bot. Fill OWNERS in infra/agents/nudger.prompt.ts from the distinct owner_id values on open deals. references/digest.md (installed beside this file) is the digest shape.
  4. Adapt. Work the sections below in order: What should not change is what you argue back about (say what breaks, then do it if they still want it); What you can change is what you offer unprompted; What you will be asked is the floor, and you derive before you ask. If you are asking more than about four questions you have skipped lookups. Record what you changed and why under a ## Decisions section in your copy of this file.
  5. Check, then plan. node --import tsx evals/contract.mjs from this skill's folder, then npm run check && cargo-ai cdk plan from the project root. Show the diff, and deploy only on an explicit yes: cargo-ai cdk deploy. Never cdk init --force into a non-empty directory.
  6. Verify. With the models filled (or seeded with test rows, cargo-ai storage record create-bulk), run the prompt's selection by hand (cargo-ai storage SQL over the models) and compare it with what a rep would call stalled. Then send the agent its trigger text once (cargo-ai ai message create), walk Done when line by line with evidence, and send it again: the second run must post nothing.

What you will be asked

Derive before you ask. An input with a lookup is looked up, not asked. Only the ones marked asked genuinely live in the operator's head.

InputKindHow it is answeredWhy it matters
where deals and activities come fromaskedthe native models in this folder, filled by whatever the team already runs (a sync, call-capture, a sequencer), or a CRM via crm-backed. Check what fills them before anything else.An empty gtm_activities model makes every open deal look quiet, and the first digest flags the whole pipeline.
deal and activity columnsderivedRead the models' columns once. The native defineDeal schema carries is_closed, owner_id, stage_name, close_date; gtm_activities carries opportunity_id and occurred_at.The selection rests on these. A CRM-backed swap renames them, and the prompt's SQL has to follow.
QUIET_DAYS (infra/agents/nudger.prompt.ts)askedthe number of days without logged activity after which the team agrees a deal is stalled. Default fourteen.Too short and the digest is noise reps mute; too long and it reports deals already lost.
OWNERS (infra/agents/nudger.prompt.ts)derivedSELECT DISTINCT owner_id over open deals, then the name the digest prints for each.An owner missing from the map lands under "Unassigned or unmapped owner", which nobody reads as theirs.
channelId (infra/agents/nudger.ts)askedthe Slack channel id (C…) the digests may land in, read from the connector's channel autocomplete. Invite the bot.Digests quote deal amounts and prospect lines. Locked so they never land in a customer shared channel.
LLM connector and model (infra/connectors/anthropic.ts)valuederived: cargo-ai connection connector list. languageModel is a placeholder to set.It is what every Monday is billed against.

Checked before moving on, not after the deploy:

  • gtm_opportunities and gtm_activities hold rows, and every open deal's activities carry its opportunity_id
  • the selection SQL run by hand returned deals a rep agrees are stalled, and none that are closed
  • channelId is a C… id the Slack connector can see, and the bot is in that channel
  • node --import tsx evals/contract.mjs passes

What you can change

VariationWhen it is rightHowWhat it costs
quiet-by-stageLate-stage deals should be flagged sooner than early onesReplace the single QUIET_DAYS condition in §1 of the prompt with a CASE on dealstageThe rule gets harder to read in one glance. Keep the table of stage to days in the prompt, not in someone's head.
per-rep-dmReps want their own digest, not a shared channelReplace the locked channelId with one postMessage use per repOne use per rep to maintain. Dropping the lock instead lets the agent pick the destination, which is how a digest reaches the wrong person.
min-amountSmall deals flood the digestAdd amount >= to the §1 SQLSmall deals that matter (a land for a big expansion) go unflagged.
manager-rollupLeadership wants one view of every stalled dealAdd a final post to the same channel: one line per owner with their count and total amountOne more post. It turns a nudge into a scoreboard, which changes how reps read the digest above it.
crm-backedThe deals already live in HubSpot, Salesforce or AttioReplace gtm_opportunities and gtm_activities with connector-backed models of the same slugs that extract every record and every column (fetchRecords, columnSelectionMode: "all", no filter): HubSpot deals plus notes, meetings, calls and emails, or Salesforce Opportunity plus Task and Event. Last activity maps to the latest engagement timestamp (hs_timestamp, ActivityDate), or to the deal roll-up (notes_last_updated, LastActivityDate) if you extract only deals. Adapt the column names in §1 of the prompt; drop the no-connector assertion in the contractOne connector to authorize and a sync to schedule. A roll-up property is only as fresh as the CRM keeps it; engagement rows are what actually happened.
no-draftsReps prefer to write their own follow-upsDrop the Draft line from §3 and §4 of the promptThe digest says what is stuck but not how to unstick it; the cheapest follow-up is the one already written.

What should not change

  • "Stalled" is asked in SQL, over every deal. (infra/agents/nudger.prompt.ts §1) Neither the models nor a CRM-backed extractor filter. Put the rule in an extractor's config and it becomes invisible to anyone reading the query, and changing N means a redeploy and a re-extraction instead of an edited line.
  • Last activity is computed from activity rows. (infra/agents/nudger.prompt.ts §1) A roll-up property a sync forgets to refresh makes every deal look quiet.
  • The ledger is checked before research and written after the post. (infra/agents/nudger.prompt.ts §2 and §5) Check after and every re-run pays for the research again. Write before and a failed post is recorded as sent, so the owner hears nothing and the deal is skipped all week.
  • The ledger, not Slack history, is the dedupe. (infra/agents/nudger.ts) Reading the channel back treats a deleted digest or another bot's post as "already nudged". The contract fails if a Slack read sits on uses.
  • channelId is locked on postMessage. (infra/agents/nudger.ts) Digests carry deal amounts and quoted prospect lines.
  • The deal models are read, never written. (infra/agents/nudger.ts) A nudge that could move a stage or close a deal changes the forecast from a guess. The only writable model is the ledger.
  • The draft is never sent. (infra/agents/nudger.prompt.ts) The owner knows things the CRM does not, such as a call last week nobody logged. A sent draft is how a prospect gets a "just checking in" the day after they signed.
  • Weekly. (infra/agents/nudger.ts) The ledger keys on the ISO week. A daily cron would post Monday's digest and then nothing for six days, which reads as broken; to nudge daily, change the ledger key with it.

Done when

  • node --import tsx evals/contract.mjs passes
  • cargo-ai cdk plan reports the agent, the gtm_opportunities, gtm_accounts, gtm_activities and deal_nudges models, the two connectors and the two folders
  • the hand-run selection returned only open deals whose latest activity is older than QUIET_DAYS
  • the first run posted exactly one digest per owner with stalled deals, in the references/digest.md shape, and wrote one deal_nudges row per deal with the digest's Slack ts
  • a second run the same Monday, once the first run's ledger rows read back through SQL, posted nothing and added no row
  • every Last: quote exists in the gtm_activities row it came from, with that date
  • no draft was sent and no deal, account or activity row changed

What it costs

There is no enrichment provider, no CRM connector and no per-record fan-out: the selection and the last-activity reads are SQL over the workspace's own models. The one connector action is the Slack post. Immediately before the plan, read its live price:

  • cargo-ai orchestration action list postMessage --kind connector --integration-slug slack

Say the number out loud; the run posts once per owner with stalled deals. The recurring cost is the agent run, once a week, billed as LLM tokens through the Anthropic connector. It scales with the number of stalled deals that week, and maxSteps caps it per run. A crm-backed adaptation adds the CRM extract: read its price with cargo-ai connection integration get .

Composes into

call-capture (logged calls are the activity that keeps a deal off the list), meeting-prep (the meeting the nudge books gets a card), and weekly-planning (the stalled count is a line in the week's plan).

相关技能

诊断生产力系统反复失效的根因,给出最小干预——容量测算、瓶颈定位、可靠的本地记录。

作者 Iván855 次安装69 星标

以 AI 机器人身份加入视频会议,提供语音、虚拟形象与屏幕共享四种模式。

作者 johnpatternai22 次安装8 星标

把自然语言描述转为结构化 JSON,并由 mcp-diagram-generator MCP 服务生成 Draw.io、Mermaid 或 Excalidraw 图表文件。

作者 nssa.io1.0k 次安装47 星标

在本地磁盘以分类纯 Markdown 文件保存需要长期留存的事实,与智能体内置记忆并存。

作者 Iván559 次安装18 星标

从 AdMapix API 拉取广告创意、应用、榜单和收入预估等数据,原样返回结构化 JSON。

作者 fly0pants4.3k 次安装296 星标

执行 Git 操作(提交、分支、合并、变基、冲突解决与恢复)时强制套用安全规则。

作者 Iván535 次安装31 星标

cargo-ai 的更多技能

浏览全部技能

读写团队的 GTM 知识库——一个由 Git 管理的 Markdown 仓库,记录 ICP、人设、玩法、证据、异议等。

作者 cargo-ai16 次安装

用一个 CLI 表面执行、构建、绘制并查询 Cargo 工作流、动作、批量与 AI 代理。

作者 cargo-ai16 次安装

查找、认证并配置 Cargo 工作流节点所需的外部系统连接器。

作者 cargo-ai14 次安装

检查并修改 Cargo 工作区的数据模型,并对存储运行 SQL 查询。

作者 cargo-ai14 次安装

在 Cargo 上跑 B2B 拓客、联系人补全、线索打分与 CRM 同步,每一步都内置授权基础与抑制名单校验。

作者 cargo-ai13 次安装

通过 Cargo CLI 管理 AI agent、release、MCP server 与 memory。

作者 cargo-ai17 次安装