mcpbeat Sign in

Cowork Dashboard Team Dashboard Agent Skill

| Manager-side team rollup for Copilot Cowork ROI. Aggregates the de-identified stats teammates post (via the Cowork Team Report Member skill) to a shared Teams channel into ONE anonymized HTML dashboard (five tabs, with the how-to-read guide built in), then emails the channel members a summary with the dashboard attached. First run asks for the Teams channel link and remembers it; each run reads the latest 15 days and keeps the latest post per person. Numbers only — no names or files; a Role breaks out only when 3+ share it. Small homogeneous teams; not org-wide. Use when the user asks to "build the team Cowork Team Report", "aggregate my team's Cowork stats", "roll up the channel posts", "manager Cowork Team Report", "email the team dashboard", or set up / refresh the rollup.

40k tokens
context cost
the whole folder, loaded on every use
15
files
ships runnable scripts
0
copies elsewhere
how many repositories repackaged it
6
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/microsoft/CoworkDashboard --skill cowork-dashboard-team-dashboard

What comes with it

145 309 bytes besides the instruction
CHANGELOG.md
README.md
config/team_config.json
examples/sample_raw_messages.json
references/value-pillars.md
scripts/build_dashboard.py
scripts/build_guide_pdf.py
scripts/build_outputs.py
scripts/parse_posts.py
scripts/process_groups.json
scripts/resolve_channel.py
scripts/roles_taxonomy.json
scripts/skill_aliases.json
scripts/skills_vocabulary.json

The instruction itself

16 sections, as written by the author

Cowork Team Report — Team Dashboard (manager rollup)

Aggregates the de-identified Cowork Team Report posts teammates publish (via the **Copilot ROI

Member** skill, cowork-dashboard-member) to a shared Teams channel, renders a single self-contained,

anonymized HTML dashboard, and emails the channel members a high-level summary with the

dashboard attached. The interpretation guide is built into the dashboard (the How to read

tab, plus a clickable "?" on every section title) — there is no separate PDF attachment by

default, so recipients read everything in one file.

This skill only reads what the Member skill posts. It never harvests anyone's OneDrive and

never sees names, files, or prompts. If a label (business process, skill, Role) doesn't match the

Member bundle's copy, aggregation drifts — the taxonomy files here are byte-for-byte mirrors of

the Member skill's (see *Cross-skill contract*).

Scope (v1)

  • Small, homogeneous teams (people doing similar work), team level. A handful of

contributors sharing one channel.

  • Not org-wide / large-team / multi-channel aggregation, and not cross-team benchmarking.

When NOT to Use

  • A single person's full impact reportcowork-roi-report (rich personal web app).
  • Posting your own de-identified stats to the channel → cowork-dashboard-member.
  • The member-side anonymized table postcowork-roi-report-aggregated.
  • Org-wide / multi-team / cross-channel aggregation — out of scope for v1; don't force it.
  • GitHub Copilot / IDE usage reports, daily briefings, or single-meeting summaries

different skills entirely.

  • If the shared channel has no Cowork Team Report posts in the last 15 days, don't fabricate a dashboard —

say the window was empty and offer to widen it.

First run — point the skill at the channel (once)

The rollup reads ONE shared Teams channel that teammates post to. The channel is not hard-coded.

  • Load config/team_config.json. If team_id or channel_id is blank, this is a first run.
  • Ask for the channel link. Use AskUserQuestion to ask the user to paste the **link of the

Teams channel** where the team posts its Cowork Team Report stats (in Teams: channel ⋯ → *Get link to

channel*). This must be the same channel cowork-dashboard-member posts to.

  • Resolve + persist the IDs from that link — no Graph call needed:
   python scripts/resolve_channel.py --link "<pasted url>" --config config/team_config.json

It extracts channel_id (the 19:…@thread.… segment) and team_id (the groupId), writes them

plus channel_link back to the config, and every later run reads the same place. Optionally call

GetTeam(team_id) and save its displayName as team_name so the dashboard header is named.

  • The Team must already exist and the runner must be a member of it

