Solution Page
Turn cross-functional Slack activity into a concise CEO briefing with wins, risks, decisions required, and next-week watch items.
Overview
For CEOs, Chiefs of Staff, Founders
Integrations: Slack signals, Executive brief, Risk tracking
• Executive brief
• Risk summary
• Decision queue
• Watch items
• Creates a dependable executive operating rhythm.
• Reduces manual briefing work for chiefs of staff and founders.
• Makes organizational signal easier to review week over week.
What It Solves
Executive updates are often delayed, subjective, and dependent on someone manually stitching together cross-functional context.
Workflow
Collect operating signals from Slack and connected workflows.
Classify wins, risks, decisions, and watch items into an executive frame.
Deliver a weekly brief that leadership can consume quickly.
Implementation
Review the underlying plan definition, inspect the template when available, and see how the workflow is encoded for repeatable execution.
Plan Code
Markdown Report
ceo-weekly-pulse.yaml
478 lines
# CEO Weekly Pulse Report
# Pulls recent Slack history from sales, dev, leadership, and health-check
# using explicit channel IDs via preCalls, then synthesizes a structured
# executive brief for a CEO audience.
transformers:
- name: cleanup_slack_history
onFunctionOutput: conversations_history
jmesPath: 'structuredContent.messages || result.messages || messages'
requiredTools:
- name: slack
type: mcp
parameters:
- name: lookBackDays
schema:
type: string
default: "7"
title: "Look Back Days"
description: "Number of days of Slack history to retrieve (for example: '7')"
- name: reportWeekOf
schema:
type: string
default: ""
description: "Week-ending date label, for example 'March 21, 2026'. Leave blank to auto-detect."
preCalls:
- name: computeCutoff
in: vars
var: oldestTs
args:
days: "{{ .params.lookBackDays }}"
code: |-
const days = parseInt(args.days, 10);
const safeDays = Number.isFinite(days) && days > 0 ? days : 7;
const nowSec = Math.floor(Date.now() / 1000);
nowSec - (safeDays * 86400);
- name: conversations_history
in: vars
var: salesRaw
args:
channel: "C091MES33UK"
oldest: "{{ .vars.oldestTs }}"
limit: 200
- name: conversations_history
in: vars
var: devRaw
args:
channel: "C08A3PZ78NL"
oldest: "{{ .vars.oldestTs }}"
limit: 200
- name: conversations_history
in: vars
var: leadershipRaw
args:
channel: "C08K10S721K"
oldest: "{{ .vars.oldestTs }}"
limit: 200
- name: conversations_history
in: vars
var: healthCheckRaw
args:
channel: "C095SEVCS1G"
oldest: "{{ .vars.oldestTs }}"
limit: 200
components:
schemas:
DepartmentPulse:
type: object
required:
- headline
- wins
- blockers
- risks
- sentiment
- notableThreads
properties:
headline:
type: string
description: "One sentence — the single most important thing happening in this department this week"
wins:
type: array
items:
type: string
description: "Concrete achievements, closed deals, shipped work, or milestones landed"
blockers:
type: array
items:
type: string
description: "Active blockers, unresolved dependencies, or slowdowns raised in the channel"
risks:
type: array
items:
type: string
description: "Forward-looking risks or concerns a CEO should monitor"
sentiment:
type: string
enum: [strong, steady, concerning, unclear]
description: "Overall team energy and momentum reading for the week"
notableThreads:
type: array
items:
type: string
description: "2-3 significant discussions or decisions worth CEO awareness"
sessions:
extract-sales-signals:
prompt: |-
You are a business analyst preparing a CEO briefing.
The conversations_history call returned Slack messages for sales.
The transformer cleaned them into a list of messages.
Here is the Slack history for sales:
```json
{{ json .vars.salesRaw }}
```
Map this data exactly to the salesSignals schema.
Focus on:
- deal updates
- pipeline movement
- customer wins or losses
- quota progress
- objections heard in the field
- pricing or competitive mentions
Sentiment classification rules:
- use "strong" when wins clearly outweigh blockers and risks and momentum is positive
- use "steady" when work is progressing normally with manageable blockers
- use "concerning" when blockers, slippage, or risks materially threaten progress
- use "unclear" only when there is not enough signal in the retrieved messages
- sentiment is required and must never be blank
If the channel is inaccessible, missing, or contains no messages in the selected time window,
still return a valid DepartmentPulse with:
- headline: "No messages retrieved from the sales channel in the selected time window."
- wins: []
- blockers: []
- risks: []
- sentiment: "unclear"
- notableThreads: []
Do not return an empty string for sentiment.
extract-dev-signals:
prompt: |-
You are a business analyst preparing a CEO briefing.
The conversations_history call returned Slack messages for dev.
The transformer cleaned them into a list of messages.
Here is the Slack history for dev:
```json
{{ json .vars.devRaw }}
```
Map this data exactly to the devSignals schema.
Focus on:
- features shipped
- bugs in production
- incidents
- deployment status
- technical debt discussions
- scope changes
- any signs of timelines slipping or accelerating
Translate technical language into business impact where possible.
Sentiment classification rules:
- use "strong" when delivery is healthy and wins clearly outweigh blockers
- use "steady" when execution is progressing with manageable issues
- use "concerning" when incidents, deployment problems, tool limits, or technical blockers materially threaten progress
- use "unclear" only when there is not enough signal in the retrieved messages
- sentiment is required and must never be blank
If the channel is inaccessible, missing, or contains no messages in the selected time window,
still return a valid DepartmentPulse with:
- headline: "No messages retrieved from the dev channel in the selected time window."
- wins: []
- blockers: []
- risks: []
- sentiment: "unclear"
- notableThreads: []
Do not return an empty string for sentiment.
extract-leadership-signals:
prompt: |-
You are a business analyst preparing a CEO briefing.
The conversations_history call returned Slack messages for leadership.
The transformer cleaned them into a list of messages.
Here is the Slack history for leadership:
```json
{{ json .vars.leadershipRaw }}
```
Map this data exactly to the leadershipSignals schema.
Focus on:
- strategic discussions
- directional decisions made or deferred
- cross-functional priorities
- goal progress or slippage
- resourcing conversations
- escalations
- issues requiring CEO visibility or intervention
Sentiment classification rules:
- use "strong" when leadership signals show aligned momentum and clear progress
- use "steady" when leadership is operating normally with contained concerns
- use "concerning" when there are escalations, strategic tension, security concerns, or material adoption risks
- use "unclear" only when there is not enough signal in the retrieved messages
- sentiment is required and must never be blank
If the channel is inaccessible, missing, or contains no messages in the selected time window,
still return a valid DepartmentPulse with:
- headline: "No messages retrieved from the leadership channel in the selected time window."
- wins: []
- blockers: []
- risks: []
- sentiment: "unclear"
- notableThreads: []
Do not return an empty string for sentiment.
extract-health-check-signals:
prompt: |-
You are a business analyst preparing a CEO briefing.
The conversations_history call returned Slack messages for health-check.
The transformer cleaned them into a list of messages.
Here is the Slack history for health-check:
```json
{{ json .vars.healthCheckRaw }}
```
Map this data exactly to the healthCheckSignals schema.
Focus on:
- alerts
- outages
- degraded services
- on-call escalations
- infrastructure bottlenecks
- deployment failures
- remediation work
- operational risks that could affect customers or team throughput
Translate technical alerts into business terms where possible.
Sentiment classification rules:
- use "strong" when systems are stable and operational wins clearly outweigh incidents
- use "steady" when systems are healthy with manageable operational noise
- use "concerning" when outages, degraded services, incidents, or infrastructure risks materially affect customers or team throughput
- use "unclear" only when there is not enough signal in the retrieved messages
- sentiment is required and must never be blank
If the channel is inaccessible, missing, or contains no messages in the selected time window,
still return a valid DepartmentPulse with:
- headline: "No messages retrieved from the health-check channel in the selected time window."
- wins: []
- blockers: []
- risks: []
- sentiment: "unclear"
- notableThreads: []
Do not return an empty string for sentiment.
build-ceo-report:
dependsOn:
- session: extract-sales-signals
- session: extract-dev-signals
- session: extract-leadership-signals
- session: extract-health-check-signals
context: true
prompt: |-
You are the Chief of Staff preparing the weekly CEO report.
{{ if .params.reportWeekOf }}The report covers the week of {{ .params.reportWeekOf }}.{{ else }}Use today's date to determine and label the report week automatically.{{ end }}
The structured signals available in context are:
- salesSignals
- devSignals
- leadershipSignals
- healthCheckSignals
Produce a polished executive brief for a CEO audience.
Write it the way a CEO wants to read it:
- Lead with the most important thing happening in the business right now
- Be direct and specific — no vague language, no filler
- Surface decisions the CEO needs to make or conversations they need to have
- Flag risks before they become crises
- Celebrate wins clearly and attribute them
- The CEO reads this in under 5 minutes — every sentence must earn its place
Requirements:
- executiveSummary must be a 3-5 sentence memo, not bullets
- companyMomentum.overallSentiment must be one of: accelerating, steady, mixed, at-risk
- every department sentiment must be one of: strong, steady, concerning, unclear
- every decisionsRequired.urgency must be one of: this-week, this-month, watching
- if a department has no real activity, keep the empty arrays and use sentiment "unclear"
- set reportMeta.channelsCovered to the four channel categories, not raw IDs
- set reportMeta.generatedAt to a current ISO timestamp
- do not return empty strings for any enum field
- if all departments have no real activity, set companyMomentum.overallSentiment to "at-risk"
- if all departments have no real activity and you create one escalation item, set its urgency to "this-week"
Overall sentiment classification rules:
- use "accelerating" when multiple departments show strong forward momentum with limited risk
- use "steady" when execution is healthy and risks are contained
- use "mixed" when there are meaningful wins and meaningful risks at the same time
- use "at-risk" when blockers or operational risk materially threaten company execution
- overallSentiment is required and must never be blank
Populate every final field explicitly:
- reportMeta.weekOf
- reportMeta.generatedAt
- reportMeta.channelsCovered
- executiveSummary
- companyMomentum.overallSentiment
- companyMomentum.topWin
- companyMomentum.topRisk
- departments.sales
- departments.dev
- departments.leadership
- departments.healthCheck
- decisionsRequired
- lookingAhead.keyMilestones
- lookingAhead.watchList
The departments object should be synthesized directly from the intermediate signals:
- departments.sales from salesSignals
- departments.dev from devSignals
- departments.leadership from leadershipSignals
- departments.healthCheck from healthCheckSignals
Do not leave reportMeta, executiveSummary, companyMomentum, or departments fields blank if relevant signal data exists.
schema:
type: object
properties:
salesSignals:
x-session: extract-sales-signals
$ref: "#/components/schemas/DepartmentPulse"
devSignals:
x-session: extract-dev-signals
$ref: "#/components/schemas/DepartmentPulse"
leadershipSignals:
x-session: extract-leadership-signals
$ref: "#/components/schemas/DepartmentPulse"
healthCheckSignals:
x-session: extract-health-check-signals
$ref: "#/components/schemas/DepartmentPulse"
reportMeta:
x-session: build-ceo-report
type: object
description: "Report header metadata"
required:
- weekOf
- generatedAt
- channelsCovered
properties:
weekOf:
type: string
description: "Week-ending date this report covers, for example 'March 21, 2026'"
generatedAt:
type: string
description: "ISO timestamp when the report was generated"
channelsCovered:
type: array
items:
type: string
description: "List of Slack channels included in this report"
executiveSummary:
x-session: build-ceo-report
type: string
description: >
3-5 sentence memo written directly to the CEO. Leads with the biggest business
development this week (positive or negative), then calls out the most important
cross-functional signal, and closes with what needs the CEO's attention.
Written in confident, direct prose — not bullets.
companyMomentum:
x-session: build-ceo-report
type: object
description: "Top-line momentum read across all departments"
required:
- overallSentiment
- topWin
- topRisk
properties:
overallSentiment:
type: string
enum: [accelerating, steady, mixed, at-risk]
description: "CEO's one-word read on where the company is this week"
topWin:
type: string
description: "The single best thing that happened this week, company-wide"
topRisk:
type: string
description: "The single most pressing risk on the CEO's radar this week"
departments:
x-session: build-ceo-report
type: object
description: "Department-by-department pulse"
required:
- sales
- dev
- leadership
- healthCheck
properties:
sales:
$ref: "#/components/schemas/DepartmentPulse"
dev:
$ref: "#/components/schemas/DepartmentPulse"
leadership:
$ref: "#/components/schemas/DepartmentPulse"
healthCheck:
$ref: "#/components/schemas/DepartmentPulse"
decisionsRequired:
x-session: build-ceo-report
type: array
description: "Explicit decisions or interventions the CEO needs to make this week"
items:
type: object
required:
- decision
- context
- urgency
- raisedBy
properties:
decision:
type: string
description: "What needs to be decided or acted on"
context:
type: string
description: "Why this is on the CEO's plate — what's blocking or at stake"
urgency:
type: string
enum: [this-week, this-month, watching]
description: "How soon the CEO needs to engage"
raisedBy:
type: string
description: "Team or person who surfaced this issue in Slack"
lookingAhead:
x-session: build-ceo-report
type: object
description: "Forward-looking view into next week"
required:
- keyMilestones
- watchList
properties:
keyMilestones:
type: array
items:
type: string
description: "Launches, deadlines, or commitments due in the next 7 days mentioned across channels"
watchList:
type: array
items:
type: string
description: "Situations that aren't crises yet but the CEO should keep an eye on"