Skip to content

M365 + Clawpilot Playbook

Status: Set 27 May 2026 from Issy peer-AI knowledge transfer. Origin: PAC (48h burn) and atlas-portfolio v0.4.0–v0.4.3 (4-day arc) both fell into the same trap — building new apps when Clawpilot was already a configurable shell. Sush asked Issy (peer Copilot SE who shipped both surfaces successfully) for the actual architecture via his AI. The reply unblocked both lines of work and surfaced one new rule. Related: clawpilot-embed-research.md · pac-architecture.md · pac-v08-second-brain.md · architecture-and-data-first-playbook.md · msx-auth-fabric-pattern.md

🎯 27 May 2026 evening update — the pattern was already running. A live workiq-ask_work_iq call from a Copilot CLI session (this very session) returned actionable inbox triage on the first try: no install, no MSAL config, no Conditional Access wall, no EULA prompt. Sush had 5 plugins already installed as Copilot CLI plugins (workiq, workiq-productivity, microsoft-365-agents-toolkit, msx-mcp, mcp-gateway) which collectively expose: workiq-ask_work_iq tool · 11 m365-admin-graph-* tools · msx-mcp-get_account_overview · @msx custom agent · and the daily-outlook-triage / email-analytics / channel-audit / channel-digest / action-item-extractor skills. The MSAL "auth recipe" below has been demoted from Path 1 to Path 3 (custom-MCP fallback). New Path 1 is "verify the plugins are installed, then just ask."

Deeper meta-lesson: Before designing any new flow, open a Copilot CLI session and ask Atlas the question. If Atlas can answer with existing plugin tools, you're done. PAC's 48 hours and atlas-portfolio's 4 days were both spent solving a problem that didn't exist — the plugins were already there.


TL;DR — the 3 hard facts from Issy

  1. There is no "email client" app. What Sush saw was Clawpilot configured with an M365 MCP server wrapping Microsoft Graph. Configure the shell, don't build one.
  2. MSAL acquireTokenInteractive in an embedded browser, scopes against /me (user-delegated), not app/tenant level. Device code is what Microsoft Corp Conditional Access blocks. App-level scopes are what triggers the admin-consent wall. /me-level user-delegated scopes work without admin consent.
  3. For MSX, no persistent dashboard. A skill probes the .xlsx shape first (column sniff, sample rows, type infer) THEN writes a self-contained HTML renderer to fit. One HTML file per question. No SPA, no build step, no framework.

