---
name: client-relationships
description: Compose one client's campaign digest or the internal committed-deal sweep from two sealed playbooks over four read/record Admin MCP operations, and return it as the run's reply for the Hermes gateway to deliver.
visibility: public
allowed-tools:
  - Read
  - Bash
  - mcp__sellable-admin__admin_list_clients
  - mcp__sellable-admin__admin_client_status
  - mcp__sellable-admin__admin_client_channel_record_delivery
  - mcp__sellable-admin__admin_committed_deal_list
---

# Client Relationships

Hermes is the reasoner and the writer. The Admin MCP is the authority for who
our clients are, what their numbers are, which day has already been claimed, and
what is in the committed-deal book. The Hermes GATEWAY is the only thing that
delivers anything. This skill never sends prospect outreach.

## Sealed inputs

Read these files from this skill directory before doing any work:

- `references/aida-client-digest-v1.md`
- `references/shermeen-committed-deal-chase-v1.md`

Accept only these immutable references:

- `aida-client-digest@1#eb737788f5152f003286b36858a4f063bec22f3f70a221c0a8d42de84be64046`
- `shermeen-committed-deal-chase@1#a7f3054ffd49e0b462e77e800421af818703e669b6e45130aa22fcd734fb4601`

Refuse if a file is missing, its declared hash differs, or its `contract-json`
block differs from the prose. Do not repair, reinterpret, edit, or publish a
playbook. Never edit/publish/activate a playbook.

## Two modes, one per cron job

The invocation names the mode.

### `digest <slug>` — ONE client

1. Compute the local business date with
   `Intl.DateTimeFormat("en-CA", { timeZone: "America/New_York" })`.
2. Call `admin_list_clients` and select that slug. If its status is not `ACTIVE`
   or `ONBOARDING`, or it has no `SHARED` channel, reply `[SILENT]`.
3. Call `admin_client_channel_record_delivery` with `phase:"claim"`, the
   `SHARED` channel's ROW id as `channelId`, and that business date. On
   `claimed:false`, reply `[SILENT]` — another run already covered this client
   today, and a same-day retrigger must not deliver a second digest.
4. Call `admin_client_status` once for that client and use its `window7d` and
   `priorWindow7d` blocks.
5. Compose the digest per the sealed Aida playbook and RETURN IT AS THE REPLY.
   That reply is what the gateway delivers to this job's own
   `deliver: "slack:<channelId>"` target. Reply `[SILENT]` when the playbook
   says there is nothing worth posting.

Never post for more than the one client this job is for, and never target the
`REPLIES` or `FOLLOWUPS` rows.

### `chase` — the internal sweep, 30 minutes after the digests

1. Call `admin_committed_deal_list` and compose the sweep per the sealed chase
   playbook.
2. Read `$HERMES_HOME/cron/jobs.json` and, for every job named
   `sellable-client-digest-*`, read its `last_run_at`, `last_status`,
   `last_error` and `last_delivery_error` fields (written by
   `cron/jobs.py:mark_job_run`, which tracks delivery failure separately from
   agent failure and clears it on a successful delivery).
3. For each digest job that ran today, call
   `admin_client_channel_record_delivery` with `phase:"record"` and
   `{ok:true}` when `last_status` is `ok` and `last_delivery_error` is empty,
   otherwise `{ok:false, deliveryError: last_delivery_error}`.
4. Include any delivery failure as an actionable line in the summary, e.g.
   "Clover digest not delivered: not_in_channel — invite the bot to that
   channel".
5. Return the summary as the reply, addressed to the configured
   `<@shermeenSlackUserId>`; the gateway delivers it to the home channel. Reply
   `[SILENT]` when nothing is due and nothing failed.

## Delivery boundary

This agent has no way to send to Slack and must never try.
Its reply is the only outbound path, and the Hermes gateway delivers it.

Specifically forbidden:

- `hermes send`. The CLI cannot see the bot token: the Sellable installer keeps
  `SLACK_BOT_TOKEN` out of the runtime environment on purpose and hands it to
  the gateway over file descriptor 9, which no CLI child inherits. That is a
  security boundary, not an oversight, and defeating that containment is not an
  option.
- Any direct Slack Web API call.
- `curl` or any other terminal Slack write.
- Any other tool or MCP server that reaches Slack.
- The `cronjob` toolset. A runtime-created or runtime-edited job would break the
  byte-identity the next Admin install asserts over the cron inventory.

## Failure handling

A returned `NEEDS_CHANNEL_FIX` is an actionable human row in the summary naming
the raw Slack code and its remedy: `not_in_channel` means invite the Sellable
Admin bot, `channel_not_found` means the stored id is wrong, `is_archived` means
demote the row. A returned `DELIVERY_FAILED` is reported and left for the next
scheduled run. Both are never retried inside the run — a retry loop against a
per-channel rate limit is a retry storm, not a fix.

An unreachable Admin MCP or product route is a visible blocker. Never fall back
to stale data and never answer from a local file.

## Prohibitions

This skill never sends prospect outreach. Never launch, pause or modify a
campaign. Never record a cron run as a committed-deal touch. Never move a deal's
or a client account's status. Never write to any Slack channel selection or
channel policy. Never write to any CRM: there is no tool for it, so any attempt
would be Bash improvisation. Chase evidence is a human-recorded touch with its
own optional evidence reference.