(ChannelMessage.Read.All). This skill does not create Teams or channels. If a read fails with an

authorization error, the runner isn't a member — add them in Teams; the skill can't grant access.

On later runs team_id + channel_id are already set, so skip straight to the workflow. Re-ask for a

link only if the user wants to point at a different channel.

Workflow

Read config/team_config.json. If team_id/channel_id are blank, run First run above.

2. Read the channel posts (latest 15 days)

ListChannelMessages(team_id, channel_id, top=50) (paginate with next_link if the team is chatty).

Save the returned value array verbatim to working/raw_messages.json (the parser accepts the Graph

message shape directly). The latest-15-days window and latest-post-per-person dedupe are

applied in step 3 — don't hand-filter here.

3. Parse + aggregate (window, anonymize, group, canonicalize)

python scripts/parse_posts.py --in working/raw_messages.json --config config/team_config.json \
       --out working/team_data.json --window-days 15 [--now YYYY-MM-DD] [--generated YYYY-MM-DD]

parse_posts.py:

  • keeps only posts from the last 15 days (--window-days, anchored to --now/today), then keeps

the latest post per sender (id hashed away, never stored/shown), numbering contributors 1..N;

  • reads each post's parser-stable tables by header signature (tolerant of metric wording drift);
  • pulls the Role line if present (the only attribute — no names, no country, no files);
  • groups business processes (process_groups.json) and canonicalizes skills

(skills_vocabulary.json + skill_aliases.json);

  • writes working/team_data.json (meta + one snapshot + members[] with role|null + metrics).

4. Build the dashboard (guide built in)

python scripts/build_outputs.py --in working/team_data.json --config config/team_config.json

Renders the single deliverable:

  • output/cowork-team-roi-dashboard.html — self-contained HTML (no external assets). Five small

tabs: Overview (auto-insights + KPI band) · Impact & Value (pillars, categories with $ and

contributor reach per category, roles, deliverables by format) · How Cowork is used

(business-process accordion — each process expands to its deliverables, with **type-only items

collapsed per format** e.g. "HTML · 5 deliverables" — category mix, analyzed → produced) ·

Trends (minimal fortnight-over-fortnight line) · How to read (the full in-dashboard guide:

every KPI, the five tabs, the two controls, how task categories are derived, the privacy model, and

the methodology). Every section title also carries a clickable "?" popover. Value = hours ×

rate, recomputed live by a rate control.

The How to read tab replaces the old standalone one-page PDF — the guide now travels *inside* the

dashboard, so there is nothing separate to notice or toggle to. build_outputs.py just drives

build_dashboard.py (still runnable on its own). The legacy PDF (build_guide_pdf.py) is retained

but off by default; pass --with-pdf to build_outputs.py only if someone explicitly wants a

printable copy.

5. Email the channel members (summary + dashboard attachment) — a separate, expected approval

The email send is deliberately not bundled into step 4: building the file is one approval, and

sending it to people is a second, distinct approval. If email_on_run is true (default) and the

user hasn't said "don't send":

  • Recipients = the channel members. ListChannelMembers(team_id, channel_id) → resolve each to an

email/UPN; de-duplicate; include the runner. (A standard channel returns the team members — that's

the intended audience.) Never add anyone outside the channel.

  • Body = a high-level HTML summary (aggregate only, same privacy rules as the dashboard). Pull the

figures from working/team_data.json — sum the members' headline metrics (time saved, value =

hours × rate, sessions, run tasks, deliverables) and name the top 1–2 business processes. Do not

hand-invent numbers; if a figure isn't in the data, omit it.

  • Send with the dashboard attached (the guide is inside it — no separate PDF):
  SendEmailWithAttachments(
    to=<resolved channel-member emails>,
    subject="Team Cowork Team Report — latest rollup (<period>)",
    content_type="HTML", body=<summary html>,
    direct_attachment_file_paths=["output/cowork-team-roi-dashboard.html"])

In interactive runs the platform's approval dialog is the confirmation; scheduled runs send