The meta-rule (Issy's exact words):

"The meta-mistake both PAC and atlas-portfolio share is rebuilding plumbing that already exists — auth flow, MCP runtime, tool routing, chat UI, session state. Don't build a new app. Start from a Claude Desktop or Clawpilot shell, add Graph + WorkIQ + MSX as MCPs, then write thin skills on top. The skills are markdown files, not code. The LLM is the renderer for everything dynamic."


Clarke's deeper component list (added 27 May 2026 evening, second Issy message)

Clarke (Issy's AI) sent a second, more detailed component list. These layers are beyond what we initially captured. Read this section before designing future Atlas surfaces.

PAC arc additional components

Layer What it does Sush equivalent (if any)
Long-term memory store Categorised key/value of preferences, facts, decisions, context. Persistent across sessions. Soul files (~/.copilot/copilot-instructions.md) + session journal. Similar idea, different storage. Clawpilot's own m-memory.json (~/.copilot/m-memory.json — 32 KB on 23 May) is the closest analogue we have.
Cron-style automations Scheduled tasks that fire even when user isn't actively chatting. Clarke's reply to Issy was generated by one. Copilot CLI's manage_schedule is session-bound. We don't have persistent cross-session automations yet.
Teams relay Persistent bot connection for proactive outbound messages. How Clarke pings Issy when something completes. Not present. Could be future work — Clawpilot ships a Teams-relay deploy on clawpilot-relay.azurewebsites.net (per clawpilot-embed-research.md) but it's mobile-Teams → desktop-Clawpilot, not the proactive direction Clarke uses.
Sensitivity awareness Per-session MIP-label tracking. Highest label encountered blocks unsafe outbound paths. 🚨 Rules #2 + #3 in the soul file are our manual version of this — auto-enforcement would be safer.

Skills folder canonical path (Clawpilot)

Path Used by Notes
~/.copilot/skills/ Copilot CLI ✅ + Clawpilot ✅ Where the existing 18 skills already live (per ls ~/.copilot/skills/). Clawpilot's asar reads from here too (line 4477: Uo = D.join(u(), "skills")).
~/.copilot/m-skills/ Clawpilot ✅ (canonical) "Migrated local skills from workspace to ~/.copilot/m-skills/" appears in asar log message (line 4512). Per 27 May placement, morning-brief SKILL.md lives in BOTH paths (SHA-256 verified identical).

Practice: when authoring a new user-level skill, place it in both folders. SHA-256 match means deduplication is safe.

MSX dashboard — full tech stack (confirmed by Clarke)

The dashboard pattern Issy uses for MSX exports:

Component Choice Notes
Input .xlsx export from MSX, dropped into OneDrive (Issy's path) Generic to any tabular source
Parser Python + pandas + openpyxl Runs FIRST, EVERY TIME. Probes columns, samples 5–10 rows, infers types. No exceptions. Rule #6 baked in.
Generator Claude LLM (inside Clawpilot) via web-artifacts-builder skill The model writes the HTML at generation time
Output artifact Single self-contained .html file Opens via file:// URL, also renders inline in Clawpilot chat
Frontend HTML5 + CSS3 + vanilla JavaScript NO React, NO Vue, NO Angular, NO SPA framework, NO bundler. Inline <script> + <style> tags.
Viz library Chart.js (bar/line/pie/scatter) or D3.js (custom viz) Loaded via CDN <script> tag in <head>
Data embedding JSON literal in <script> block at generation time NO fetch, NO API call, NO auth, NO CORS, NO key
Styling Clawpilot theme variables (CSS custom properties) Consistent palette across every artifact
Layout CSS Grid + Flexbox Responsive
Interactivity Vanilla JS event handlers Filter, sort, drill-down, tooltip, hover state
Build step NONE Opens directly in any browser via file://
Backend / server NONE Pure static client-side. Email it, drop on SharePoint, share OneDrive link.

One-line summary (Clarke's words): "It is a single-page HTML file that already has the data baked inside it. The LLM writes the HTML, the data is embedded as JSON, and Chart.js or D3 does the drawing. No framework, no backend, no build."

Issy's pattern in one sentence

Same shell (Clawpilot), different skills. PAC is just M365 MCP + a handful of mail/chat/calendar skills. atlas-portfolio is just xlsx probe + web-artifacts-builder skill. Both run inside Clawpilot. Claude is the renderer for everything dynamic. You write workflows in markdown, not code.

Pending external follow-ups from this exchange

  • Sanitized skill files — Clarke offered: "Issy, want me to drop sanitized copies of the actual skill files into a shared OneDrive folder for Sush to lift?" — Sush should say YES (queued as issy-skill-files-request todo).
  • MSX-dashboard prompt for Atlas — Issy asked Clarke to write one; not arrived yet. Once delivered, lift it via msx-dashboard-prompt todo.

Execution paths (revised 27 May 2026 evening, ranked by simplicity)

Path What it gives you When to pick Effort
Path 1 — Pre-installed Copilot CLI plugins ✅ already done on Sush's box workiq-ask_work_iq (Q&A across mail/Teams/files/people) · daily-outlook-triage skill · email-analytics · channel-audit · channel-digest · action-item-extractor · 11 m365-admin-graph-* tenant tools · msx-mcp-get_account_overview · @msx agent. Microsoft handles auth — workiq is CA-pre-approved. Default. First flow you try for any new chat-driven M365 / MSX workflow. Zero — plugins already installed. Just run copilot and ask.
Path 2 — Agent365 HTTP MCPs in Clawpilot Same surface inside the Clawpilot GUI shell. Native agent365-mail / agent365-teamsserver / agent365-calendartools / agent365-meserver / agent365-wordserver / agent365-sharepoint HTTP endpoints, Microsoft-hosted on Corp tenant 72f988bf-86f1-41af-91ab-2d7cd011db47. Clawpilot triggers OAuth automatically on first call. If you want the surface in Clawpilot specifically (GUI > terminal). Open Q (27 May): schema support for type:"http" in ~/.copilot/m-mcp-servers.json is unverified — current file only shows type:"command" entries. Probe before committing. Low — add 4 JSON entries to m-mcp-servers.json + restart Clawpilot.
Path 3 — Custom Graph MCP with MSAL (fallback recipe) A user-written stdio MCP server that uses @azure/msal-node to acquire tokens for Microsoft Graph against the user's /me. Recipe below. Only if Paths 1 + 2 are blocked (off-network, tenant doesn't allow Agent365, or you need a scope Microsoft doesn't expose via workiq / Agent365). High — app reg, MSAL config, Node MCP server code, token cache, restart cycle. The path PAC failed twice.

Execution checklist for Path 1 (the one that works today)

# 1. Verify plugins are installed (Sush's box already passes)
copilot plugin list
# Expect: workiq@work-iq · workiq-productivity@work-iq · microsoft-365-agents-toolkit@work-iq · mcp-gateway@awesome-sas-copilot · msx-mcp@msx-mcp

# 2. Open a Copilot CLI session in any directory
copilot

# 3. Ask Atlas a M365 question — that's it
> brief me on overnight emails, group by sender, action verb each
> what's on my calendar Thursday  any double-bookings?
> last 5 emails I exchanged with anyone at ProServeIT
> @msx get_account_overview for <customer name>

If you want the morning-brief flow specifically in Sush's voice (4-surface coverage + ⏱️ chips + Rule #2 drafts-only), the custom morning-brief skill lives at ~/.copilot/skills/morning-brief/SKILL.md (set 27 May 2026 evening). Differentiates from the generic daily-outlook-triage plugin skill.


Path 3 — Custom Graph MCP with MSAL (fallback recipe — only if Paths 1+2 are blocked)

✅ What works — Issy's confirmed pattern

  • MSAL acquireTokenInteractive in an embedded browser (NOT device code)
  • All scopes user-delegated against /me (NOT app/tenant level)
  • No tenant admin consent required for any of the scopes below
Scope Permission Surface unlocked
Mail.Read Read user's mail Inbox triage, search
Mail.Send Send mail as user Send replies
Mail.ReadWrite Read + write user's mail (incl. drafts) Draft to ~/Drafts (🚨 Rule #2 still applies — no actual send without bypass)
Chat.Read Read user's Teams chats 1:1 + group chat summarisation
Chat.ReadWrite Read + send Teams chats Reply drafts
People.Read Read user's people list (relevant contacts) "Who is X" lookups
Calendars.ReadWrite Read + write user's calendar Slot search, conflict detection, RSVP drafts

❌ What broke PAC

Attempt What we did Why it failed
1 — MSAL device code Followed MSAL docs top-down, picked simplest flow Device code is exactly what Microsoft Corp CA blocks (correct: that's the policy across all MSFT-tenanted devices)
2 — acquireTokenInteractive with app-level scopes Right auth path, wrong scope granularity Requested at app/tenant level → admin-consent wall for Chat.Read / People.Read
3 — WorkIQ MCP as subprocess Pivoted to internal MS pattern from Frontier SE Wrapping bug we never isolated (Issy's read: "the issue was almost certainly the wrapping, not WorkIQ itself")

Concrete fix: Configure Clawpilot's MCP roster to include an M365 MCP server with: - clientId = an Azure AD app reg you (or your tenant) owns - redirectUri = local loopback http://localhost:<port> for embedded browser flow - authority = https://login.microsoftonline.com/<your-tenant-id> (or common for multi-tenant) - scopes = the /me-level user-delegated list above - Token cache = MSAL's built-in encrypted local store

🔓 Open ask to Issy: the actual MCP config file Issy uses. He offered "happy to compare configs" — worth a 15-min sync when he's free. Until then, our config is approximate.


Direct Graph vs WorkIQ — when to use which

Issy's pattern uses BOTH, addressed at different shapes of question:

Use case Tool Why
List my unread emails Direct Graph Fast, deterministic, structured response
Get a specific email by ID Direct Graph Deterministic
Send / reply / draft email Direct Graph Audit trail, predictable
What's been said about ProServeIT this week? WorkIQ MCP Fuzzy reasoning across email + chat + files + people in one query
Find the meeting where Andrew committed to the demo date WorkIQ MCP Cross-surface semantic search
Summarise overnight activity WorkIQ MCP Multi-source reasoning

Rule of thumb: Graph for nouns (specific things), WorkIQ for verbs (cross-surface reasoning).


The skills pattern

Skills are markdown files, not code. Each skill has a description: frontmatter that lets the LLM decide when to fire it.

Why markdown over code

  • The LLM is the renderer — it writes the actual HTML / JSON / table inline based on what the data probe found
  • No build step, no compile, no deploy
  • Sush can edit a skill in 30 seconds without spinning up a dev environment
  • The skill describes intent + tool routing; the LLM handles execution

Specific skills worth writing for Sush's PAC-style flows

Skill name What it does MCPs it uses
morning-brief "Give me my top emails + chats from overnight, grouped by sender, with action verbs and ETA-to-respond" Graph (Mail.Read, Chat.Read) + WorkIQ for cross-source priority signal
draft-reply-in-my-voice Drafts a reply pulling tone from past replies to the same person Graph (Mail.Read for tone corpus, Mail.ReadWrite to save draft)
calendar-clear Find blocks of free time + flag double-bookings + suggest move targets Graph (Calendars.ReadWrite)
mention-watch Scan email/Teams for new contexts my name surfaces in WorkIQ (cross-surface)
customer-360-quick For a customer name: latest email + latest chat + last calendar invite Graph + WorkIQ

🚨 Rule #2 still applies

Any skill that drafts an email or message saves to Drafts only — never sends. Same for calendar — drafts an RSVP, doesn't commit. Bypass required per ~/.copilot/copilot-instructions.md § 🚨 #2 RULE.


The MSX data pattern (Rule #6 baked into a skill)

Issy's MSX skill enforces probe-before-render mechanically:

1. Column sniff   — read header row, list columns
2. Sample rows    — read first 10 rows, infer column types
3. Type infer     — string vs number vs date vs currency
4. THEN write     — generate HTML/JS renderer fitted to the shape it actually found

The renderer is a single self-contained HTML file per question — opens in a browser, no SPA, no framework, no build step. Viz lib is whatever the model picks inline (usually Chart.js or D3).

This is exactly Rule #6 (PROBE → SCRAPE → LOAD → RENDER) that we codified on 25 May 2026 after our 4-day atlas-portfolio v0.4.0–v0.4.3 arc. Issy bakes it into a skill so the discipline is automatic on day one. We arrived at the same destination after pain. He arrives there by design.

Data sources for MSX

  • OneDrive drop (Issy's most common path) — manually export from MSX, drop into a watched folder, skill picks it up next time it runs
  • MSX MCP against the live cube — direct query, no manual re-export loop. Clone at C:\ssClawy\msft-internal-mcps\msx-mcp\

Path C — Helm + Clawpilot (architecture committed 27 May 2026)

Helm (= atlas-portfolio Electron app) already wires Clawpilot via ACP for its chat sidebar. Path C decides:

  • Clawpilot owns the M365 surface (email / chat / calendar) via the M365 MCP described above
  • Helm stays focused on MSX portfolio, customer 360, opps, ACR — the work the Scout tab is extending
  • Helm's chat sidebar can ask Clawpilot Atlas M365-aware questions when the customer in focus needs it (e.g., "show me the last 5 emails with this customer"). The ACP wire already exists from v2.1.x
  • Do not put M365 MCP server inside Helm — that duplicates the plumbing Clawpilot already provides

What Path C is NOT

  • ❌ Adding Email / Chat / Calendar tabs directly into Helm
  • ❌ Building a new Electron shell (PAC archived — do not revive)
  • ❌ Putting MSAL auth flow inside Helm
  • ❌ Two separate auth tokens for the same M365 surface

What the user experiences

Surface What user does What happens behind the curtain
Open Clawpilot "Brief me on overnight" Clawpilot Atlas → M365 MCP → Graph → reply rendered inline
Open Helm, customer card "Latest email with this CSAM?" Helm sidebar → ACP → Clawpilot Atlas → M365 MCP → Graph → reply back into Helm sidebar
Open Helm, generic question "What's my ACR YTD?" Helm sidebar → ACP → Clawpilot Atlas → Helm's MSX data → reply (no M365 needed)

One auth flow, one M365 MCP config, two surfaces that collaborate.


The meta-rule: shell-first, not app-first

Before building any new app, shell, runtime, or container, the Rule #5 architecture-gate comparison must evaluate each existing shell as a possible host. If any existing shell can host the workflow with a config + a skill, that's the answer. Build new only when every existing-shell row is explicitly killed.

See ~/.copilot/copilot-instructions.md § Rule #5 → "Shell-first comparison row" addendum (set 27 May 2026).


Failure modes this pattern avoids

Our mistake (PAC + atlas-portfolio) Why we made it Issy's alternative
Built PAC as a new Electron app Saw "I want email/chat" → reached for "build a new app" Configure Clawpilot's M365 MCP. Hours, not days
MSAL device code first Read MSAL docs top-down, picked simplest flow Skip to interactive in embedded browser — the only flow CA allows on MSFT-tenanted boxes
Requested scopes at app/tenant level Followed app-reg defaults User-delegated at /me level — no admin consent wall
Wrote MSX renderer before probing data shape Dashboard pattern feels like "design the page first" Probe the .xlsx FIRST, then write renderer to fit
Helm as persistent MSX dashboard with all-in-one design "An app should have UI for everything users need" Each question = one self-contained HTML, model is the renderer
Duplicated MCP plumbing inside PAC + considered duplicating in Helm Each app feels self-contained Configure the shell once, every project benefits

Execution checklist (next session that picks this up — REVISED 27 May 2026 evening)

When the next session is ready to act on this playbook, do these in order:

  • [ ] Read this playbook end-to-end first (you are here)
  • [ ] Verify Path 1 plugins are installed: copilot plugin list — should show workiq, workiq-productivity, microsoft-365-agents-toolkit, msx-mcp, mcp-gateway (on Sush's box, already done)
  • [ ] Test workiq with a read-only probe: workiq-ask_work_iq with question like "what's the most important email in my inbox right now?" — validated 27 May 2026 evening, worked on first call
  • [ ] If you need the GUI shell experience (Path 2): probe whether m-mcp-servers.json supports type:"http". Quick test = add one Agent365 entry, restart Clawpilot, check if it loads.
  • [ ] Don't write a new Graph MCP unless Paths 1 + 2 are both blocked — that's Path 3 (the fallback PAC tried twice)
  • [ ] For Helm: keep Helm focused on its visual MSX dashboard role. Helm's chat sidebar can ACP-forward M365 questions to Copilot CLI Atlas. Do NOT add M365 MCP server inside Helm.
  • [ ] Log results in ~/.copilot/session-journal.md

Citations & cross-references

Deliverables shipped 27 May 2026 PM (todos helm-ctx-injection + clawpilot-plugin-install + clawpilot-m-skills-place)

  • atlas-portfolio commit 0c346e0 (Phase 100 / v2.3.1) — helm-ctx-injection — sidebar prepends customer context. When user is on an account page, <body> carries data-helm-customer-* attrs and the inline send handler wraps the user's text with a Helm context prefix before posting to /api/chat/prompt. Validated by scripts/smoke-helm-ctx-injection.mjs (16 checks, 🟢 ALL PASS).
  • ~/.copilot/scripts/clawpilot-agent365-template.json — 6 Agent365 HTTP MCP entries ready to merge into m-mcp-servers.json (mail / teamsserver / calendartools / meserver / wordserver / sharepoint).
  • ~/.copilot/scripts/apply-clawpilot-agent365-mcps.ps1 — idempotent merge script (refuses to run if Clawpilot process is alive; auto-backups; round-trip JSON validates; re-run is a no-op).
  • ~/.copilot/m-skills/morning-brief/SKILL.md — Sush-voice triage skill placed in the Clawpilot-canonical skills path (SHA-256 matches the copy in ~/.copilot/skills/morning-brief/).