automatically. The "Powered by Copilot Cowork" footer is appended by the host — don't add your own.

6. Verify + deliver

Glob output/cowork-team-roi-dashboard.html to confirm it exists, then tell the user it's saved and

the email went to the channel members.

Optionally show a 3-line highlight (time saved, value, top process) — aggregate only.

7. (Optional) automate — run 1–2 days after the member fortnight

If the user asks, SetupScheduledPrompt with a self-contained description: *"Read the last 15 days of

Cowork Team Report posts in the team channel, aggregate them into the anonymized team dashboard (the how-to-read

guide is built into it), save it to my files, and email it to the channel members."*

Timing: the Member skill posts on a biweekly Monday cycle, so schedule the manager rollup to

run 1–2 days later — on Wednesday — which gives teammates Monday and Tuesday to post before the

rollup reads the channel. Use frequency Week, interval = cadence_days / 7 (= 2 → every other

Wednesday), weekDays=["Wednesday"], hours=["9"], name "Cowork Team Report team dashboard". Scheduled runs

build the dashboard and email the channel members automatically (no interactive approval).

Privacy (hard rules)

  • Never show anything at an individual level. Members are counts + a number only.
  • k-anonymity: a per-attribute (Role) breakdown renders only when privacy_k_threshold

(default 3) contributors share that Role; otherwise those contributors collapse into a single

combined bar. Small homogeneous teams usually render one combined bar — that's correct.

  • Attributes: only the directory Role a post carries. Never names, country, file names,

prompts, or JTBD prose. The parser doesn't read them and the dashboard can't show them.

  • The email body is aggregate-only too — same rules; no member is ever named or singled out.
  • The whole artifact is team-safe / shareable — it exposes totals and the generic shape of work,

never who did what.

Cross-skill contract (keep in sync)

This skill can only aggregate what cowork-dashboard-member posts. These must match its copies or

aggregation breaks — change them in both bundles together:

| Item | This skill | Must match |

|---|---|---|

| Business-process grouping | scripts/process_groups.json | cowork-dashboard-member/scripts/process_groups.json (and cowork-roi-report's copy) — byte-for-byte |

| Skills vocabulary | scripts/skills_vocabulary.json | cowork-dashboard-member/scripts/skills_vocabulary.json (and cowork-roi-report's) — byte-for-byte |

| Roles taxonomy | scripts/roles_taxonomy.json | cowork-dashboard-member/scripts/roles_taxonomy.jsonbyte-for-byte |

| Value pillars | references/value-pillars.md | cowork-dashboard-member/references/value-pillars.mdbyte-for-byte |

| Role attribute + no country/names | reads the post header Role: line | cowork-dashboard-member/scripts/format_member_message.py (emits Role:; excludes country/names) |

| Deliverable → process link + by-type rollup | parser reads the "By type" deliverables table | format_member_message.py (that rollup "is also what the aggregated Dashboard reads") |

| The shared channel | channel_id resolved from the link the user pastes | the channel cowork-dashboard-member posts to (its SKILL.md → *Target channel*) — must be the same channel |

  • scripts/skill_aliases.json is a reader-only compatibility shim (maps older non-canonical skill

labels → the vocabulary). It is not part of the shared contract and lives only here.

  • Deliverable NAMES: the Member skill strips file names by design (emits

Type/Date/Process/Skills/Hours/Value — no names). To show doc names, the Member skill must first add

an opt-in name manifest; only then can this reader surface a manager-only named list. That is a

Member-skill change — flag it before promising named deliverables.

Guardrails

  • No fabricated data. Every number traces to a post via the pipeline. Empty sections are omitted;

an empty 15-day window yields no dashboard, not a made-up one.

  • No hand math. parse_posts.py totals; build_dashboard.py prices at the live rate; the email

figures are read from team_data.json.

  • Self-contained output. The HTML embeds all CSS/JS/data — no external assets.
  • Latest post wins, within the window. The reader keeps only the last 15 days, then the most

recent post per sender; re-running a member's post replaces their earlier contribution.

  • Channel is user-owned. Read the channel resolved from the user's link; re-ask only if they name

a different one. Never guess or construct a channel_id.

  • Email stays inside the channel. Recipients are the channel members only; the body is

aggregate-only. Interactive sends go through the approval dialog; honor "don't email" / email_on_run:false.

Bundled files

  • SKILL.md, README.md, CHANGELOG.md
  • config/team_config.json — rate + k-threshold + cadence + 15-day lookback + email toggle; the

channel IDs are filled in on first run (not shipped hard-coded).

  • scripts/resolve_channel.py — parse a pasted Teams channel/message link → team_id + channel_id; persist to config (stdlib only).
  • scripts/parse_posts.py — channel posts → anonymized team_data.json (stdlib only; 15-day window, latest-per-sender, groups processes, canonicalizes skills, k-anon-ready).
  • scripts/build_dashboard.pyteam_data.json → self-contained HTML dashboard with the guide built in (stdlib only): the How to read tab, per-section "?" helpers, per-category contributor reach (with a <k privacy floor), and type-only deliverables collapsed per format.
  • scripts/build_guide_pdf.pylegacy one-page landscape interpretation PDF (uses reportlab). Retained but off by default; the guide now lives inside the dashboard.
  • scripts/build_outputs.py — the build step; renders the dashboard (guide built in). Pass --with-pdf to also regenerate the legacy PDF.
  • scripts/process_groups.json, scripts/skills_vocabulary.json, scripts/roles_taxonomy.jsonmirrors of the Member bundle (shared contract).
  • scripts/skill_aliases.json — reader-only skill-label compatibility shim.
  • references/value-pillars.mdmirror of the four-pillar crosswalk.
  • examples/sample_raw_messages.json — two real, de-identified posts for an offline end-to-end test.

Other skills for the same job

different authors, same section of the catalogue
XLSX
by anthropics
vendor ×15

Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas

5k tokens scripts
XLSX
by w95
×7

Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like \"the xlsx in my downloads\") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved.

3k tokens
Raffle Winner Picker
by frostant
×5

Picks random winners from lists, spreadsheets, or Google Sheets for giveaways, raffles, and contests. Ensures fair, unbiased selection with transparency.

949 tokens
Fda Database
by christophacham
×4

Query openFDA API for drugs, devices, adverse events, recalls, regulatory submissions (510k, PMA), substance identification (UNII), for FDA regulatory data analysis and safety research.

32k tokens scripts
Matlab
by christophacham
×4

MATLAB and GNU Octave numerical computing for matrix operations, data analysis, visualization, and scientific computing. Use when writing MATLAB/Octave scripts for linear algebra, signal processing, image processing, differential equations, optimization, statistics, or creating scientific visualizations. Also use when the user needs help with MATLAB syntax, functions, or wants to convert between MATLAB and Python code. Scripts can be executed with MATLAB or the open-source GNU Octave interpreter.

25k tokens
Umap Learn
by ComeOnOliver
×4

UMAP dimensionality reduction. Fast nonlinear manifold learning for 2D/3D visualization, clustering preprocessing (HDBSCAN), supervised/parametric UMAP, for high-dimensional data.

14k tokens
D3 Viz
by chrisvoncsefalvay
×3

Creating interactive data visualisations using d3.js. This skill should be used when creating custom charts, graphs, network diagrams, geographic visualisations, or any complex SVG-based data visualisation that requires fine-grained control over visual elements, transitions, or interactions. Use this for bespoke visualisations beyond standard charting libraries, whether in React, Vue, Svelte, vanilla JavaScript, or any other environment.

20k tokens
Alphafold Database
by christophacham
×3

Access AlphaFold 200M+ AI-predicted protein structures. Retrieve structures by UniProt ID, download PDB/mmCIF files, analyze confidence metrics (pLDDT, PAE), for drug discovery and structural biology.

7k tokens

How to use it

Copy the folder

Take microsoft/cowork-dashboard-team-dashboard from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.