diff --git a/.github/sync-state.json b/.github/sync-state.json index 33133c6..8ba369a 100644 --- a/.github/sync-state.json +++ b/.github/sync-state.json @@ -2,12 +2,12 @@ "version": 1, "sources": { "slack-plus-teams-experts": { - "lastSyncedCommit": "9ee143ba47bc28dd1eccf19cdbafffeddd51b4ab", - "lastSyncedAt": "2026-04-21T02:21:41Z" + "lastSyncedCommit": "934d0276f92efa42148bd4fb74edf0f98ac87bd0", + "lastSyncedAt": "2026-05-18T11:36:59Z" }, "slack-plus-teams-docs": { - "lastSyncedCommit": "9ee143ba47bc28dd1eccf19cdbafffeddd51b4ab", - "lastSyncedAt": "2026-04-21T02:21:44Z" + "lastSyncedCommit": "934d0276f92efa42148bd4fb74edf0f98ac87bd0", + "lastSyncedAt": "2026-05-18T11:37:03Z" } } } diff --git a/skills/microsoft-365-agents-toolkit/docs/README.md b/skills/microsoft-365-agents-toolkit/docs/README.md index 3cad2f3..2408cf1 100644 --- a/skills/microsoft-365-agents-toolkit/docs/README.md +++ b/skills/microsoft-365-agents-toolkit/docs/README.md @@ -6,6 +6,7 @@ A practical guide for developers adding cross-platform support to an existing bo | Document | What It Covers | |---|---| +| [**Migration Guide**](migration-guide.md) | **Step-by-step guide for migrating Line of Business apps from Slack to Teams** | | [**Feature Gaps**](feature-gaps.md) | **Complete inventory of every RED and YELLOW gap with mitigations in both directions** | | [**Workflows**](workflows.md) | **Message-native workflow scenarios: standup, PTO, equipment, account health, break management, incidents** | | [Messaging & Commands](messaging-and-commands.md) | Messages, slash commands, events, threading, @mentions | diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/adapter-pattern-architecture.png b/skills/microsoft-365-agents-toolkit/docs/assets/adapter-pattern-architecture.png new file mode 100644 index 0000000..9082007 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/adapter-pattern-architecture.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/add_adapter_slide.py b/skills/microsoft-365-agents-toolkit/docs/assets/add_adapter_slide.py new file mode 100644 index 0000000..ad36da5 --- /dev/null +++ b/skills/microsoft-365-agents-toolkit/docs/assets/add_adapter_slide.py @@ -0,0 +1,319 @@ +from pptx import Presentation +from pptx.util import Pt, Emu +from pptx.enum.text import PP_ALIGN, MSO_ANCHOR +from pptx.dml.color import RGBColor +from pptx.enum.shapes import MSO_SHAPE +from pptx.oxml.ns import qn + +prs = Presentation('C:/source/slack-plus-teams/docs/slack-plus-teams-architecture.pptx') + +# Theme colors from slides 1 and 2 — no platform-specific colors +INDIGO = RGBColor(0x4B, 0x4A, 0x78) +WHITE = RGBColor(0xFF, 0xFF, 0xFF) +GRAY_TEXT = RGBColor(0x6D, 0x6D, 0x6D) +LIGHT_GRAY = RGBColor(0x7A, 0x7A, 0x7A) +GREEN = RGBColor(0x2E, 0x7D, 0x32) +LIGHT_INDIGO_BG = RGBColor(0xE8, 0xE8, 0xF0) # light indigo for adapter bg +LIGHT_GREEN_BG = RGBColor(0xE8, 0xF5, 0xE9) # light green for shared layer bg +ARROW_COLOR = INDIGO + +slide_layout = prs.slide_layouts[0] +slide = prs.slides.add_slide(slide_layout) + + +def add_rect(left, top, width, height, fill_color=None): + shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height) + shape.line.fill.background() + if fill_color: + shape.fill.solid() + shape.fill.fore_color.rgb = fill_color + else: + shape.fill.background() + tf = shape.text_frame + tf.word_wrap = True + tf.auto_size = None + tf.margin_left = Emu(91440) + tf.margin_right = Emu(91440) + tf.margin_top = Emu(45720) + tf.margin_bottom = Emu(45720) + return shape, tf + + +def add_rounded(left, top, width, height, fill_color=None, radius=5000, + border_color=None, border_width=None): + shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height) + if border_color: + shape.line.color.rgb = border_color + shape.line.width = border_width or Pt(1.5) + else: + shape.line.fill.background() + spPr = shape._element.spPr + prstGeom = spPr.find(qn('a:prstGeom')) + if prstGeom is not None: + avLst = prstGeom.find(qn('a:avLst')) + if avLst is None: + from lxml import etree + avLst = etree.SubElement(prstGeom, qn('a:avLst')) + else: + for child in list(avLst): + avLst.remove(child) + from lxml import etree + gd = etree.SubElement(avLst, qn('a:gd')) + gd.set('name', 'adj') + gd.set('fmla', f'val {radius}') + if fill_color: + shape.fill.solid() + shape.fill.fore_color.rgb = fill_color + else: + shape.fill.background() + tf = shape.text_frame + tf.word_wrap = True + tf.auto_size = None + tf.margin_left = Emu(91440) + tf.margin_right = Emu(91440) + tf.margin_top = Emu(45720) + tf.margin_bottom = Emu(45720) + return shape, tf + + +def set_text(tf, text, size, color, bold=False, align=PP_ALIGN.LEFT): + p = tf.paragraphs[0] + p.text = text + p.alignment = align + p.runs[0].font.size = size + p.runs[0].font.color.rgb = color + p.runs[0].font.bold = bold + + +def add_box(left, top, width, height, title, subtitle_lines, + fill_color, text_color, border_color=None): + """Add a labeled box with title and subtitle lines.""" + shape, tf = add_rounded(left, top, width, height, fill_color=fill_color, + radius=4000, border_color=border_color, + border_width=Pt(1.5)) + tf.margin_top = Emu(36000) + tf.margin_bottom = Emu(36000) + p = tf.paragraphs[0] + p.alignment = PP_ALIGN.CENTER + run = p.add_run() + run.text = title + run.font.size = Pt(13) + run.font.bold = True + run.font.color.rgb = text_color + for line in subtitle_lines: + p2 = tf.add_paragraph() + p2.alignment = PP_ALIGN.CENTER + r2 = p2.add_run() + r2.text = line + r2.font.size = Pt(9.5) + r2.font.color.rgb = text_color + r2.font.bold = False + return shape + + +def add_arrow(x1, y1, x2, y2, color=ARROW_COLOR, width=Pt(2), head=True, tail=False): + """Add an arrow. head=arrowhead at end, tail=arrowhead at start.""" + connector = slide.shapes.add_connector( + 1, Emu(x1), Emu(y1), Emu(x2), Emu(y2) + ) + connector.line.color.rgb = color + connector.line.width = width + connector.line.fill.solid() + connector.line.color.rgb = color + ln = connector._element.find(qn('a:ln')) + if ln is None: + spPr = connector._element.spPr + ln = spPr.find(qn('a:ln')) + if ln is not None: + from lxml import etree + if head: + t = etree.SubElement(ln, qn('a:tailEnd')) + t.set('type', 'triangle') + t.set('w', 'med') + t.set('len', 'med') + if tail: + h = etree.SubElement(ln, qn('a:headEnd')) + h.set('type', 'triangle') + h.set('w', 'med') + h.set('len', 'med') + return connector + + +# --- Title banner (squared corners, matching slide 2) --- +shape, tf = add_rect(Emu(109728), Emu(411480), Emu(4500000), Emu(713232), fill_color=INDIGO) +p = tf.paragraphs[0] +run = p.add_run() +run.text = "Adapter Pattern Architecture" +run.font.size = Pt(22) +run.font.bold = True +run.font.color.rgb = WHITE + +# Subtitle +shape, tf = add_rect(Emu(4800000), Emu(493776), Emu(7200000), Emu(219456)) +set_text(tf, "Inbound calls from each platform converge on a shared service layer", + Pt(13.5), GRAY_TEXT) + + +# === Layout === +# +# [Slack] --> [Slack Adapter] --> [ Shared Service ] <-- [Teams Adapter] <-- [Teams] +# [ Layer ] +# +# Both platforms send calls INWARD to the central shared layer. +# The shared layer is the hub; adapters translate platform-specific protocols. + +slide_w = 12192000 +center_x = slide_w // 2 +center_y = 3700000 # slightly below center to account for title + +# Shared Service Layer — center, prominent +shared_w = 2600000 +shared_h = 2000000 +shared_left = center_x - shared_w // 2 +shared_top = center_y - shared_h // 2 + +# Adapter boxes +adapter_w = 1800000 +adapter_h = 1400000 +adapter_gap = 400000 # gap between adapter and shared layer + +slack_adapter_left = shared_left - adapter_gap - adapter_w +slack_adapter_top = center_y - adapter_h // 2 + +teams_adapter_left = shared_left + shared_w + adapter_gap +teams_adapter_top = center_y - adapter_h // 2 + +# Platform boxes (outer) +platform_w = 1500000 +platform_h = 1000000 +platform_gap = 350000 + +slack_left = slack_adapter_left - platform_gap - platform_w +slack_top = center_y - platform_h // 2 + +teams_left = teams_adapter_left + adapter_w + platform_gap +teams_top = center_y - platform_h // 2 + + +# --- Draw boxes --- + +# Shared Service Layer (center, green theme) +add_box(shared_left, shared_top, shared_w, shared_h, + "Shared Service Layer", + ["Business logic", "AI / LLM calls", "Data access", "Common types"], + fill_color=LIGHT_GREEN_BG, text_color=GREEN, + border_color=GREEN) + +# Slack Adapter (left of center) +add_box(slack_adapter_left, slack_adapter_top, adapter_w, adapter_h, + "Slack Adapter", + ["@slack/bolt", "Event handlers", "Block Kit"], + fill_color=LIGHT_INDIGO_BG, text_color=INDIGO, + border_color=INDIGO) + +# Teams Adapter (right of center) +add_box(teams_adapter_left, teams_adapter_top, adapter_w, adapter_h, + "Teams Adapter", + ["Agents SDK", "Activity handlers", "Adaptive Cards"], + fill_color=LIGHT_INDIGO_BG, text_color=INDIGO, + border_color=INDIGO) + +# Slack Platform (far left) +add_box(slack_left, slack_top, platform_w, platform_h, + "Slack", + ["WebSocket", "Socket Mode"], + fill_color=INDIGO, text_color=WHITE) + +# Teams Platform (far right) +add_box(teams_left, teams_top, platform_w, platform_h, + "Microsoft Teams", + ["HTTPS", "Bot Framework"], + fill_color=INDIGO, text_color=WHITE) + + +# --- Arrows: both sides point INWARD to the shared layer --- +arrow_y_top = center_y - 150000 # upper arrow (inbound) +arrow_y_bot = center_y + 150000 # lower arrow (outbound/response) + +# LEFT SIDE: Slack → Slack Adapter → Shared Layer + +# Slack → Slack Adapter (inbound) +add_arrow(slack_left + platform_w, arrow_y_top, + slack_adapter_left, arrow_y_top) + +# Slack Adapter → Shared Layer (inbound) +add_arrow(slack_adapter_left + adapter_w, arrow_y_top, + shared_left, arrow_y_top) + +# Shared Layer → Slack Adapter (response) +add_arrow(shared_left, arrow_y_bot, + slack_adapter_left + adapter_w, arrow_y_bot) + +# Slack Adapter → Slack (response) +add_arrow(slack_adapter_left, arrow_y_bot, + slack_left + platform_w, arrow_y_bot) + + +# RIGHT SIDE: Teams → Teams Adapter → Shared Layer + +# Teams → Teams Adapter (inbound) +add_arrow(teams_left, arrow_y_top, + teams_adapter_left + adapter_w, arrow_y_top) + +# Teams Adapter → Shared Layer (inbound) +add_arrow(teams_adapter_left, arrow_y_top, + shared_left + shared_w, arrow_y_top) + +# Shared Layer → Teams Adapter (response) +add_arrow(shared_left + shared_w, arrow_y_bot, + teams_adapter_left, arrow_y_bot) + +# Teams Adapter → Teams (response) +add_arrow(teams_adapter_left + adapter_w, arrow_y_bot, + teams_left, arrow_y_bot) + + +# --- Arrow labels --- +def add_label(cx, cy, text): + w = 1400000 + h = 220000 + shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, + Emu(cx - w // 2), Emu(cy), + Emu(w), Emu(h)) + shape.fill.background() + shape.line.fill.background() + tf = shape.text_frame + tf.word_wrap = True + p = tf.paragraphs[0] + p.alignment = PP_ALIGN.CENTER + p.text = text + p.runs[0].font.size = Pt(8.5) + p.runs[0].font.color.rgb = LIGHT_GRAY + p.runs[0].font.italic = True + + +# Labels above the inbound arrows +label_y = center_y - shared_h // 2 - 280000 + +# Left side labels +slack_mid = (slack_left + platform_w + slack_adapter_left) // 2 +add_label(slack_mid, label_y, "Events / Messages") + +slack_adapter_mid = (slack_adapter_left + adapter_w + shared_left) // 2 +add_label(slack_adapter_mid, label_y, "Normalized Calls") + +# Right side labels +teams_mid = (teams_left + teams_adapter_left + adapter_w) // 2 +add_label(teams_mid, label_y, "Activities / Messages") + +teams_adapter_mid = (teams_adapter_left + shared_left + shared_w) // 2 +add_label(teams_adapter_mid, label_y, "Normalized Calls") + + +# --- Footer --- +shape, tf = add_rect(Emu(219456), Emu(6455664), Emu(6035040), Emu(128016)) +set_text(tf, "Slack to Teams migration guide \u2022 architecture diagram 4 of 7", + Pt(9.5), LIGHT_GRAY) + +prs.save('C:/source/slack-plus-teams/docs/slack-plus-teams-architecture-v3.pptx') +print("Slide 4 (Adapter Pattern Architecture) added successfully!") diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/add_slide.py b/skills/microsoft-365-agents-toolkit/docs/assets/add_slide.py new file mode 100644 index 0000000..c5fe903 --- /dev/null +++ b/skills/microsoft-365-agents-toolkit/docs/assets/add_slide.py @@ -0,0 +1,231 @@ +from pptx import Presentation +from pptx.util import Pt, Emu +from pptx.enum.text import PP_ALIGN, MSO_ANCHOR +from pptx.dml.color import RGBColor +from pptx.enum.shapes import MSO_SHAPE +from pptx.oxml.ns import qn + +prs = Presentation('C:/source/slack-plus-teams/docs/slack-plus-teams-architecture.pptx') + +# Style constants from existing slides +INDIGO = RGBColor(0x4B, 0x4A, 0x78) +WHITE = RGBColor(0xFF, 0xFF, 0xFF) +GRAY_TEXT = RGBColor(0x6D, 0x6D, 0x6D) +LIGHT_GRAY = RGBColor(0x7A, 0x7A, 0x7A) +GREEN = RGBColor(0x2E, 0x7D, 0x32) +AMBER = RGBColor(0xEF, 0x6C, 0x00) +RED_ISH = RGBColor(0xC6, 0x28, 0x28) +LIGHT_BG = RGBColor(0xF5, 0xF5, 0xF5) + +slide_layout = prs.slide_layouts[0] # only layout available +slide = prs.slides.add_slide(slide_layout) + + +def add_rect(left, top, width, height, fill_color=None): + """Add a plain rectangle (squared corners) matching slide 2 header style.""" + shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height) + shape.line.fill.background() + if fill_color: + shape.fill.solid() + shape.fill.fore_color.rgb = fill_color + else: + shape.fill.background() + tf = shape.text_frame + tf.word_wrap = True + tf.auto_size = None + tf.margin_left = Emu(91440) + tf.margin_right = Emu(91440) + tf.margin_top = Emu(45720) + tf.margin_bottom = Emu(45720) + return shape, tf + + +def add_rounded(left, top, width, height, fill_color=None, radius=8000): + """Add a rounded rectangle with a controlled corner radius.""" + shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height) + shape.line.fill.background() + # Set corner radius via adjustment + spPr = shape._element.spPr + prstGeom = spPr.find(qn('a:prstGeom')) + if prstGeom is not None: + avLst = prstGeom.find(qn('a:avLst')) + if avLst is None: + from lxml import etree + avLst = etree.SubElement(prstGeom, qn('a:avLst')) + else: + for child in list(avLst): + avLst.remove(child) + from lxml import etree + gd = etree.SubElement(avLst, qn('a:gd')) + gd.set('name', 'adj') + gd.set('fmla', f'val {radius}') + if fill_color: + shape.fill.solid() + shape.fill.fore_color.rgb = fill_color + else: + shape.fill.background() + tf = shape.text_frame + tf.word_wrap = True + tf.auto_size = None + tf.margin_left = Emu(91440) + tf.margin_right = Emu(91440) + tf.margin_top = Emu(45720) + tf.margin_bottom = Emu(45720) + return shape, tf + + +def set_text(tf, text, size, color, bold=False, align=PP_ALIGN.LEFT): + p = tf.paragraphs[0] + p.text = text + p.alignment = align + p.runs[0].font.size = size + p.runs[0].font.color.rgb = color + p.runs[0].font.bold = bold + + +# --- Title banner (squared corners to match slide 2) --- +shape, tf = add_rect(Emu(109728), Emu(411480), Emu(4500000), Emu(713232), fill_color=INDIGO) +p = tf.paragraphs[0] +run = p.add_run() +run.text = "Prioritization Matrix" +run.font.size = Pt(22) +run.font.bold = True +run.font.color.rgb = WHITE + +# Subtitle +shape, tf = add_rect(Emu(4800000), Emu(493776), Emu(7000000), Emu(219456)) +set_text(tf, "Plot LOB apps by business impact and migration complexity to sequence your rollout.", Pt(13.5), GRAY_TEXT) + +# --- Grid layout (smaller, with gaps between quadrants) --- +grid_left = Emu(2200000) +grid_top = Emu(1500000) +grid_w = Emu(7600000) +grid_h = Emu(4200000) +gap = Emu(80000) # whitespace between quadrants +quad_w = (grid_w - gap) // 2 +quad_h = (grid_h - gap) // 2 + +# Quadrant backgrounds (with subtle corner radius and gap spacing) +add_rounded(grid_left, grid_top, quad_w, quad_h, + fill_color=RGBColor(0xE8, 0xF5, 0xE9), radius=5000) # TL green +add_rounded(grid_left + quad_w + gap, grid_top, quad_w, quad_h, + fill_color=RGBColor(0xFF, 0xF3, 0xE0), radius=5000) # TR amber +add_rounded(grid_left, grid_top + quad_h + gap, quad_w, quad_h, + fill_color=LIGHT_BG, radius=5000) # BL gray +add_rounded(grid_left + quad_w + gap, grid_top + quad_h + gap, quad_w, quad_h, + fill_color=RGBColor(0xFF, 0xEB, 0xEE), radius=5000) # BR red + + +# Quadrant labels +def add_quadrant_label(left, top, text, color): + shape = slide.shapes.add_shape( + MSO_SHAPE.RECTANGLE, + left + Emu(80000), top + Emu(60000), + Emu(1800000), Emu(280000) + ) + shape.fill.background() + shape.line.fill.background() + tf = shape.text_frame + tf.word_wrap = True + p = tf.paragraphs[0] + p.text = text + p.alignment = PP_ALIGN.LEFT + p.runs[0].font.size = Pt(11) + p.runs[0].font.bold = True + p.runs[0].font.color.rgb = color + + +add_quadrant_label(grid_left, grid_top, "Migrate First", GREEN) +add_quadrant_label(grid_left + quad_w + gap, grid_top, "Plan Carefully", AMBER) +add_quadrant_label(grid_left, grid_top + quad_h + gap, "Quick Wins", RGBColor(0x75, 0x75, 0x75)) +add_quadrant_label(grid_left + quad_w + gap, grid_top + quad_h + gap, "Deprioritize", RED_ISH) + + +# --- App bubbles (smaller, reduced corner radius) --- +def add_app_bubble(cx, cy, name, subtitle, fill_color, text_color=WHITE): + bw = Emu(1700000) + bh = Emu(560000) + shape, tf = add_rounded(cx - bw // 2, cy - bh // 2, bw, bh, + fill_color=fill_color, radius=5000) + tf.margin_left = Emu(64000) + tf.margin_right = Emu(64000) + tf.margin_top = Emu(32000) + tf.margin_bottom = Emu(32000) + p = tf.paragraphs[0] + p.text = name + p.alignment = PP_ALIGN.CENTER + p.runs[0].font.size = Pt(11) + p.runs[0].font.bold = True + p.runs[0].font.color.rgb = text_color + p2 = tf.add_paragraph() + p2.text = subtitle + p2.alignment = PP_ALIGN.CENTER + p2.runs[0].font.size = Pt(9) + p2.runs[0].font.color.rgb = text_color + p2.runs[0].font.bold = False + + +# Quadrant centers (based on new smaller grid) +tl_cx = grid_left + quad_w // 2 +tl_cy = grid_top + quad_h // 2 +tr_cx = grid_left + quad_w + gap + quad_w // 2 +tr_cy = grid_top + quad_h // 2 +bl_cx = grid_left + quad_w // 2 +bl_cy = grid_top + quad_h + gap + quad_h // 2 +br_cx = grid_left + quad_w + gap + quad_w // 2 +br_cy = grid_top + quad_h + gap + quad_h // 2 + +# Top-left: High Impact, Low Complexity +add_app_bubble(tl_cx, tl_cy - Emu(280000), "IT Helpdesk Bot", "Q&A, ticket creation", GREEN) +add_app_bubble(tl_cx, tl_cy + Emu(280000), "Sales Dashboard Bot", "CRM lookups, daily reports", GREEN) + +# Top-right: High Impact, High Complexity +add_app_bubble(tr_cx, tr_cy, "HR Onboarding Suite", "Workflows, forms, approvals", AMBER) + +# Bottom-left: Low Impact, Low Complexity +add_app_bubble(bl_cx, bl_cy, "Standup Reminder", "Scheduled messages only", RGBColor(0x75, 0x75, 0x75)) + +# Bottom-right: Low Impact, High Complexity +add_app_bubble(br_cx, br_cy, "Legacy Build Monitor", "Custom integrations, webhooks", RED_ISH) + + +# --- Axis labels --- +def add_label(left, top, width, height, text, size, color, align=PP_ALIGN.CENTER): + shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height) + shape.fill.background() + shape.line.fill.background() + tf = shape.text_frame + p = tf.paragraphs[0] + p.text = text + p.alignment = align + p.runs[0].font.size = size + p.runs[0].font.bold = True + p.runs[0].font.color.rgb = color + + +# Y-axis labels +add_label(Emu(400000), grid_top + Emu(500000), Emu(1400000), Emu(350000), + "High Impact", Pt(10), INDIGO) +add_label(Emu(400000), grid_top + quad_h + gap + Emu(500000), Emu(1400000), Emu(350000), + "Low Impact", Pt(10), INDIGO) + +# X-axis labels +total_w = quad_w * 2 + gap +add_label(grid_left + Emu(400000), grid_top + grid_h + Emu(80000), + Emu(2000000), Emu(300000), "Low Complexity", Pt(10), INDIGO) +add_label(grid_left + quad_w + gap + Emu(400000), grid_top + grid_h + Emu(80000), + Emu(2000000), Emu(300000), "High Complexity", Pt(10), INDIGO) + +# Axis titles +add_label(Emu(400000), grid_top + quad_h // 2, Emu(1200000), Emu(350000), + "Business Impact \u2191", Pt(9), INDIGO) +add_label(grid_left + quad_w - Emu(200000), grid_top + grid_h + Emu(340000), + Emu(1800000), Emu(250000), "Migration Complexity \u2192", Pt(9), INDIGO) + +# --- Footer --- +shape, tf = add_rect(Emu(219456), Emu(6455664), Emu(6035040), Emu(128016)) +set_text(tf, "Slack to Teams migration guide \u2022 architecture diagram 3 of 7", + Pt(9.5), LIGHT_GRAY) + +prs.save('C:/source/slack-plus-teams/docs/slack-plus-teams-architecture-v2.pptx') +print("Slide 3 (Prioritization Matrix) added successfully!") diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/app-migration-priorities.png b/skills/microsoft-365-agents-toolkit/docs/assets/app-migration-priorities.png new file mode 100644 index 0000000..7313fcb Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/app-migration-priorities.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/atk-created-bot.png b/skills/microsoft-365-agents-toolkit/docs/assets/atk-created-bot.png new file mode 100644 index 0000000..85885d8 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/atk-created-bot.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/azure-app-service-overview.png b/skills/microsoft-365-agents-toolkit/docs/assets/azure-app-service-overview.png new file mode 100644 index 0000000..3f8e6b9 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/azure-app-service-overview.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/configure-azure-bot.png b/skills/microsoft-365-agents-toolkit/docs/assets/configure-azure-bot.png new file mode 100644 index 0000000..20e7c61 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/configure-azure-bot.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/create-azure-bot.png b/skills/microsoft-365-agents-toolkit/docs/assets/create-azure-bot.png new file mode 100644 index 0000000..ff8b0a6 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/create-azure-bot.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/enable-teams-channel.png b/skills/microsoft-365-agents-toolkit/docs/assets/enable-teams-channel.png new file mode 100644 index 0000000..4f62c4a Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/enable-teams-channel.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/migration-complete.png b/skills/microsoft-365-agents-toolkit/docs/assets/migration-complete.png new file mode 100644 index 0000000..800273c Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/migration-complete.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/migration-strategies.png b/skills/microsoft-365-agents-toolkit/docs/assets/migration-strategies.png new file mode 100644 index 0000000..4858780 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/migration-strategies.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/onboard-missing-experts.png b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-missing-experts.png new file mode 100644 index 0000000..db85ee9 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-missing-experts.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/onboard-path-prompt.png b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-path-prompt.png new file mode 100644 index 0000000..ad83003 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-path-prompt.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/onboard-plan-output.png b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-plan-output.png new file mode 100644 index 0000000..6569bde Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-plan-output.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/onboard-strategy-prompt.png b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-strategy-prompt.png new file mode 100644 index 0000000..21e2b98 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/onboard-strategy-prompt.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/slack-installed-apps.png b/skills/microsoft-365-agents-toolkit/docs/assets/slack-installed-apps.png new file mode 100644 index 0000000..f93267b Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/slack-installed-apps.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/teams-admin-center-manage-apps.png b/skills/microsoft-365-agents-toolkit/docs/assets/teams-admin-center-manage-apps.png new file mode 100644 index 0000000..1cc7776 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/teams-admin-center-manage-apps.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/assets/teams-sideload-bot-chat.png b/skills/microsoft-365-agents-toolkit/docs/assets/teams-sideload-bot-chat.png new file mode 100644 index 0000000..f4b441a Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/assets/teams-sideload-bot-chat.png differ diff --git a/skills/microsoft-365-agents-toolkit/docs/migration-guide.md b/skills/microsoft-365-agents-toolkit/docs/migration-guide.md new file mode 100644 index 0000000..ce9691e --- /dev/null +++ b/skills/microsoft-365-agents-toolkit/docs/migration-guide.md @@ -0,0 +1,633 @@ +# Slack to Teams: Line of Business App Migration Guide + +A step-by-step guide for migrating your organization's custom Slack bots and Line of Business (LOB) applications to Microsoft Teams — or extending them to run on both platforms simultaneously. + +> **Data migration vs. app migration:** This guide focuses on migrating your **custom-built apps and bots**. For migrating your organization's **data** (channels, messages, files, users), see Microsoft's official guide: [Migrate from Slack to Microsoft Teams](https://learn.microsoft.com/en-us/microsoftteams/migrate-slack-to-teams). + +--- + +## Table of Contents + +1. [Migration Overview](#migration-overview) +2. [Phase 1: Plan Your Migration](#phase-1-plan-your-migration) +3. [Phase 2: Set Up Your Environment](#phase-2-set-up-your-environment) +4. [Phase 3: Bootstrap the Expert System](#phase-3-bootstrap-the-expert-system) +5. [Phase 4: Execute the Migration Plan](#phase-4-execute-the-migration-plan) +6. [Phase 5: Review the Migrated Code](#phase-5-review-the-migrated-code) +7. [Phase 6: Test and Deploy](#phase-6-test-and-deploy) +8. [Phase 7: Data Migration (Channels, Messages, Files)](#phase-7-data-migration-channels-messages-files) +9. [Post-Migration: Maintaining and Extending Your App](#post-migration-maintaining-and-extending-your-app) + +--- + +## Migration Overview + +Most organizations have invested significantly in custom Slack bots that automate workflows, surface data from internal systems, and integrate with Line of Business tools. Migrating these apps to Teams doesn't mean starting over — the `slack-plus-teams` expert system guides AI coding agents through every bridging decision, turning weeks of trial-and-error into a structured, repeatable process. + +### What This Guide Covers + +| Concern | Approach | +|---------|----------| +| **Custom bots & integrations** | Extend your Slack bot to also run on Teams (dual-platform) | +| **Slash commands** | Bridge to Teams text commands or message extensions | +| **Block Kit UI** | Convert to Adaptive Cards | +| **Modals & interactive flows** | Bridge to Task Modules / Dialogs | +| **OAuth & identity** | Map Slack OAuth to Azure AD / Microsoft SSO | +| **Infrastructure** | Bridge AWS services to Azure equivalents (or run both) | +| **Webhooks & connectors** | Migrate incoming webhooks to Teams connectors or bot endpoints | +| **Channel data & history** | Reference to Microsoft's official data migration tools | + +### Migration Strategies + +You have three options depending on your timeline and requirements: + +1. **Dual-platform (recommended)** — Keep your Slack bot running while adding Teams support. Both platforms share a common service layer. Migrate users gradually. +2. **Full migration** — Rewrite the Slack bot as a Teams-only app. Simpler end state but higher risk and no fallback. +3. **Parallel operation** — Run independent Slack and Teams bots with shared backend services. Lower coupling but duplicated logic. + +> **This guide follows the dual-platform approach**, which is recommended for LOB apps because it minimizes disruption and allows phased rollout. + +![Diagram showing the three migration strategies](./assets/migration-strategies.png) + +--- + +## Phase 1: Plan Your Migration + +Before writing any code, assess what you have and what needs to move. + +### 1.1 Inventory Your Slack Apps + +List every custom bot, integration, and workflow in your Slack workspace: + +1. Go to `.slack.com/apps/manage` to see all installed apps +2. Identify which are **custom-built** (your LOB apps) vs. **third-party** (marketplace apps) +3. For each custom app, document: + - What it does (commands, event handlers, scheduled jobs) + - Which channels it operates in + - What external systems it connects to + - How many users depend on it + +![Slack workspace App Management page](./assets/slack-installed-apps.png) + +### 1.2 Categorize by Complexity + +Use the difficulty ratings from [feature-gaps.md](feature-gaps.md) to categorize each feature your app uses: + +| Rating | Meaning | Examples | +|--------|---------|----------| +| **GREEN** | Direct mapping exists — straightforward conversion | Messages, basic commands, simple cards | +| **YELLOW** | Requires design decisions — mapping exists but behavior differs | Ephemeral messages, file uploads, thread broadcasting | +| **RED** | Gap — no direct equivalent, requires redesign | Mid-form modal updates, emoji reactions as input, workflow steps | + +### 1.3 Prioritize Migration Order + +For organizations with multiple LOB apps, prioritize based on: + +- **Business impact** — Which apps are most critical to daily operations? +- **Complexity** — Start with GREEN-heavy apps to build team confidence +- **User overlap** — Which app's users are migrating to Teams first? +- **Dependencies** — Which apps depend on other apps that need to migrate first? + +![Example prioritization matrix. Apps in the high-impact, low-complexity quadrant are marked "Migrate First."](./assets/app-migration-priorities.png) + +### 1.4 Coordinate with Data Migration + +Microsoft provides a complete guide for migrating your organization's Slack data to Teams: + +> **[Migrate from Slack to Microsoft Teams](https://learn.microsoft.com/en-us/microsoftteams/migrate-slack-to-teams)** +> +> This covers: +> - Exporting channels, messages, and files from Slack +> - Mapping Slack users to Microsoft 365 accounts (with PowerShell scripts) +> - Planning team and channel structure in Teams +> - Copying channel history and files +> - User readiness and adoption planning + +**Coordinate your app migration timeline with data migration.** Your LOB apps should be ready on Teams before (or at the same time as) users are migrated, so they don't lose access to critical workflows. + +--- + +## Phase 2: Set Up Your Environment + +### 2.1 Prerequisites + +| Requirement | Details | +|-------------|---------| +| **Node.js** | v18+ (LTS recommended) | +| **TypeScript** | v5+ | +| **Slack app** | Your existing Slack bot with API credentials | +| **Azure account** | For Teams bot registration and deployment | +| **Microsoft 365 developer tenant** | For testing ([free dev program](https://developer.microsoft.com/microsoft-365/dev-program)) | +| **Microsoft 365 Agents Toolkit** | [VS Code extension or CLI](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/overview-agents-toolkit) for Teams app scaffolding | +| **AI coding agent** | Claude Code, GitHub Copilot, or Cursor | + +### 2.2 Register a Teams Bot + +#### Option A: Agents Toolkit (recommended) + +The fastest path is to let Agents Toolkit (ATK) handle bot registration automatically: + +```bash +# Install the CLI if you haven't (or use the VS Code extension) +npm install -g @microsoft/m365agentstoolkit-cli + +# From your project directory (after scaffolding in 2.4): +atk provision --env local +``` + +This single command creates the **Entra ID app registration**, **Bot Framework registration**, and **Teams app** — including enabling the Teams channel. Then generate local credentials: + +```bash +atk deploy --env local +# Produces .localConfigs with CLIENT_ID, CLIENT_SECRET, TENANT_ID, PORT +``` + +> **Tip:** If `.localConfigs` is missing `TENANT_ID`, copy it from `env/.env.local`. + +Skip to [2.4 Scaffold a Teams App with Manifest](#24-scaffold-a-teams-app-with-manifest) if using ATK — section 2.3 is handled automatically. + +#### Option B: Manual Azure Portal registration + +Use this path to understand what ATK automates, or when ATK is not available: + +1. Go to the [Azure Portal](https://portal.azure.com) → **Create a resource** → **Azure Bot** +2. Configure the bot with a unique handle and your Azure subscription +3. Under **Configuration**, note your **Microsoft App ID** and generate a **Client Secret** +4. Set the messaging endpoint to your app's URL (e.g., `https://your-app.azurewebsites.net/api/messages`) or a [Dev Tunnel](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started) for local testing (e.g., `https://your-tunnel.devtunnels.ms/api/messages`) + +![Azure Portal "Create Azure Bot" page](./assets/create-azure-bot.png) + +![Azure Bot Configuration page](./assets/configure-azure-bot.png) + +### 2.3 Enable Teams Channel (manual path only) + +> **If you used ATK in 2.2, skip this step** — `atk provision` enables the Teams channel automatically. + +1. In the Azure Bot resource, go to **Channels** +2. Click **Microsoft Teams** to enable the Teams channel +3. Accept the Terms of Service + +![Azure Bot Channels page](./assets/enable-teams-channel.png) + +### 2.4 Scaffold a Teams App with Manifest + +Use Microsoft 365 Agents Toolkit to create a scaffolded Agent: + +```bash +# Using Agents Toolkit CLI (install: npm install -g @microsoft/m365agentstoolkit-cli) +atk new -c basic-custom-engine-agent -l typescript -n slack-plus-teams-bot -i false +``` + +Your manifest defines your app's identity, permissions, and capabilities in Teams. + +![VS Code showing a newly scaffolded bot project with the manifest file open](./assets/atk-created-bot.png) + +--- + +## Phase 3: Bootstrap the Expert System + +The `slack-plus-teams` expert system is a collection of micro-expert files that guide AI agents through every aspect of cross-platform bot development. Here's how to set it up. + +### 3.1 Clone the Repository + +Clone the `slack-plus-teams` repository from GitHub: + +```bash +git clone https://github.com/microsoft/slack-plus-teams.git +``` + +### 3.2 Start the Onboarding Flow + +Open your AI coding agent (Claude Code, GitHub Copilot, Cursor, etc.) from your Slack bot's project directory and reference the onboarding playbook: + +``` +Read ../slack-plus-teams/ONBOARD.md and follow the instructions. I have an existing Slack bot that I want to add Teams support to. +``` + +The agent will walk you through the following steps interactively: + +1. **Ask for your project path** — The agent asks where your existing Slack bot lives. Provide the path (e.g., `..\bolt-js-assistant-template` or an absolute path). +2. **Bootstrap the expert system** — The agent copies the `experts/` directory from the cloned repo into your project automatically. +3. **Analyze your codebase** — The agent scans your project in parallel to detect your language, platform, features, and architecture. +4. **Present analysis results** — You'll see a summary table showing what the agent found (language, platform, framework, hosting, features, etc.). +5. **Ask for your migration strategy** — The agent presents the three migration strategies (Dual-platform, Full migration, Parallel operation) and waits for your choice. +6. **Identify missing experts** — The agent compares your tech stack against the expert system to find any gaps (see [Identifying and Building Missing Experts](#identifying-and-building-missing-experts) below). +7. **Build missing experts** — Based on the gap analysis, the agent can create new experts for technologies not yet covered. +8. **Run the cross-platform advisor** — The agent loads the bridging advisor, builds a feature inventory of your codebase, and walks you through design decisions for any YELLOW-rated features (e.g., ephemeral messages, transport mode). You can accept the recommended defaults or choose alternatives. +9. **Generate a migration plan** — The agent produces a `PLAN.md` file with your complete migration roadmap, including phased implementation steps and expert references for each task. + +![AI coding agent onboarding flow — project path prompt](./assets/onboard-path-prompt.png) +![AI coding agent onboarding flow — migration strategy prompt](./assets/onboard-strategy-prompt.png) + +#### Identifying and Building Missing Experts + +After you choose your migration strategy, the agent compares your project's tech stack against the expert system to identify any technologies that aren't yet covered. If it finds gaps, it offers to build new expert files for you: + +1. **All high priority** — Automatically create experts for the most important gaps. +2. **Let me pick** — Review the list and choose which experts to create. +3. **Skip** — Proceed with the existing experts as-is. + +Built experts are saved to the appropriate domain folder (e.g., `experts/models/` or `experts/slack/`) in the same format as the existing experts. You can always build additional experts later by asking your AI agent to create one for a specific technology. + +![AI coding agent onboarding flow — gap analysis results and expert building prompt](./assets/onboard-missing-experts.png) + +### 3.3 Cross-Platform Architecture + +After the advisor walkthrough, the agent loads the cross-platform architecture expert (`experts/bridge/cross-platform-architecture-ts.md`) to design your dual-platform bot structure. Based on your codebase analysis and migration strategy, it determines: + +- **Entry point pattern** — How Slack (Socket Mode) and Teams (HTTPS) adapters coexist in the same process +- **Shared service layer** — Which business logic to extract so both platforms share it +- **Adapter boundaries** — What stays platform-specific vs. what becomes shared +- **Transport setup** — How to run both WebSocket (Slack) and HTTP (Teams) receivers + +The agent uses this architecture to inform the migration plan it generates next. + +### 3.4 Review the Generated Plan + +The agent produces a `PLAN.md` file that lists: +- Every feature to bridge, with difficulty ratings +- The recommended migration order +- Which expert files to consult for each feature +- Architecture decisions (dual-bot, single-server, etc.) + +Review and approve this plan before proceeding. + +![Generated PLAN.md file](./assets/onboard-plan-output.png) + +--- + +## Phase 4: Execute the Migration Plan + +With the `PLAN.md` approved, tell your AI coding agent to start executing it. The agent works through each phase of the plan autonomously, consulting the expert system for platform-specific patterns and making architecture decisions based on the cross-platform advisor's earlier analysis. + +``` +Execute the migration plan in PLAN.md. Start with Phase 1. +``` + +The agent does all the coding work — extracting shared services, creating adapters, bridging UI, wiring up auth. **Your role is to review the code it produces, test on both platforms, and provide feedback.** The sections below describe what the agent builds at each stage so you know what to look for during review. + +### 4.1 Architecture: Adapter Pattern + +The agent sets up a **shared service layer** with platform-specific adapters. The typical project structure it creates looks like: + +``` +your-app/ +├── src/ +│ ├── adapters/ +│ │ ├── slack-bot.ts # Slack Bolt adapter +│ │ └── teams-bot.ts # Teams AI SDK adapter +│ ├── services/ +│ │ ├── message-handler.ts # Shared business logic +│ │ ├── command-registry.ts # Shared command handling +│ │ └── action-handler.ts # Shared interactive responses +│ ├── ui/ +│ │ ├── blocks.ts # Block Kit builders +│ │ ├── cards.ts # Adaptive Card builders +│ │ └── convert.ts # Block Kit ↔ Adaptive Card conversion +│ ├── identity/ +│ │ └── user-map.ts # Cross-platform user identity mapping +│ └── index.ts # Entry point — starts both adapters +├── experts/ # Expert system (copied in Phase 3) +├── .env # Platform credentials +└── package.json +``` + +![Architecture diagram showing the adapter pattern — a central "Shared Service Layer" box connected to two adapter boxes (Slack Adapter and Teams Adapter). Each adapter connects to its respective platform.](./assets/adapter-pattern-architecture.png) + +### 4.2 Key Dependencies + +The agent adds the required Teams dependencies alongside your existing Slack packages: + +```json +{ + "dependencies": { + "@slack/bolt": "^4.0.0", + "@microsoft/teams-ai": "^2.0.0", + "botbuilder": "^4.23.0" + } +} +``` + +### 4.3 Entry Point Pattern + +The agent creates a single entry point that starts both platform adapters: + +```typescript +// src/index.ts +import { slackApp } from './adapters/slack-bot'; +import { teamsApp } from './adapters/teams-bot'; + +// Start Slack (Socket Mode) +slackApp.start(); +console.log('Slack bot running (Socket Mode)'); + +// Start Teams (HTTP on port 3978) +teamsApp.listen(3978); +console.log('Teams bot running on :3978'); +``` + +> See the working example at `examples/slack-add-teams/` for a complete reference implementation. + +--- + +## Phase 5: Review the Migrated Code + +As the agent works through `PLAN.md`, review what it produces at each step. The agent tackles features in order of difficulty — GREEN first, then YELLOW, then RED — extracting business logic into the shared service layer and creating platform-specific adapters. Here's what to expect and what to look for. + +### 5.1 Core Messaging and Commands + +The agent bridges your bot's message handling and commands between the two platforms: + +| Slack Pattern | Teams Equivalent | Difficulty | +|---------------|------------------|------------| +| `app.message()` handlers | `app.on('message')` activity handlers | GREEN | +| Slash commands (`/status`) | Text command detection or message extensions | GREEN | +| Button clicks / menu selections | Adaptive Card `Action.Submit` handlers | GREEN | +| Threaded replies (`thread_ts`) | Reply-to-activity chains | GREEN | +| Ephemeral messages (`postEphemeral`) | `refresh.userIds` per-user cards or 1:1 chat | YELLOW | +| Proactive messages | Conversation reference + `continueConversation` | YELLOW | + +For each feature, the agent creates a shared service function (business logic) and two thin adapters (one for Slack, one for Teams) that call into it. + +> **Expert references:** `experts/bridge/events-activities-ts.md`, `experts/bridge/commands-slash-text-ts.md`, `experts/bridge/interactive-responses-ts.md` + +### 5.2 UI Components + +The agent converts your Slack Block Kit layouts to Adaptive Cards for Teams. This is the most visible part of the migration — review the generated cards carefully. + +| Block Kit Element | Adaptive Card Equivalent | Difficulty | +|-------------------|-------------------------|------------| +| `section` with text | `TextBlock` | GREEN | +| `actions` with buttons | `ActionSet` with `Action.Submit` | GREEN | +| `input` block | `Input.Text` | GREEN | +| `image` / `context` / `divider` | `Image` / subtle `TextBlock` / separator | GREEN | +| Modals (`views.open`) | Task Modules / Dialogs | GREEN–YELLOW | +| Push new modal view | Multi-step dialog (sequential) | YELLOW | +| Mid-form modal updates | Close + reopen with new content | YELLOW | +| Field validation errors in modal | Custom validation before submit | RED | + +> **Expert references:** `experts/bridge/ui-block-kit-adaptive-cards-ts.md`, `experts/bridge/ui-modals-dialogs-ts.md` + +### 5.3 Identity and Auth + +The agent sets up the identity bridging layer so your bot can resolve users across both platforms: + +| Slack | Teams | +|-------|-------| +| Slack User ID (`U0123ABC`) | Azure AD Object ID (GUID) | +| OAuth 2.0 with Slack as provider | Azure AD / Microsoft SSO | +| `SLACK_CLIENT_ID` + `SLACK_CLIENT_SECRET` | `CLIENT_ID` + `CLIENT_SECRET` + `TENANT_ID` | +| `users.info` API | Microsoft Graph API | + +The agent generates a user mapping service that associates Slack User IDs with Azure AD Object IDs. For bulk mapping, Microsoft's data migration guide includes a [PowerShell script](https://learn.microsoft.com/en-us/microsoftteams/migrate-slack-to-teams#users) for matching Slack email addresses to Microsoft Entra ID accounts. + +> **Expert reference:** `experts/bridge/identity-oauth-bridge-ts.md` + +### 5.4 Infrastructure (Optional) + +If your Slack bot runs on AWS, the agent can bridge infrastructure to Azure. This is optional — the dual-platform approach doesn't require moving off AWS. + +| AWS Service | Azure Equivalent | Expert | +|-------------|-----------------|--------| +| Lambda | Azure Functions | `bridge/infra-compute-ts.md` | +| S3 | Azure Blob Storage | `bridge/infra-storage-ts.md` | +| DynamoDB | Cosmos DB | `bridge/infra-storage-ts.md` | +| Secrets Manager | Azure Key Vault | `bridge/infra-secrets-config-ts.md` | +| CloudWatch | Application Insights | `bridge/infra-observability-ts.md` | + +The agent also configures **dual transport** — Socket Mode (WebSocket) for Slack alongside an HTTPS endpoint on port 3978 for Teams. + +> **Expert reference:** `experts/bridge/transport-socketmode-https-ts.md` + +--- + +## Phase 6: Test and Deploy + +### 6.1 Local Testing + +1. **Slack:** Test via Socket Mode (no tunnel needed) +2. **Teams:** Start a dev tunnel (`devtunnel host -p 3978 --allow-anonymous`), set `BOT_ENDPOINT` in `env/.env.local`, then run `atk provision --env local` and `atk deploy --env local` +3. **Sideload** your Teams app in a test tenant, then send a test message to verify the bot responds. + +![Sideloaded bot in the Teams left rail with a chat window showing the bot responding to a test message](./assets/teams-sideload-bot-chat.png) + +### 6.2 Test Matrix + +Verify every migrated feature on both platforms: + +| Feature | Slack | Teams | Notes | +|---------|:-----:|:-----:|-------| +| Basic messages | [ ] | [ ] | | +| Commands | [ ] | [ ] | Slash vs. text | +| Cards / UI | [ ] | [ ] | Block Kit vs. Adaptive Cards | +| Modals / Dialogs | [ ] | [ ] | | +| File upload | [ ] | [ ] | | +| Auth flow | [ ] | [ ] | | +| Error handling | [ ] | [ ] | | + +### 6.3 Deploy + +For the dual-platform bot, deploy to a service that can run both adapters: + +| Option | Best For | +|--------|----------| +| **Azure App Service** | Full control, always-on, easy scaling | +| **Azure Container Apps** | Containerized workloads | +| **Azure Functions** | Event-driven, cost-optimized | +| **AWS Lambda + Azure Functions** | Keep Slack on AWS, add Teams on Azure | + +> **Expert reference:** `experts/deploy/azure-bot-deploy-ts.md`, `experts/deploy/aws-bot-deploy-ts.md` + +![Azure Portal Overview page for the deployed App Service showing Status: Running and the default `*.azurewebsites.net` endpoint](./assets/azure-app-service-overview.png) + +### 6.4 Publish to Your Organization + +1. Upload your Teams app package to the **Teams Admin Center** +2. Approve the app for your organization +3. Optionally pin the app in the Teams app bar for all users + +![Microsoft Teams admin center "Manage apps" page with a custom LOB app (`testbot0511dev`) listed and its app status visible](./assets/teams-admin-center-manage-apps.png) + +--- + +## Phase 7: Data Migration (Channels, Messages, Files) + +App migration and data migration are complementary efforts. While this guide focuses on apps, here's how data migration fits into the overall plan. + +### Microsoft's Official Data Migration Guide + +Follow [Migrate from Slack to Microsoft Teams](https://learn.microsoft.com/en-us/microsoftteams/migrate-slack-to-teams) for the complete data migration process: + +1. **Plan your migration** + - Determine what can be exported based on your Slack plan + - Assess workspace usage and scope + - Map Slack users to Microsoft 365 accounts + +2. **Export from Slack** + - Public channel history and files (all plans) + - Private channels and DMs (paid plans, may require DocuSign request) + - Use Slack's export tools: `https://get.slack.help/hc/articles/204897248` + +3. **Plan your Teams structure** + - Map Slack workspaces → Teams teams + - Map Slack channels → Teams channels + - Use the mapping table: + + | Slack Structure | Teams Structure | + |-----------------|-----------------| + | 1 small workspace | 1 team | + | 1 large workspace | Multiple teams | + | Multiple workspaces | Multiple teams (grouped logically) | + +4. **Import to Teams** + - Copy exported files to Teams channel document libraries + - Use tools like [ArgyleMigrator](https://github.com/rbrynteson/ArgyleMigrator) for channel history + - Set up Microsoft 365 Connectors to replace Slack webhooks + +5. **Roll out to users** + - License users for Teams + - Add users to the appropriate teams + - Remove Slack access on a coordinated schedule + - Provide training using [Microsoft's Teams adoption resources](https://adoption.microsoft.com/microsoft-teams/) + +### Coordination Timeline + +| Week | App Migration | Data Migration | +|------|--------------|----------------| +| 1-2 | Inventory & planning | Export Slack data, map users | +| 3-4 | Bootstrap expert system, architect | Plan Teams structure | +| 5-8 | Migrate core features, UI, auth | Import history, set up channels | +| 9-10 | Testing & deployment | Sideload apps, user testing | +| 11-12 | Publish to org | License users, cutover | + +--- + +## Post-Migration: Maintaining and Extending Your App + +Migration isn't the end — it's the beginning of building on a dual-platform (or Teams-native) foundation. The `slack-plus-teams` expert system continues to add value long after the initial migration. + +### Ongoing Development with the Expert System + +The expert system isn't just for migration — it's a permanent knowledge base for your AI coding agent. Keep the `experts/` directory in your project for ongoing development. + +#### Adding New Features + +When you need to add a new feature to your dual-platform bot: + +1. **Describe the feature** to your AI agent in natural language +2. The agent **routes to the correct expert(s)** via `experts/index.md` +3. The expert provides **platform-specific patterns** for both Slack and Teams +4. The agent implements the feature using the **shared service layer** pattern + +``` +Example prompt: +"Add a /ticket command that creates a Jira ticket and posts a confirmation +card with a link to the ticket. It should work on both Slack and Teams." +``` + +The agent will: +- Consult `experts/bridge/commands-slash-text-ts.md` for command bridging +- Consult `experts/bridge/ui-block-kit-adaptive-cards-ts.md` for the confirmation card +- Implement the shared service logic once, with platform-specific adapters + +#### Keeping Up with Platform Changes + +Both Slack and Teams regularly release new APIs and features. The expert system helps you adopt them: + +- **New Teams AI SDK features** → Consult `experts/teams/` domain experts +- **New Slack Bolt features** → Consult `experts/slack/` domain experts +- **New bridging patterns** → Consult `experts/bridge/` domain experts +- **AI model integration** → Consult `experts/models/` for OpenAI, Anthropic, Bedrock, etc. + +#### Updating the Expert System + +Pull the latest expert files periodically to get updated patterns: + +```bash +# Update experts from the slack-plus-teams repo +cd ./slack-plus-teams && git pull && cd .. +cp -r ./slack-plus-teams/experts/ ./experts/ +``` + +### Maintaining Your Dual-Platform App + +#### Shared Service Layer Benefits + +Because your business logic lives in the shared service layer, maintenance is simplified: + +| Change | Where to Edit | Platforms Affected | +|--------|--------------|-------------------| +| Business logic update | `services/` | Both (automatic) | +| New Slack-only feature | `adapters/slack-bot.ts` | Slack only | +| New Teams-only feature | `adapters/teams-bot.ts` | Teams only | +| UI update (both) | `ui/blocks.ts` + `ui/cards.ts` | Both | +| New shared command | `services/command-registry.ts` | Both (automatic) | + +#### Monitoring Both Platforms + +Set up observability for both platform adapters: + +- **Slack:** Monitor Socket Mode connection health, API rate limits +- **Teams:** Monitor HTTPS endpoint health, bot framework errors +- **Shared:** Monitor service layer errors, external API latency + +> **Expert reference:** `experts/bridge/infra-observability-ts.md` + +#### Scaling Your Team's Capabilities + +The expert system works with any AI coding agent. As your team grows: + +- New developers can use the onboarding flow (ONBOARD.md) to get productive immediately +- The expert system provides consistent, vetted patterns regardless of which AI agent is used +- Platform comparison docs in `docs/` give human developers quick reference for bridging decisions + +### Eventually Sunsetting Slack + +If your organization fully migrates to Teams, you can: + +1. **Remove the Slack adapter** (`adapters/slack-bot.ts`) and Slack dependencies +2. **Keep the shared service layer** — it's platform-agnostic business logic +3. **Simplify the entry point** to start only the Teams adapter +4. **Retain the expert system** — it's still valuable for Teams-specific development + +The adapter pattern makes this a clean, low-risk operation. + +--- + +## Quick Reference: Expert System Domains + +| Domain | Expert Count | Use For | +|--------|-------------|---------| +| `experts/bridge/` | 27 | Cross-platform bridging (the core of migration) | +| `experts/teams/` | 36 | Teams-specific features and patterns | +| `experts/slack/` | 19 | Slack-specific features and patterns | +| `experts/convert/` | 9 | Language conversion (JS/Ruby/Java/Kotlin → TypeScript) | +| `experts/models/` | 8 | AI model provider integration | +| `experts/deploy/` | 5 | Cloud deployment (Azure + AWS) | +| `experts/security/` | 3 | Input validation and secrets management | + +## Quick Reference: Key Expert Files for Migration + +| Migration Task | Expert File | +|----------------|-------------| +| Overall migration strategy | `bridge/cross-platform-advisor-ts.md` | +| Architecture decisions | `bridge/cross-platform-architecture-ts.md` | +| Block Kit → Adaptive Cards | `bridge/ui-block-kit-adaptive-cards-ts.md` | +| Slash commands → text commands | `bridge/commands-slash-text-ts.md` | +| Events → Activities | `bridge/events-activities-ts.md` | +| Modals → Task Modules | `bridge/ui-modals-dialogs-ts.md` | +| OAuth → Azure AD | `bridge/identity-oauth-bridge-ts.md` | +| Middleware → Handlers | `bridge/middleware-handlers-ts.md` | +| Socket Mode → HTTPS | `bridge/transport-socketmode-https-ts.md` | +| AWS → Azure infrastructure | `bridge/infra-compute-ts.md` | + +--- + +## Additional Resources + +- **Microsoft's data migration guide:** [Migrate from Slack to Microsoft Teams](https://learn.microsoft.com/en-us/microsoftteams/migrate-slack-to-teams) +- **Teams developer documentation:** [Microsoft Teams Platform](https://learn.microsoft.com/en-us/microsoftteams/platform/) +- **Slack Bolt documentation:** [Slack Bolt for JavaScript](https://slack.dev/bolt-js/) +- **Teams AI SDK:** [Teams AI Library](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/teams-conversational-ai/teams-conversation-ai-overview) +- **Working examples:** See `examples/slack-add-teams/` and `examples/dual-platform-bot/` in this repository +- **Platform differences:** See `docs/feature-gaps.md` for the complete RED/YELLOW gap inventory diff --git a/skills/microsoft-365-agents-toolkit/docs/slack-plus-teams-architecture.pptx b/skills/microsoft-365-agents-toolkit/docs/slack-plus-teams-architecture.pptx new file mode 100644 index 0000000..d4db029 Binary files /dev/null and b/skills/microsoft-365-agents-toolkit/docs/slack-plus-teams-architecture.pptx differ diff --git a/skills/microsoft-365-agents-toolkit/experts/bridge/app-distribution-packaging-ts.md b/skills/microsoft-365-agents-toolkit/experts/bridge/app-distribution-packaging-ts.md index ebb2dd7..c08dc33 100644 --- a/skills/microsoft-365-agents-toolkit/experts/bridge/app-distribution-packaging-ts.md +++ b/skills/microsoft-365-agents-toolkit/experts/bridge/app-distribution-packaging-ts.md @@ -11,7 +11,7 @@ Bridges Slack App Directory distribution and Teams app packaging / Admin Center 3. **Slack `InstallationStore` → conversation reference storage.** Slack's `InstallationStore` persists tokens per workspace for API calls. Teams doesn't need per-workspace tokens, but you still need to store conversation references for proactive messaging. Replace `InstallationStore` with a conversation reference store keyed by `conversationId`. [learn.microsoft.com -- Proactive messages](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages) 4. **Slack org-level install → Teams Admin Center tenant-wide deployment.** Slack Enterprise Grid supports org-level app installation. In Teams, tenant-wide deployment is done via the Teams Admin Center by an IT admin: Manage Apps → Upload/Approve → Deploy to users/groups. No code changes needed — the admin controls distribution. [learn.microsoft.com -- Admin Center](https://learn.microsoft.com/en-us/microsoftteams/manage-apps) 5. **Development install → Teams sideloading.** Slack development apps are installed via the app's manage page or OAuth URL. Teams development apps are sideloaded: upload the app package (ZIP with manifest + icons) directly into Teams. Sideloading must be enabled by the tenant admin. [learn.microsoft.com -- Sideloading](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload) -6. **Teams Toolkit simplifies packaging, provisioning, and deployment.** Teams Toolkit (VS Code extension or CLI `teamsapp`) automates: Azure resource provisioning, app package generation, sideloading, and publishing. It replaces the manual Azure Portal + zip file workflow. Use `teamsapp package` to generate the app package and `teamsapp publish` to submit. [learn.microsoft.com -- Teams Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teams-toolkit-fundamentals) +6. **Agents Toolkit simplifies packaging, provisioning, and deployment.** Agents Toolkit (VS Code extension or CLI `atk`) automates: Azure resource provisioning, app package generation, sideloading, and publishing. It replaces the manual Azure Portal + zip file workflow. Use `atk package` to generate the app package and `atk publish` to submit. [learn.microsoft.com -- Agents Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teams-toolkit-fundamentals) 7. **Multi-tenant Slack app → Azure AD multi-tenant app registration.** Slack multi-workspace apps use the App Directory + OAuth per workspace. Teams multi-tenant bots use a single Azure AD app registration with `signInAudience: "AzureADMultipleOrgs"`. Any tenant can install the bot without workspace-specific OAuth. [learn.microsoft.com -- Multi-tenant](https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-authentication-basics) 8. **Slack app manifest (`manifest.json`) → Teams app manifest (`manifest.json` in app package).** Both platforms use JSON manifests but with completely different schemas. Slack's manifest includes OAuth scopes, event subscriptions, slash commands. Teams manifest includes `bots`, `composeExtensions`, `staticTabs`, `webApplicationInfo`, `validDomains`. No automatic conversion exists. [learn.microsoft.com -- Manifest schema](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema) 9. **Slack app icons (512x512 + workspace-specific) → Teams icons (color 192x192 + outline 32x32).** Teams requires exactly two icon files in the app package: a full-color icon (192x192 PNG) and an outline/monochrome icon (32x32 PNG with transparent background). The outline icon is used in the Teams activity bar. [learn.microsoft.com -- App icons](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema#icons) @@ -115,13 +115,13 @@ app.start(3978); ```shell # Option 1: Sideload for development # Build the app package (manifest.json + icons in a ZIP) -teamsapp package --env dev +atk package --env dev -i false # Upload to Teams: # Teams → Apps → Manage your apps → Upload a custom app # Option 2: Submit to organization's app catalog -teamsapp publish --env staging +atk publish --env staging # IT admin approves in Teams Admin Center → Manage Apps # Option 3: Submit to public Teams App Store (Partner Center) @@ -181,10 +181,10 @@ my-teams-bot.zip ## instructions -Use this expert when adding cross-platform support in either direction for app distribution and packaging. It covers: Slack App Directory bridged to Teams App Store (Partner Center), OAuth install flow vs Azure Bot registration, InstallationStore vs conversation reference storage, org-level deployment via Teams Admin Center, sideloading for development, Teams Toolkit for packaging, multi-tenant Azure AD registration, icon requirements, store review timelines, and reverse mapping from Teams manifest/Admin Center back to Slack app manifest and App Directory submission. Pair with `identity-oauth-bridge-ts.md` for the identity/OAuth model change, `../teams/runtime.manifest-ts.md` for Teams manifest creation, and `../teams/runtime.proactive-messaging-ts.md` for conversation reference storage patterns. +Use this expert when adding cross-platform support in either direction for app distribution and packaging. It covers: Slack App Directory bridged to Teams App Store (Partner Center), OAuth install flow vs Azure Bot registration, InstallationStore vs conversation reference storage, org-level deployment via Teams Admin Center, sideloading for development, Agents Toolkit for packaging, multi-tenant Azure AD registration, icon requirements, store review timelines, and reverse mapping from Teams manifest/Admin Center back to Slack app manifest and App Directory submission. Pair with `identity-oauth-bridge-ts.md` for the identity/OAuth model change, `../teams/runtime.manifest-ts.md` for Teams manifest creation, and `../teams/runtime.proactive-messaging-ts.md` for conversation reference storage patterns. ## research Deep Research prompt: -"Write a micro expert for bridging Slack App Directory distribution and Microsoft Teams app packaging / Admin Center publishing in either direction. Cover: App Directory vs Teams App Store (Partner Center), OAuth install flow vs Azure Bot registration, InstallationStore vs conversation reference storage, org-level install vs Teams Admin Center, sideloading, Teams Toolkit packaging, multi-tenant Azure AD app registration, icon requirements, manifest schema differences, OAuth scope to RSC mapping, store review timeline, and reverse mapping from Teams manifest/publishing back to Slack app manifest and App Directory submission. Include code examples and a mapping table." +"Write a micro expert for bridging Slack App Directory distribution and Microsoft Teams app packaging / Admin Center publishing in either direction. Cover: App Directory vs Teams App Store (Partner Center), OAuth install flow vs Azure Bot registration, InstallationStore vs conversation reference storage, org-level install vs Teams Admin Center, sideloading, Agents Toolkit packaging, multi-tenant Azure AD app registration, icon requirements, manifest schema differences, OAuth scope to RSC mapping, store review timeline, and reverse mapping from Teams manifest/publishing back to Slack app manifest and App Directory submission. Include code examples and a mapping table." diff --git a/skills/microsoft-365-agents-toolkit/experts/deploy/azure-bot-deploy-ts.md b/skills/microsoft-365-agents-toolkit/experts/deploy/azure-bot-deploy-ts.md index cf13a22..0a7de69 100644 --- a/skills/microsoft-365-agents-toolkit/experts/deploy/azure-bot-deploy-ts.md +++ b/skills/microsoft-365-agents-toolkit/experts/deploy/azure-bot-deploy-ts.md @@ -6,7 +6,7 @@ Step-by-step deployment of a Slack bot, Teams bot, or dual bot to Azure. Covers ## rules -1. **Install prerequisites before anything else.** You need: Node.js 20 LTS, Azure CLI (`az`), and optionally the Agents Toolkit CLI (`npm install -g @microsoft/teamsapp-cli`). Verify with `az --version` and `node --version`. [learn.microsoft.com/cli/azure/install-azure-cli](https://learn.microsoft.com/cli/azure/install-azure-cli) +1. **Install prerequisites before anything else.** You need: Node.js 20 LTS, Azure CLI (`az`), and optionally the Agents Toolkit CLI (`npm install -g @microsoft/m365agentstoolkit-cli`). Verify with `az --version` and `node --version`. [learn.microsoft.com/cli/azure/install-azure-cli](https://learn.microsoft.com/cli/azure/install-azure-cli) 2. **Authenticate and set the target subscription.** Run `az login` to open browser auth, then `az account set --subscription `. All subsequent commands use this subscription. [learn.microsoft.com/cli/azure/authenticate-azure-cli](https://learn.microsoft.com/cli/azure/authenticate-azure-cli) 3. **Create a resource group to contain all bot resources.** `az group create --name --location `. Use a region close to your users (e.g., `eastus`, `westeurope`). All subsequent resources go in this group. [learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-cli](https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-cli) 4. **Register an Entra ID App Registration.** This is the bot's identity — required for both Teams and Slack bots on Azure. `az ad app create --display-name ` returns an `appId` (client ID). Then create a secret: `az ad app credential reset --id `. Save the `password` — it's the CLIENT_SECRET and is only shown once. [learn.microsoft.com/entra/identity-platform/quickstart-register-app](https://learn.microsoft.com/entra/identity-platform/quickstart-register-app) @@ -19,7 +19,7 @@ Step-by-step deployment of a Slack bot, Teams bot, or dual bot to Azure. Covers 11. **Build and deploy.** Run `npm run build` locally, then zip deploy: `az webapp deploy --resource-group --name --src-path --type zip`. For Functions: `func azure functionapp publish `. [learn.microsoft.com/azure/app-service/deploy-zip](https://learn.microsoft.com/azure/app-service/deploy-zip) 12. **Enable Always On for App Service.** `az webapp config set --resource-group --name --always-on true`. Without this, the app goes idle after 20 minutes and the next request cold-starts. For Functions Premium, configure Always Ready instances instead. [learn.microsoft.com/azure/app-service/configure-common](https://learn.microsoft.com/azure/app-service/configure-common) 13. **Verify the deployment.** Check the health endpoint: `curl https://.azurewebsites.net/api/health`. Then send a test message in Teams or Slack. Check App Service logs: `az webapp log tail --resource-group --name `. [learn.microsoft.com/azure/app-service/troubleshoot-diagnostic-logs](https://learn.microsoft.com/azure/app-service/troubleshoot-diagnostic-logs) -14. **Agents Toolkit fast path (Teams bots).** Instead of steps 3-12, run `teamsapp provision` (creates App Registration, Bot Service, App Service, and all config) then `teamsapp deploy` (builds and deploys). Two commands replace the entire manual process. Requires a `teamsapp.yml` in your project. [learn.microsoft.com/microsoftteams/platform/toolkit/teamsfx-cli](https://learn.microsoft.com/microsoftteams/platform/toolkit/teamsfx-cli) +14. **Agents Toolkit fast path (Teams bots).** Instead of steps 3-12, run `atk provision` (creates App Registration, Bot Service, App Service, and all config) then `atk deploy` (builds and deploys). Two commands replace the entire manual process. Requires an `m365agents.yml` in your project. [learn.microsoft.com/microsoftteams/platform/toolkit/toolkit-cli](https://learn.microsoft.com/microsoftteams/platform/toolkit/microsoft-365-agents-toolkit-cli) ## interview @@ -45,7 +45,7 @@ question: "How do you want to deploy?" header: "Method" options: - label: "Agents Toolkit CLI (Recommended)" - description: "teamsapp provision + teamsapp deploy — automates App Registration, Bot Service, App Service, and manifest sideloading in two commands." + description: "atk provision + atk deploy — automates App Registration, Bot Service, App Service, and manifest sideloading in two commands." - label: "Manual az CLI" description: "Full control, step-by-step. Learn exactly what resources are created and how they connect." - label: "You Decide Everything" @@ -143,19 +143,20 @@ az webapp log tail --resource-group rg-mybot --name mybot-app ```bash # 1. Install Agents Toolkit CLI -npm install -g @microsoft/teamsapp-cli +npm install -g @microsoft/m365agentstoolkit-cli@beta # 2. Provision all Azure resources (App Registration, Bot Service, App Service) -teamsapp provision --env dev +atk provision --env dev --resource-group --region -i false # 3. Build and deploy -teamsapp deploy --env dev +atk deploy --env dev -i false # 4. Sideload to Teams for testing -teamsapp preview --env dev +# Get TEAMS_APP_ID from env/.env.dev, open: +# https://teams.microsoft.com/l/app/$TEAMS_APP_ID?installAppPackage=true&webjoin=true -# That's it — three commands from zero to running bot in Teams. -# teamsapp.yml in your project defines the resource topology. +# That's it — two commands from zero to running bot in Teams. +# m365agents.yml in your project defines the resource topology. ``` ### Slack bot on Azure App Service @@ -239,7 +240,7 @@ az webapp config appsettings set \ - https://learn.microsoft.com/azure/app-service/quickstart-nodejs - https://learn.microsoft.com/azure/app-service/deploy-zip - https://learn.microsoft.com/azure/app-service/configure-common -- https://learn.microsoft.com/microsoftteams/platform/toolkit/teamsfx-cli +- https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/microsoft-365-agents-toolkit-cli - https://learn.microsoft.com/azure/app-service/troubleshoot-diagnostic-logs ## instructions @@ -252,4 +253,4 @@ Pair with: `../teams/project.scaffold-files-ts.md` (project structure before dep Deep Research prompt: -"Write a micro expert on deploying a Slack Bolt.js or Microsoft Teams bot to Azure. Cover: Azure CLI installation, az login, resource group creation, Entra ID App Registration (client ID + secret), Azure Bot Service creation and Teams channel connection, App Service provisioning with Node.js 20 LTS, environment variable configuration via App Settings, zip deployment, Always On configuration, Agents Toolkit CLI (teamsapp provision + teamsapp deploy) as a fast path, Slack-on-Azure configuration (Event Subscriptions URL), dual bot deployment on shared Express, and common deployment verification steps. Provide 3-4 canonical bash script examples and 6-8 common pitfalls." +"Write a micro expert on deploying a Slack Bolt.js or Microsoft Teams bot to Azure. Cover: Azure CLI installation, az login, resource group creation, Entra ID App Registration (client ID + secret), Azure Bot Service creation and Teams channel connection, App Service provisioning with Node.js 20 LTS, environment variable configuration via App Settings, zip deployment, Always On configuration, Agents Toolkit CLI (atk provision + atk deploy) as a fast path, Slack-on-Azure configuration (Event Subscriptions URL), dual bot deployment on shared Express, and common deployment verification steps. Provide 3-4 canonical bash script examples and 6-8 common pitfalls." diff --git a/skills/microsoft-365-agents-toolkit/experts/deploy/index.md b/skills/microsoft-365-agents-toolkit/experts/deploy/index.md index e4cfc6d..4ea48d2 100644 --- a/skills/microsoft-365-agents-toolkit/experts/deploy/index.md +++ b/skills/microsoft-365-agents-toolkit/experts/deploy/index.md @@ -46,7 +46,7 @@ multiSelect: false ## task clusters ### Deploy to Azure -When: deploying a bot to Azure, Azure App Service, Azure Functions, Azure Container Apps, `az` CLI, `az login`, Azure Bot registration, App Registration, Entra ID, `teamsapp provision`, `teamsapp deploy`, Agents Toolkit deploy, deploy Teams bot, deploy Slack bot to Azure +When: deploying a bot to Azure, Azure App Service, Azure Functions, Azure Container Apps, `az` CLI, `az login`, Azure Bot registration, App Registration, Entra ID, `atk provision`, `atk deploy`, Agents Toolkit deploy, deploy Teams bot, deploy Slack bot to Azure Read: - `azure-bot-deploy-ts.md` Cross-domain deps: `../teams/project.scaffold-files-ts.md` (project structure), `../teams/runtime.manifest-ts.md` (Teams manifest for sideloading), `../teams/dev.debug-test-ts.md` (Agents Toolkit reference), `../security/secrets-ts.md` (secrets hygiene), `../bridge/infra-compute-ts.md` (if also migrating from AWS) diff --git a/skills/microsoft-365-agents-toolkit/experts/index.md b/skills/microsoft-365-agents-toolkit/experts/index.md index bf934be..afea0b8 100644 --- a/skills/microsoft-365-agents-toolkit/experts/index.md +++ b/skills/microsoft-365-agents-toolkit/experts/index.md @@ -78,7 +78,7 @@ The pre-task interview gates the entire workflow. Expert-level `## interview` se Scan the user's message for signal words. Pick the **first matching domain**; if signals overlap, prefer the domain whose signals appear more often. ### Teams — build or modify a Teams bot / agent -Signals: Teams SDK, `@microsoft/teams-ai`, Adaptive Cards, ChatPrompt, Graph API, MCP, A2A, `app.ts`, manifest, proactive message, message extension, dialog, task module, Teams Toolkit, Bot Framework, SSO, OAuth, streaming, citations, RAG, function calling, memory, state, storage, `microsoft_teams`, `microsoft_teams.apps`, `microsoft_teams.ai`, `ActivityContext`, `@app.on_message`, `OpenAICompletionsAIModel`, `Microsoft.Teams.Apps`, `Microsoft.Teams.AI`, `AddTeams()`, `UseTeams()`, `IContext`, `OnMessage`, `OpenAIChatPrompt`, Teams Python, Teams .NET, Teams C#, `m365agents.yml`, `teamsapp provision`, `teamsapp deploy`, `teamsapp publish`, `teamsapp preview`, `teamsapp validate`, `teamsapp package`, `teamsapp new`, Agents Playground, `.m365agentsplayground.yml`, lifecycle hooks, `env/.env`, SharePoint Lists, workflow state, message-native records, Action.Execute refresh, presence trigger, Shifts trigger, call queue, Graph change notifications, approval workflow, in-channel approval, escalation, conversational query, natural language query, NL retrieval, composable workflow, workflow engine +Signals: Teams SDK, `@microsoft/teams-ai`, Adaptive Cards, ChatPrompt, Graph API, MCP, A2A, `app.ts`, manifest, proactive message, message extension, dialog, task module, Agents Toolkit, Bot Framework, SSO, OAuth, streaming, citations, RAG, function calling, memory, state, storage, `microsoft_teams`, `microsoft_teams.apps`, `microsoft_teams.ai`, `ActivityContext`, `@app.on_message`, `OpenAICompletionsAIModel`, `Microsoft.Teams.Apps`, `Microsoft.Teams.AI`, `AddTeams()`, `UseTeams()`, `IContext`, `OnMessage`, `OpenAIChatPrompt`, Teams Python, Teams .NET, Teams C#, `m365agents.yml`, `atk provision`, `atk deploy`, `atk publish`, `atk preview`, `atk validate`, `atk package`, `atk new`, Agents Playground, `.m365agentsplayground.yml`, lifecycle hooks, `env/.env`, SharePoint Lists, workflow state, message-native records, Action.Execute refresh, presence trigger, Shifts trigger, call queue, Graph change notifications, approval workflow, in-channel approval, escalation, conversational query, natural language query, NL retrieval, composable workflow, workflow engine → Read `experts/teams/index.md` ### Slack — build or modify a Slack app @@ -94,7 +94,7 @@ Signals: OpenAI, Azure OpenAI, GPT-4o, GPT-4, Anthropic, Claude, `@anthropic-ai/ → Read `experts/models/index.md` ### Deploy — deploy a bot to Azure or AWS -Signals: deploy, deployment, provision, hosting, publish, go live, production, `az login`, `aws configure`, App Service, Azure Functions, Container Apps, Lambda, EC2, ECS, Fargate, Elastic Beanstalk, Azure Bot, `teamsapp provision`, `teamsapp deploy`, Agents Toolkit deploy, zip deploy, SAM deploy, CDK deploy, API Gateway, deploy to Azure, deploy to AWS, push to cloud, CloudFormation +Signals: deploy, deployment, provision, hosting, publish, go live, production, `az login`, `aws configure`, App Service, Azure Functions, Container Apps, Lambda, EC2, ECS, Fargate, Elastic Beanstalk, Azure Bot, `atk provision`, `atk deploy`, Agents Toolkit deploy, zip deploy, SAM deploy, CDK deploy, API Gateway, deploy to Azure, deploy to AWS, push to cloud, CloudFormation → Read `experts/deploy/index.md` ### Convert — rewrite source code from another language to TypeScript diff --git a/skills/microsoft-365-agents-toolkit/experts/teams/dev.debug-test-ts.md b/skills/microsoft-365-agents-toolkit/experts/teams/dev.debug-test-ts.md index e79bf2a..75e315f 100644 --- a/skills/microsoft-365-agents-toolkit/experts/teams/dev.debug-test-ts.md +++ b/skills/microsoft-365-agents-toolkit/experts/teams/dev.debug-test-ts.md @@ -13,9 +13,10 @@ Developer tools, local debugging, DevTools plugin, sideloading, tunneling, Conso 5. Configure logging with `ConsoleLogger` at the appropriate level: `'trace'` for deep SDK internals, `'debug'` for development, `'info'` for staging, `'warn'` or `'error'` for production. Use `pattern: '-azure/msal-node'` to suppress noisy MSAL authentication logs. Child loggers are created with `logger.child('name')`. [github.com/microsoft/teams.ts -- common](https://github.com/microsoft/teams.ts/tree/main/packages/common) 6. Run `npx tsc --noEmit` as a build verification gate before testing or deploying. This type-checks all TypeScript source without producing output files. The project must compile cleanly -- type errors caught here prevent runtime failures. [github.com/microsoft/teams.ts](https://github.com/microsoft/teams.ts) 7. For testing with real Teams clients locally, use a tunneling solution (ngrok, dev tunnels, Cloudflare Tunnel) to expose your local `localhost:3978` endpoint over HTTPS. Update the Azure Bot messaging endpoint to the tunnel URL (e.g., `https://abc123.ngrok.io/api/messages`). [learn.microsoft.com -- Dev tunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview) -8. Sideload the app by creating a zip of the `appPackage/` directory (manifest.json + icons) and uploading in Teams via Apps > Manage your apps > Upload a custom app. Sideloading requires admin permission or a developer tenant. [learn.microsoft.com -- Sideload apps](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload) +8. Sideload the app by opening the Teams sideloading URL after provisioning: `https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&appTenantId=${{TENANT_ID}}&login_hint=${{USER_EMAIL}}` Use `TEAMS_APP_ID` and `USER_EMAIL` from `env/.env.local`; use `TENANT_ID` from `.localConfigs` (generated by `atk deploy --env local`, mapped from `TEAMS_APP_TENANT_ID` in `env/.env.local`). Alternatively, zip the `appPackage/` directory (manifest.json + icons) and upload in Teams via Apps > Manage your apps > Upload a custom app. Both paths require admin-enabled custom app upload or a developer tenant. [learn.microsoft.com -- Sideload apps](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload) 9. Use `skipAuth: true` in `AppOptions` for purely local development against DevTools without Azure Bot credentials. This disables JWT validation. Never use it in production or when testing against real Teams clients. [github.com/microsoft/teams.ts -- apps](https://github.com/microsoft/teams.ts/tree/main/packages/apps) -10. The M365 Agents Toolkit VS Code extension provides GUI-based provisioning, dev tunnel management, one-click deployment, and manifest editing. It is an alternative to manual CLI workflows for developers who prefer a visual interface. [learn.microsoft.com -- Agents Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-v4/teams-toolkit-fundamentals-vs) +10. Use Agents Toolkit (ATK) as the recommended provisioning path for local development. First start a devtunnel (`devtunnel host -p 3978 --allow-anonymous`) and set `BOT_ENDPOINT` in `env/.env.local` to the tunnel URL. Then run `atk provision --env local -i false` to create the Entra ID app registration, Bot Framework registration, and Teams app. Then run `atk deploy --env local -i false` to generate `.localConfigs` with CLIENT_ID, CLIENT_SECRET, TENANT_ID, and PORT. Verify `.localConfigs` has TENANT_ID — if missing, copy the value of `TEAMS_APP_TENANT_ID` from `env/.env.local` into `TENANT_ID` in `.localConfigs`. See → `toolkit.lifecycle-cli.md` for the full m365agents.yml reference. [learn.microsoft.com -- Agents Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/microsoft-365-agents-toolkit-cli) +11. For manual bot registration without ATK, create the Entra ID app registration and Azure Bot resource through the Azure Portal or Azure CLI, then copy the credentials into `.env`. This path is useful for understanding what ATK automates or when ATK is not available. See → `azure-bot-deploy-ts.md` for the full manual workflow. ## patterns @@ -90,43 +91,55 @@ app.start(process.env.PORT || 3978).catch(console.error); ### Build verification and debugging workflow ```typescript -// Step-by-step local development workflow: +// === Option A: ATK-provisioned workflow (recommended) === // 1. Install dependencies // npm install -// 2. Create .env with required variables -// CLIENT_ID= -// CLIENT_SECRET= -// TENANT_ID= -// PORT=3978 +// 2. Start a dev tunnel (must be running BEFORE provisioning) +// devtunnel host -p 3978 --allow-anonymous +// Copy the tunnel URL and set BOT_ENDPOINT in env/.env.local -// 3. Type-check the project (build gate) +// 3. Provision bot resources via ATK (creates Entra ID app + Bot Framework + Teams app) +// atk provision --env local -i false + +// 4. Generate .localConfigs with credentials +// atk deploy --env local -i false +// Verify .localConfigs contains CLIENT_ID, CLIENT_SECRET, TENANT_ID, PORT. +// If TENANT_ID is missing, copy the value of TEAMS_APP_TENANT_ID from env/.env.local into TENANT_ID in .localConfigs. + +// 5. Type-check the project (build gate) // npx tsc --noEmit -// Fix any type errors before proceeding. -// 4. Start dev server with file watching +// 6. Start dev server with file watching // npm run dev -// This runs: tsx watch -r dotenv/config src/index.ts -// 5. Open DevTools in browser +// 7. Open DevTools in browser // http://localhost:3979/devtools -// Send test messages, inspect activities in real time. -// 6. For real Teams testing, set up a tunnel: -// ngrok http 3978 -// Copy the HTTPS URL (e.g., https://abc123.ngrok.io) -// Update Azure Bot messaging endpoint to: -// https://abc123.ngrok.io/api/messages +// 8. For real Teams testing, start a dev tunnel and provision: +// devtunnel host -p 3978 --allow-anonymous +// Set BOT_ENDPOINT in env/.env.local to the tunnel URL +// atk provision --env local -i false +// atk deploy --env local -i false +// Open Teams sideload URL (TEAMS_APP_ID from env/.env.local): +// https://teams.microsoft.com/l/app/$TEAMS_APP_ID?installAppPackage=true&webjoin=true&appTenantId=$TENANT_ID +// (TEAMS_APP_ID from env/.env.local; TENANT_ID from .localConfigs, mapped from TEAMS_APP_TENANT_ID in env/.env.local) + +// === Option B: Manual workflow (no ATK) === + +// 1. npm install +// 2. Create .env: CLIENT_ID, CLIENT_SECRET, TENANT_ID, PORT=3978 +// (Register bot manually -- see azure-bot-deploy-ts.md) +// 3. npx tsc --noEmit +// 4. npm run dev +// 5. devtunnel host -p 3978 --allow-anonymous → update Azure Bot messaging endpoint +// 6. Sideload: zip appPackage/ → upload in Teams -// 7. Sideload the app: -// cd appPackage -// zip -r ../mybot.zip manifest.json color.png outline.png -// Upload mybot.zip in Teams > Apps > Upload a custom app +// === Build for production (both options) === -// 8. Build for production: -// npm run build # Compiles to dist/ via tsup -// npm run start # Runs compiled JS: node -r dotenv/config . +// npm run build # Compiles to dist/ via tsup +// npm run start # Runs compiled JS: node -r dotenv/config . // Common troubleshooting: // - Bot not responding in Teams? @@ -137,6 +150,8 @@ app.start(process.env.PORT || 3978).catch(console.error); // Check: tsconfig module is "NodeNext", not "commonjs" // - .env not loaded? // Check: dotenv in devDependencies, -r dotenv/config in scripts +// - 401 Unauthorized after atk deploy? +// Check: .localConfigs has TENANT_ID; if missing, copy the value of TEAMS_APP_TENANT_ID from env/.env.local into TENANT_ID in .localConfigs ``` ## pitfalls @@ -149,6 +164,8 @@ app.start(process.env.PORT || 3978).catch(console.error); - **Missing sideload permissions**: Sideloading requires either admin-enabled custom app upload or a Microsoft 365 developer tenant. Without it, the "Upload a custom app" option does not appear in Teams. - **Wrong log level in production**: Running with `'debug'` or `'trace'` in production floods logs and can impact performance. Switch to `'info'` or `'warn'` for deployed environments. - **Testing only in DevTools**: DevTools simulates a Teams client but does not replicate all Teams behaviors (e.g., @mention stripping, SSO token exchange, card rendering differences). Always test in a real Teams client before shipping. +- **`.localConfigs` missing TENANT_ID**: After `atk deploy --env local`, the generated `.localConfigs` may omit `TENANT_ID`. Without it, MSAL defaults to the wrong token authority, causing 401 errors. Copy the value of `TEAMS_APP_TENANT_ID` from `env/.env.local` into `TENANT_ID` in `.localConfigs`. +- **Dev tunnel URL blacklisted or expired**: Dev tunnel URLs can be flagged by corporate proxies or expire after inactivity. If the bot suddenly stops receiving messages with a working tunnel, create a fresh tunnel and update the messaging endpoint. ## references @@ -168,8 +185,9 @@ This expert covers local development, debugging, and testing workflows for Teams - Run the bot locally with `npm run dev` (tsx watch with hot reload) - Configure `ConsoleLogger` levels and noise filtering for different environments - Use `skipAuth: true` for credential-free local testing -- Set up ngrok or dev tunnels for testing with real Teams clients -- Sideload the bot by packaging and uploading `appPackage/` as a zip +- Provision bot credentials locally with `atk provision --env local` and `atk deploy --env local` +- Set up dev tunnels or ngrok for testing with real Teams clients +- Sideload the bot via the Teams sideloading URL or by packaging and uploading `appPackage/` as a zip - Run `npx tsc --noEmit` as a build verification gate - Troubleshoot common issues (bot not responding, DevTools blank, import errors) - Understand the difference between DevTools testing and real Teams testing diff --git a/skills/microsoft-365-agents-toolkit/experts/teams/index.md b/skills/microsoft-365-agents-toolkit/experts/teams/index.md index 9b8a6a0..6e4e5a3 100644 --- a/skills/microsoft-365-agents-toolkit/experts/teams/index.md +++ b/skills/microsoft-365-agents-toolkit/experts/teams/index.md @@ -172,7 +172,7 @@ Read: - `runtime.routing-handlers-ts.md` (for mapping TeamsActivityHandler to SDK v2 routes) ### Dev: Debug & Test -When: debugging, testing, Teams Toolkit, local tunnel, dev tools, unit tests +When: debugging, testing, Agents Toolkit, local tunnel, dev tools, unit tests Read: - `dev.debug-test-ts.md` - `project.scaffold-files-ts.md` (for npm scripts and build verification) @@ -197,7 +197,7 @@ Read: Note: C# has SDK support for Teams only (Tier 3). For the Slack side, route to `../bridge/rest-only-integration-ts.md`. ### Toolkit: Lifecycle & CLI -When: `m365agents.yml`, `teamsapp` CLI, `teamsapp provision`, `teamsapp deploy`, `teamsapp publish`, `teamsapp new`, lifecycle hooks, CI/CD pipeline, built-in actions, `uses:`, `runs:`, `arm/deploy`, `azureAppService/deploy`, `teamsApp/create`, `writeToEnvironmentFile` +When: `m365agents.yml`, `atk` CLI, `atk provision`, `atk deploy`, `atk publish`, `atk new`, lifecycle hooks, CI/CD pipeline, built-in actions, `uses:`, `runs:`, `arm/deploy`, `azureAppService/deploy`, `teamsApp/create`, `writeToEnvironmentFile` Read: - `toolkit.lifecycle-cli.md` Depends on: `project.scaffold-files-ts.md` (project must exist before lifecycle commands apply) @@ -209,13 +209,13 @@ Read: Depends on: `toolkit.lifecycle-cli.md` (environments are consumed by lifecycle hooks) ### Toolkit: Agents Playground -When: Agents Playground, local testing, `teamsapp preview`, test harness, mock activity, playground config, `.m365agentsplayground.yml`, browser-based testing +When: Agents Playground, local testing, `atk preview`, test harness, mock activity, playground config, `.m365agentsplayground.yml`, browser-based testing Read: - `toolkit.playground-ts.md` - `dev.debug-test-ts.md` (broader debug patterns) ### Toolkit: Publishing -When: publish to org, Teams Store, Partner Center, admin approval, `teamsapp publish`, `teamsapp validate`, `teamsapp package`, `teamsapp update`, app validation, sideload to org, org catalog, version bump +When: publish to org, Teams Store, Partner Center, admin approval, `atk publish`, `atk validate`, `atk package`, `atk update`, app validation, sideload to org, org catalog, version bump Read: - `toolkit.publish.md` - `runtime.manifest-ts.md` (manifest must be valid before publishing) diff --git a/skills/microsoft-365-agents-toolkit/experts/teams/runtime.manifest-ts.md b/skills/microsoft-365-agents-toolkit/experts/teams/runtime.manifest-ts.md index 1b9914f..09a481f 100644 --- a/skills/microsoft-365-agents-toolkit/experts/teams/runtime.manifest-ts.md +++ b/skills/microsoft-365-agents-toolkit/experts/teams/runtime.manifest-ts.md @@ -13,7 +13,7 @@ Teams app manifest (manifest.json) structure, schema, bots config, permissions, 5. The `validDomains` array lists domains the bot is allowed to open in web views and task modules. Always include `"*.botframework.com"` and your bot's domain. Omitting a domain causes blank task modules. [learn.microsoft.com -- Valid domains](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema#validdomains) 6. The `webApplicationInfo` section provides SSO configuration with `id` (the bot/app ID) and `resource` (the application ID URI, typically `"api://botid-${{BOT_ID}}"`). Required for OAuth/SSO flows. [learn.microsoft.com -- webApplicationInfo](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema#webapplicationinfo) 7. Icons must be: `color.png` at exactly 192x192 pixels and `outline.png` at exactly 32x32 pixels with a transparent background. Both are PNG format. Place them in the `appPackage/` directory alongside `manifest.json`. [learn.microsoft.com -- App icons](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/apps-package#app-icons) -8. Package the app as a `.zip` file containing `manifest.json`, `color.png`, and `outline.png` from the `appPackage/` directory. The zip must contain these files at the root level (not nested in subdirectories). Upload via Teams > Apps > Upload a custom app, or through Teams Admin Center. [learn.microsoft.com -- App package](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/apps-package) +8. Package the app as a `.zip` file containing `manifest.json`, `color.png`, and `outline.png` from the `appPackage/` directory. The zip must contain these files at the root level (not nested in subdirectories). Use `atk package` to generate the zip with placeholders resolved, or manually zip and upload via Teams > Apps > Upload a custom app, or through Teams Admin Center. [learn.microsoft.com -- App package](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/apps-package) 9. Use placeholder variables like `${{TEAMS_APP_ID}}`, `${{BOT_ID}}`, and `${{BOT_DOMAIN}}` in the manifest for values that change between environments. The M365 Agents Toolkit resolves these during packaging. For manual deployment, replace them with actual values before zipping. [learn.microsoft.com -- Agents Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-v4/teams-toolkit-fundamentals-vs) 10. Add `staticTabs` for personal-scope tab experiences. The two default entries (`conversations` and `about`) are recommended for all bots. Add `commands` inside bot entries for slash-command discoverability in the Teams compose box. [learn.microsoft.com -- Static tabs](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema#statictabs) @@ -146,6 +146,9 @@ const manifestWithExtensions = { ```typescript // Build script or manual steps to create the app package +// Preferred: atk package --env (resolves placeholders automatically) +// Manual steps below: + // 1. Ensure appPackage/ contains: // - manifest.json (with placeholders replaced) // - color.png (192x192 pixels) diff --git a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.environments.md b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.environments.md index ff514d4..c89b762 100644 --- a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.environments.md +++ b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.environments.md @@ -7,16 +7,17 @@ Multi-environment management with environment files, variable resolution, and th ## rules 1. **Environment files live in `env/`.** Each environment has a pair of files: `env/.env.{name}` for shared config and `env/.env.{name}.user` for personal/secret values. The `environmentFolderPath` in `m365agents.yml` points to this folder. -2. **Default environment is `dev`.** Scaffolded projects create `env/.env.dev` and `env/.env.dev.user`. Additional environments (staging, production) are created by running `teamsapp provision --env `. +2. **Default environment is `dev`.** Scaffolded projects create `env/.env.dev` and `env/.env.dev.user`. Additional environments (staging, production) are created by running `atk provision --env `. 3. **Variable syntax is `${{VAR_NAME}}`.** Both `manifest.json` and `m365agents.yml` use `${{VAR_NAME}}` placeholders. At build/provision/deploy time, the toolkit resolves them from the active environment's `.env` files. 4. **`SECRET_` prefix marks sensitive values.** Variables prefixed with `SECRET_` (e.g., `SECRET_BOT_PASSWORD`, `SECRET_AAD_APP_CLIENT_SECRET`) are stored only in `.env.*.user` files, which are gitignored. Never put `SECRET_` values in `.env.{name}`. 5. **`.env.*.user` files are gitignored by default.** The scaffold includes a `.gitignore` entry for `env/.env.*.user`. These files contain developer-specific credentials and secrets. Never commit them. 6. **Built-in environment variables are auto-populated.** Lifecycle actions write outputs to env files via `writeToEnvironmentFile`. Common auto-populated vars: `TEAMS_APP_ID`, `BOT_ID`, `SECRET_BOT_PASSWORD`, `AAD_APP_CLIENT_ID`, `SECRET_AAD_APP_CLIENT_SECRET`, `AAD_APP_OBJECT_ID`, `AAD_APP_TENANT_ID`. 7. **Azure resource variables must be set per environment.** `AZURE_SUBSCRIPTION_ID` and `AZURE_RESOURCE_GROUP_NAME` are required for provisioning. Set them in `.env.{name}` or pass via CLI/CI environment. -8. **Custom environments mirror the dev structure.** To create a staging environment, run `teamsapp provision --env staging`. This creates `env/.env.staging` and `env/.env.staging.user` with the same variable structure as dev but pointing to separate cloud resources. +8. **Custom environments mirror the dev structure.** To create a staging environment, run `atk provision --env staging`. This creates `env/.env.staging` and `env/.env.staging.user` with the same variable structure as dev but pointing to separate cloud resources. 9. **VS Code sidebar switches environments.** The Agents Toolkit VS Code extension shows a dropdown in the sidebar to switch the active environment. This changes which `.env.{name}` files are used for provision, deploy, and preview commands. -10. **Manifest placeholders resolve at package time.** When `teamsapp package` or `teamsApp/zipAppPackage` runs, all `${{VAR}}` placeholders in `manifest.json` are replaced with values from the active environment. The output zip contains a fully resolved manifest. +10. **Manifest placeholders resolve at package time.** When `atk package` or `teamsApp/zipAppPackage` runs, all `${{VAR}}` placeholders in `manifest.json` are replaced with values from the active environment. The output zip contains a fully resolved manifest. 11. **Environment-specific resource isolation.** Each environment should use separate Azure resource groups to avoid resource conflicts. Use naming conventions like `rg-mybot-dev`, `rg-mybot-staging`, `rg-mybot-prod`. +12. **`.localConfigs` is the runtime config for local development.** `atk deploy --env local` generates `.localConfigs` by reading values from `env/.env.local` and transforming them via `file/createOrUpdateEnvironmentFile` in `m365agents.local.yml`. Your app reads `.localConfigs` at runtime — NOT `env/.env.local`. If `TENANT_ID` is missing from `.localConfigs`, copy the tenant value from the source variable in `env/.env.local` (for example, `TEAMS_APP_TENANT_ID`) into `TENANT_ID`, or update the local lifecycle mapping so it writes `TENANT_ID` into `.localConfigs`. ## patterns @@ -38,7 +39,7 @@ project-root/ ```ini # env/.env.dev — shared config (safe to commit) -TEAMSFX_ENV=dev +APP_ENV=dev TEAMS_APP_NAME=MyBot-Dev TEAMS_APP_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx BOT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx @@ -86,20 +87,20 @@ SECRET_AAD_APP_CLIENT_SECRET=your-client-secret-here ```bash # Step 1: Provision creates the env files and cloud resources -teamsapp provision --env staging +atk provision --env staging -i false # This creates: -# env/.env.staging (with TEAMSFX_ENV=staging, resource IDs) +# env/.env.staging (with APP_ENV=staging, resource IDs) # env/.env.staging.user (with SECRET_* values) # Step 2: Set environment-specific overrides # Edit env/.env.staging to adjust resource names, domains, etc. # Step 3: Deploy to the new environment -teamsapp deploy --env staging +atk deploy --env staging -i false -# Step 4: Preview/test against a specific environment -teamsapp preview --env staging +# Step 4: Test against the new environment +# Use agentsplayground CLI or sideload in Teams ``` ### Pattern 4: Cross-Platform Environment Variables @@ -128,7 +129,7 @@ SLACK_SIGNING_SECRET=your-slack-signing-secret PORT=3978 ``` -> **Key difference from Toolkit-managed projects:** Standalone cross-platform examples use a single `.env` file (loaded via `dotenv`) instead of the `env/.env.dev` + `env/.env.dev.user` pair. This is intentional — these examples don't ship `m365agents.yml` or run `teamsapp provision`. +> **Key difference from Toolkit-managed projects:** Standalone cross-platform examples use a single `.env` file (loaded via `dotenv`) instead of the `env/.env.dev` + `env/.env.dev.user` pair. This is intentional — these examples don't ship `m365agents.yml` or run `atk provision`. ## pitfalls @@ -139,7 +140,7 @@ PORT=3978 - **Stale env files after re-provisioning** — If you delete cloud resources and re-provision, old IDs in env files may not update. Delete the env files and re-provision from scratch. - **`${{VAR}}` vs `${VAR}` confusion** — Agents Toolkit uses double-brace `${{VAR}}`. Shell-style `${VAR}` is not recognized and will not resolve. - **Confusing Toolkit `${{VAR}}` placeholders with Slack runtime env vars** — Toolkit placeholders resolve at package/provision time in manifest files. Slack env vars (`SLACK_BOT_TOKEN`, `SLACK_APP_TOKEN`) are read at runtime by `@slack/bolt`. They live in different worlds — don't put Slack tokens inside `${{}}` brackets in the manifest. -- **Missing variables at package time** — If a `${{VAR}}` in manifest.json has no matching env entry, packaging fails. Run `teamsapp validate` first to catch these. +- **Missing variables at package time** — If a `${{VAR}}` in manifest.json has no matching env entry, packaging fails. Run `atk validate` first to catch these. - **CI/CD without `.user` files** — In CI, secrets come from pipeline secrets, not `.user` files. Set `SECRET_*` vars as environment variables in the CI runner. ## references @@ -154,8 +155,8 @@ PORT=3978 Do a web search for: - "Microsoft 365 Agents Toolkit multi-environment env files configuration 2025" -- "teamsapp provision --env staging multiple environments" -- "Teams Toolkit SECRET_ prefix environment variables" +- "atk provision --env staging multiple environments" +- "Agents Toolkit SECRET_ prefix environment variables" Pair with: - `toolkit.lifecycle-cli.md` — lifecycle hooks that consume environment variables @@ -167,4 +168,4 @@ Pair with: Deep Research prompt: -"Write a micro expert on Microsoft 365 Agents Toolkit environment management (TypeScript). Cover env/.env.{name} and env/.env.{name}.user file pairs, ${{VAR}} variable resolution in manifest.json and m365agents.yml, SECRET_ prefix convention, built-in environment variables (TEAMS_APP_ID, BOT_ID, BOT_PASSWORD, AZURE_SUBSCRIPTION_ID), creating custom environments with teamsapp provision --env, VS Code sidebar environment switching, and CI/CD environment variable injection. Include canonical patterns for: environment file structure, manifest placeholder resolution, multi-environment setup." +"Write a micro expert on Microsoft 365 Agents Toolkit environment management (TypeScript). Cover env/.env.{name} and env/.env.{name}.user file pairs, ${{VAR}} variable resolution in manifest.json and m365agents.yml, SECRET_ prefix convention, built-in environment variables (TEAMS_APP_ID, BOT_ID, BOT_PASSWORD, AZURE_SUBSCRIPTION_ID), creating custom environments with atk provision --env, VS Code sidebar environment switching, and CI/CD environment variable injection. Include canonical patterns for: environment file structure, manifest placeholder resolution, multi-environment setup." diff --git a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.lifecycle-cli.md b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.lifecycle-cli.md index 46bce02..69b65d9 100644 --- a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.lifecycle-cli.md +++ b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.lifecycle-cli.md @@ -2,45 +2,41 @@ ## purpose -M365 Agents Toolkit lifecycle configuration (`m365agents.yml`) and full `teamsapp` CLI command reference for provisioning, deploying, and managing Teams agents. +M365 Agents Toolkit lifecycle configuration (`m365agents.yml`) and full `atk` CLI command reference for provisioning, deploying, and managing Teams agents. ## rules -1. **m365agents.yml is the lifecycle manifest.** Every Agents Toolkit project has an `m365agents.yml` at the project root. It defines the `provision`, `deploy`, and `publish` lifecycle stages — each stage is an ordered list of actions. +1. **m365agents.yml is the lifecycle manifest.** Every Agents Toolkit project has an `m365agents.yml` at the project root for dev/cloud deployment, and typically an `m365agents.local.yml` for local development. They define the `provision`, `deploy`, and `publish` lifecycle stages — each stage is an ordered list of actions. `atk provision --env local` runs `m365agents.local.yml`; `atk provision --env dev` runs `m365agents.yml`. 2. **Lifecycle stages run in order: provision → deploy → publish.** Provision creates cloud resources (Azure Bot, App Registration, resource groups). Deploy pushes app code to compute targets. Publish submits the app package to the Teams catalog. 3. **Actions use `uses:` for built-ins, `runs:` for custom scripts.** Built-in actions like `arm/deploy` or `teamsApp/create` are referenced with `uses: `. Custom shell commands use `runs: `. Both accept a `with:` block for parameters. -4. **Built-in actions cover the full lifecycle.** Key actions: `aadApp/create`, `aadApp/update`, `botAadApp/create`, `botFramework/create`, `arm/deploy`, `azureAppService/deploy`, `azureFunctions/deploy`, `teamsApp/create`, `teamsApp/update`, `teamsApp/validateManifest`, `teamsApp/zipAppPackage`. -5. **`environmentFolderPath`** in `m365agents.yml` points to the `env/` directory. Defaults to `./env`. All `${{VAR}}` placeholders resolve from the active environment's `.env.{name}` files. -6. **`teamsapp new` scaffolds a project.** Creates project structure with `m365agents.yml`, `env/` folder, `appPackage/`, and starter code. Supports `--template` for predefined templates and `--interactive false` for CI. -7. **`teamsapp provision` creates cloud resources.** Runs the `provision` stage in `m365agents.yml`. Accepts `--env ` to target a specific environment (default: `dev`). Creates resources defined by ARM templates or built-in actions. -8. **`teamsapp deploy` pushes code to cloud.** Runs the `deploy` stage. Builds the project, then deploys to the compute target (App Service, Functions, Container Apps). Always run `teamsapp provision` before first deploy. -9. **`teamsapp publish` submits to the org catalog.** Runs the `publish` stage. Packages the app and submits it to the Teams Admin Center for org-wide distribution. Requires admin approval after submission. -10. **`teamsapp validate` checks the manifest.** Validates `manifest.json` against the Teams schema before packaging. Catches missing fields, invalid scopes, and schema violations early. -11. **`teamsapp package` creates the app zip bundle.** Generates the `.zip` containing `manifest.json`, icons, and resolved placeholders. This is the artifact uploaded to Teams or Partner Center. -12. **`teamsapp preview` launches local testing.** Starts the Agents Playground for local testing without deploying to Teams. See `toolkit.playground-ts.md` for details. -13. **CI/CD integration uses `teamsapp` CLI with `--env` flags.** GitHub Actions and Azure Pipelines call `teamsapp provision --env staging` and `teamsapp deploy --env staging` in sequence. Store credentials in CI secrets, not in `.env.*.user` files. +4. **Built-in actions cover the full lifecycle.** Key actions: `aadApp/create`, `aadApp/update`, `botAadApp/create`, `botFramework/create`, `arm/deploy`, `azureAppService/zipDeploy`, `azureFunctions/zipDeploy`, `teamsApp/create`, `teamsApp/update`, `teamsApp/validateManifest`, `teamsApp/zipAppPackage`, `file/createOrUpdateEnvironmentFile`. The `aadApp/create` action **must include `generateServicePrincipal: true`** — without it, the service principal is not created and the bot gets `AADSTS7000229`. +5. **Use `m365agents.yml` to replace manual Azure portal setup.** A single `provision` stage automates what otherwise requires 10+ manual `az` CLI commands or Azure Portal steps: Entra ID App Registration (`aadApp/create`), bot identity and password (`botAadApp/create`), Bot Service with Teams channel (`botFramework/create`), ARM/Bicep resource deployment (`arm/deploy`), and Teams app registration (`teamsApp/create`). Each action writes its outputs (IDs, secrets) to env files automatically. For the full manual walkthrough these actions replace, see `../deploy/azure-bot-deploy-ts.md` rules 3–12. +6. **`environmentFolderPath`** in `m365agents.yml` points to the `env/` directory. Defaults to `./env`. All `${{VAR}}` placeholders resolve from the active environment's `.env.{name}` files. +7. **`atk new` scaffolds a project.** Creates project structure with `m365agents.yml`, `m365agents.local.yml`, `env/` folder, `appPackage/`, and starter code. Supports `--capability` for predefined templates and `-i false` for non-interactive mode. ATK CLI version must be > 1.1.5-beta — install with `npm i -g @microsoft/m365agentstoolkit-cli@beta`. +8. **`atk provision` creates cloud resources.** Runs the `provision` stage in the environment-specific YAML. Accepts `--env ` to target a specific environment (default: `dev`). Always add `-i false` for non-interactive execution. Creates resources defined by ARM templates or built-in actions. +9. **`atk deploy` pushes code to cloud or generates local config.** Runs the `deploy` stage. For cloud (`--env dev`), builds the project and deploys to Azure. For local (`--env local`), writes runtime credentials to `.localConfigs` via `file/createOrUpdateEnvironmentFile`. Always run `atk provision` before first deploy. +10. **`atk publish` submits to the org catalog.** Runs the `publish` stage. Packages the app and submits it to the Teams Admin Center for org-wide distribution. Requires admin approval after submission. +11. **`atk validate` checks the manifest.** Validates `manifest.json` against the Teams schema before packaging. Catches missing fields, invalid scopes, and schema violations early. +12. **`atk package` creates the app zip bundle.** Generates the `.zip` containing `manifest.json`, icons, and resolved placeholders. Use `atk package --env -i false`. This is the artifact uploaded to Teams or Partner Center. +13. **`atk preview` launches local testing.** Starts the Agents Playground for local testing without deploying to Teams. See `toolkit.playground-ts.md` for the recommended `agentsplayground` CLI alternative that requires no provisioning. +14. **CI/CD integration uses `atk` CLI with `--env` and `-i false` flags.** GitHub Actions and Azure Pipelines call `atk provision --env staging -i false` and `atk deploy --env staging -i false` in sequence. Store credentials in CI secrets, not in `.env.*.user` files. ## patterns -### Pattern 1: m365agents.yml anatomy +### Pattern 1: m365agents.yml anatomy (cloud deployment) ```yaml -# m365agents.yml — lifecycle configuration -version: v1.7 +# m365agents.yml — lifecycle configuration for dev/cloud +version: v1.11 environmentFolderPath: ./env provision: - - uses: aadApp/create + - uses: teamsApp/create with: - name: ${{AAD_APP_NAME}} - generateClientSecret: true - signInAudience: AzureADMultipleOrgs + name: ${{TEAMS_APP_NAME}} writeToEnvironmentFile: - clientId: AAD_APP_CLIENT_ID - clientSecret: SECRET_AAD_APP_CLIENT_SECRET - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID + teamsAppId: TEAMS_APP_ID - uses: botAadApp/create with: @@ -60,65 +56,131 @@ provision: writeToEnvironmentFile: botEndpoint: BOT_ENDPOINT - - uses: teamsApp/create + - uses: teamsApp/zipAppPackage with: - name: ${{TEAMS_APP_NAME}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID + manifestPath: ./appPackage/manifest.json + outputZipPath: ./appPackage/build/appPackage.${{APP_ENV}}.zip + outputFolder: ./appPackage/build + + - uses: teamsApp/update + with: + appPackagePath: ./appPackage/build/appPackage.${{APP_ENV}}.zip deploy: - - uses: azureAppService/deploy + - uses: cli/runNpmCommand + with: + args: install + - uses: azureAppService/zipDeploy with: artifactFolder: . resourceId: ${{AZURE_APP_SERVICE_RESOURCE_ID}} +``` -publish: - - uses: teamsApp/validateManifest +### Pattern 1b: m365agents.local.yml anatomy (local development) + +```yaml +# m365agents.local.yml — lifecycle configuration for local +version: v1.11 + +provision: + - uses: teamsApp/create with: - manifestPath: ./appPackage/manifest.json + name: ${{TEAMS_APP_NAME}}-local-debug + writeToEnvironmentFile: + teamsAppId: TEAMS_APP_ID - - uses: teamsApp/zipAppPackage + - uses: aadApp/create with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip - outputFolder: ./appPackage/build + name: ${{CONFIG__MANIFEST__NAME}}-aad + generateClientSecret: true + generateServicePrincipal: true # REQUIRED — without this, AADSTS7000229 + signInAudience: AzureADMultipleOrgs + writeToEnvironmentFile: + clientId: BOT_ID + clientSecret: SECRET_BOT_PASSWORD + objectId: BOT_OBJECT_ID + tenantId: TEAMS_APP_TENANT_ID - - uses: teamsApp/update + - uses: botFramework/create with: - appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + botId: ${{BOT_ID}} + name: ${{CONFIG__MANIFEST__NAME}} + messagingEndpoint: ${{BOT_ENDPOINT}}/api/messages + description: "" # Required field — omitting causes schema error + channels: + - name: msteams + +deploy: + - uses: file/createOrUpdateEnvironmentFile + with: + target: ./.localConfigs + envs: + PORT: 3978 + CLIENT_ID: ${{BOT_ID}} + CLIENT_SECRET: ${{SECRET_BOT_PASSWORD}} + TENANT_ID: ${{TEAMS_APP_TENANT_ID}} ``` -### Pattern 2: CLI command reference +> **Critical:** `.localConfigs` is what your app reads at runtime, NOT `env/.env.local`. The `file/createOrUpdateEnvironmentFile` action transforms env vars from `env/.env.local` into `.localConfigs`. In the example above, `.localConfigs` `TENANT_ID` comes from `TEAMS_APP_TENANT_ID` in `env/.env.local`. If `TENANT_ID` is missing from `.localConfigs` after deploy, copy the value from `TEAMS_APP_TENANT_ID` in `env/.env.local`. + +### Pattern 2: Manual steps replaced by m365agents.yml + +Each `provision` action in `m365agents.yml` replaces one or more manual Azure CLI / Portal steps. This table maps them: + +| `m365agents.yml` action | Manual equivalent it replaces | What gets auto-created | +|---|---|---| +| `aadApp/create` | Azure Portal → App Registrations → New registration, or `az ad app create` + `az ad app credential reset` | Entra ID App with client ID + secret, written to env | +| `botAadApp/create` | `az ad app create` (separate bot identity) + `az ad app credential reset` | Bot-specific App ID + password, written to env | +| `botFramework/create` | `az bot create --app-type SingleTenant` + `az bot msteams create` | Azure Bot Service resource with Teams channel connected | +| `arm/deploy` | `az group create` + `az webapp create` + `az webapp config appsettings set` (or equivalent for Functions/Container Apps) | All Bicep/ARM resources (App Service, plan, settings) | +| `teamsApp/create` | Teams client → Apps → Upload a custom app, or Teams Admin Center upload | Teams app registration with `TEAMS_APP_ID` | +| `azureAppService/zipDeploy` | `az webapp deploy --src-path ` | Code deployed to App Service | +| `teamsApp/zipAppPackage` | Manually zip `manifest.json` + icons with resolved placeholders | App package `.zip` ready for sideload or publishing | + +> **Bottom line:** `atk provision` + `atk deploy` replaces steps 3–12 in `../deploy/azure-bot-deploy-ts.md`. Two commands instead of ten. + +### Pattern 3: CLI command reference ```bash +# Check CLI version (must be > 1.1.5-beta) +atk --version + +# Install / update CLI +npm i -g @microsoft/m365agentstoolkit-cli@beta + # Scaffold a new project -teamsapp new # Interactive wizard -teamsapp new --template ai-bot --interactive false # Non-interactive +atk new # Interactive wizard +atk new -c ai-bot -l typescript -i false # Non-interactive # Provision cloud resources -teamsapp provision # Uses default env (dev) -teamsapp provision --env staging # Target specific env +atk provision --env dev -i false # Uses m365agents.yml +atk provision --env local -i false # Uses m365agents.local.yml +atk provision --env dev --resource-group --region -i false # Azure resources -# Deploy application code -teamsapp deploy # Deploy to default env -teamsapp deploy --env production # Deploy to production +# Deploy application code / generate .localConfigs +atk deploy --env dev -i false # Deploy to Azure +atk deploy --env local -i false # Generate .localConfigs # Validate and package -teamsapp validate --manifest-path ./appPackage/manifest.json -teamsapp package --manifest-path ./appPackage/manifest.json \ - --output-zip-path ./build/appPackage.zip +atk validate --env dev -i false +atk package --env dev -i false # Publish to org catalog -teamsapp publish +atk publish --env dev -i false # Local preview / Agents Playground -teamsapp preview +atk preview # Update an existing Teams app registration -teamsapp update +atk update + +# Auth management +atk auth login m365 +atk auth login azure +atk auth list ``` -### Pattern 3: GitHub Actions CI/CD pipeline +### Pattern 4: GitHub Actions CI/CD pipeline ```yaml # .github/workflows/deploy.yml @@ -140,10 +202,10 @@ jobs: - run: npm ci - name: Install Agents Toolkit CLI - run: npm install -g @microsoft/teamsapp-cli + run: npm install -g @microsoft/m365agentstoolkit-cli - name: Provision - run: teamsapp provision --env production + run: atk provision --env production -i false env: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} AZURE_RESOURCE_GROUP_NAME: ${{ secrets.AZURE_RESOURCE_GROUP_NAME }} @@ -152,18 +214,18 @@ jobs: M365_ACCOUNT_PASSWORD: ${{ secrets.M365_ACCOUNT_PASSWORD }} - name: Deploy - run: teamsapp deploy --env production + run: atk deploy --env production -i false env: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} ``` -### Pattern 4: Cross-Platform Projects (no m365agents.yml) +### Pattern 5: Cross-Platform Projects (no m365agents.yml) Standalone cross-platform examples (Teams + Slack) can skip `m365agents.yml` entirely. These projects: - Use a single `.env` file at the project root (loaded via `dotenv`) instead of `env/.env.{name}` pairs - Still include `appPackage/manifest.json` for sideloading into Teams -- Run with `tsx watch` or `node` directly — no `teamsapp provision` or `teamsapp deploy` needed +- Run with `tsx watch` or `node` directly — no `atk provision` or `atk deploy` needed - Manage Azure resources manually (Bot Registration, App Service) rather than through lifecycle actions ``` @@ -180,7 +242,7 @@ cross-platform-bot/ └── tsconfig.json # extends @microsoft/teams.config/tsconfig.node.json ``` -> **When to add `m365agents.yml`:** Only when you want `teamsapp provision` / `teamsapp deploy` to manage Azure resources automatically. For teaching examples and local development, manual `.env` + sideloading is simpler. +> **When to add `m365agents.yml`:** Only when you want `atk provision` / `atk deploy` to manage Azure resources automatically. For teaching examples and local development, manual `.env` + sideloading is simpler. ## pitfalls @@ -190,8 +252,14 @@ cross-platform-bot/ - **Using `runs:` for what `uses:` handles** — Built-in actions handle auth, retries, and environment writes automatically. Only use `runs:` for truly custom steps. - **Committing `.env.*.user` files** — These contain secrets (`SECRET_*` vars). They're gitignored by default — don't override this. - **Missing `--env` in CI** — Without `--env`, the CLI uses the `dev` environment. Production pipelines must specify `--env production` explicitly. -- **Confusing `teamsapp` with `teamsfx`** — The old CLI was `teamsfx`. The current CLI is `teamsapp`. If docs reference `teamsfx`, translate to `teamsapp`. +- **Confusing `atk` with legacy CLI names** — The CLI was previously called `teamsfx`, then `teamsapp`. The current CLI is `atk` (installed as `@microsoft/m365agentstoolkit-cli`). If docs or examples reference `teamsfx` or `teamsapp`, translate to `atk`. - **ARM template parameter mismatches** — `arm/deploy` parameters must match the Bicep/ARM template's expected inputs. Mismatches cause silent failures during provisioning. +- **Missing `generateServicePrincipal: true` in `aadApp/create`** — Without this field, no service principal is created. The bot gets `AADSTS7000229` at runtime. Always include it in the local YAML's `aadApp/create` action. +- **`TENANT_ID` not written to `.localConfigs`** — The `file/createOrUpdateEnvironmentFile` may not include `TENANT_ID`. Without it, the SDK acquires tokens from the wrong authority, causing 401 from Bot Connector. Copy from `env/.env.local` if missing. +- **Devtunnel URL blacklisted after repeated 401s** — Bot Framework may cache a failing tunnel URL. Even after fixing auth, the bot still gets 401. Create a fresh devtunnel, update `BOT_ENDPOINT`, and re-provision. +- **`outputJsonPath` in `teamsApp/zipAppPackage`** — This field does not exist. Use `outputFolder` instead. Using the wrong field causes a silent schema validation error. +- **Missing `description: ""` in `botFramework/create`** — This field is required. Omitting it causes a YAML schema validation error during provisioning. +- **Using `botAadApp/create` in local YAML** — `botAadApp/create` is for cloud (`m365agents.yml`). Local templates use `aadApp/create` + `botFramework/create` instead. ## references @@ -200,18 +268,18 @@ cross-platform-bot/ - [Provision cloud resources](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/provision) - [Deploy to Azure](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/deploy) - [CI/CD with Agents Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-v4/use-cicd-template-v4) -- [teamsapp CLI reference](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-cli) +- [ATK CLI reference](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-cli) ## instructions Do a web search for: - "Microsoft 365 Agents Toolkit m365agents.yml lifecycle configuration 2025" -- "teamsapp CLI provision deploy publish commands reference" +- "atk CLI provision deploy publish commands reference" - "Agents Toolkit CI/CD GitHub Actions Azure Pipelines" Pair with: -- `project.scaffold-files-ts.md` — project scaffolding (what `teamsapp new` creates) +- `project.scaffold-files-ts.md` — project scaffolding (what `atk new` creates) - `../deploy/azure-bot-deploy-ts.md` — manual Azure deployment as alternative to Agents Toolkit - `toolkit.environments.md` — environment files consumed by lifecycle hooks - `toolkit.publish.md` — detailed publishing workflow @@ -220,4 +288,4 @@ Pair with: Deep Research prompt: -"Write a micro expert on Microsoft 365 Agents Toolkit lifecycle management (TypeScript). Cover m365agents.yml anatomy, teamsapp CLI commands (new, provision, deploy, publish, validate, package, preview, update), built-in actions (arm/deploy, azureAppService/deploy, aadApp/create, botAadApp/create, teamsApp/create, teamsApp/validateManifest, teamsApp/zipAppPackage), uses: vs runs: hooks, writeToEnvironmentFile, CI/CD integration with GitHub Actions and Azure Pipelines. Include canonical patterns for: complete m365agents.yml config, CLI command reference cheat sheet, GitHub Actions deployment pipeline." +"Write a micro expert on Microsoft 365 Agents Toolkit lifecycle management (TypeScript). Cover m365agents.yml anatomy, atk CLI commands (new, provision, deploy, publish, validate, package, preview, update), built-in actions (arm/deploy, azureAppService/deploy, aadApp/create, botAadApp/create, teamsApp/create, teamsApp/validateManifest, teamsApp/zipAppPackage), uses: vs runs: hooks, writeToEnvironmentFile, CI/CD integration with GitHub Actions and Azure Pipelines. Include canonical patterns for: complete m365agents.yml config, CLI command reference cheat sheet, GitHub Actions deployment pipeline." diff --git a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.playground-ts.md b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.playground-ts.md index 530351b..d6d5925 100644 --- a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.playground-ts.md +++ b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.playground-ts.md @@ -6,15 +6,15 @@ Agents Playground — the local web-based test harness for testing Teams agents ## rules -1. **Agents Playground is a local web UI for testing.** It provides a browser-based chat interface that simulates a Teams conversation. No Teams client or sideloading required for basic message testing. -2. **Start with `teamsapp preview`.** The CLI command starts the local bot server and opens the Agents Playground in the default browser. Alternatively, use the VS Code command palette: "Agents Toolkit: Preview". +1. **Agents Playground is a local web UI for testing.** It provides a browser-based chat interface that simulates a Teams conversation. No Teams client, sideloading, or M365 account required. Recommend Agents Playground first for testing — use Teams only when the user explicitly requests it. +2. **Use the `agentsplayground` CLI to start.** Install with `winget install agentsplayground` (Windows), or `npm install -g @microsoft/m365agentsplayground`. Start with `agentsplayground -e http://localhost:3978/api/messages -c msteams`. The `atk preview` command is an alternative that also opens the playground. 3. **`.m365agentsplayground.yml` configures the playground.** This optional config file in the project root customizes playground behavior — bot endpoint URL, display settings, and test scenarios. 4. **The playground connects to your local bot endpoint.** By default it connects to `http://localhost:3978/api/messages` (or whatever port your bot runs on). Ensure your bot server is running before or alongside the playground. 5. **Send messages to test conversation flows.** Type messages in the playground chat to simulate user input. The bot processes them through the same handler pipeline as in production Teams. 6. **Card actions work in the playground.** Adaptive Card actions (submit, execute) are supported. Test card interactions without deploying to Teams. 7. **Activity simulation for advanced testing.** The playground can simulate Teams-specific activities like `conversationUpdate` (member added/removed), `messageReaction`, and `invoke` activities that are hard to trigger manually. 8. **The playground does NOT replace Teams client testing.** It simulates core messaging and card interactions but does not support: SSO/OAuth popups, message extensions, task modules, meeting-specific features, or the full Teams app manifest experience. Always do a final validation in the real Teams client. -9. **`teamsapp preview --env ` uses environment-specific config.** The preview command loads environment variables from the specified env files, allowing you to test against different configurations. +9. **`agentsplayground` supports environment-specific config.** Pass `--client-id`, `--client-secret`, and `--tenant-id` flags to test authenticated agents, or use `--channel-id` to emulate different channels (`msteams`, `emulator`, `webchat`, `directline`). 10. **Hot reload works with the playground.** If your bot server supports hot reload (e.g., `nodemon` or `tsx watch`), changes to bot code are reflected immediately without restarting the playground. ## patterns @@ -22,18 +22,13 @@ Agents Playground — the local web-based test harness for testing Teams agents ### Pattern 1: Starting Agents Playground ```bash -# Option 1: CLI — starts bot + opens playground -teamsapp preview +# Option 1: agentsplayground CLI (recommended — no provisioning needed) +npm run dev # Start bot in background +agentsplayground -e http://localhost:3978/api/messages -c msteams # New terminal -# Option 2: CLI — target a specific environment -teamsapp preview --env dev - -# Option 3: Start bot separately, then preview -npm run dev # Start bot server on localhost:3978 -teamsapp preview # Opens playground, connects to running bot - -# Option 4: VS Code command palette -# > Agents Toolkit: Preview +# Option 2: With authentication credentials +agentsplayground -e http://localhost:3978/api/messages -c msteams \ + --client-id --client-secret --tenant-id ``` ### Pattern 2: .m365agentsplayground.yml configuration @@ -65,8 +60,7 @@ testScenarios: { "scripts": { "dev": "tsx watch src/index.ts", - "preview": "teamsapp preview", - "dev:playground": "concurrently \"npm run dev\" \"npm run preview\"" + "playground": "agentsplayground -e http://localhost:3978/api/messages -c msteams" } } ``` @@ -92,7 +86,6 @@ app.message(/.*/, async (ctx) => { const port = process.env.PORT || 3978; app.listen(port, () => { console.log(`Bot running at http://localhost:${port}`); - console.log(`Run "teamsapp preview" to open Agents Playground`); }); ``` @@ -102,7 +95,7 @@ app.listen(port, () => { - **Wrong port in playground config** — If your bot runs on a non-default port, update `.m365agentsplayground.yml` or the `BOT_ENDPOINT` env variable. - **Testing SSO in the playground** — OAuth/SSO flows require the real Teams client. The playground cannot simulate the Teams SSO token exchange. Use the playground for message/card testing, Teams client for auth flows. - **Assuming playground = Teams client** — Message extensions, task modules, meeting features, and app installation flows are not available in the playground. Always validate in Teams before publishing. -- **Forgetting `--env` for environment-specific testing** — Without `--env`, preview uses the default dev environment. If you need staging credentials or endpoints, specify the environment. +- **Forgetting `--env` for environment-specific testing** — Without `--env`, `atk preview` uses the default dev environment. For the `agentsplayground` CLI, pass auth credentials explicitly via `--client-id`, `--client-secret`, `--tenant-id`. - **Firewall blocking localhost** — Some corporate networks block local WebSocket connections. If the playground can't connect, check firewall rules for localhost ports. - **Hot reload not configured** — Without `tsx watch` or `nodemon`, code changes require manual server restart. Set up hot reload for efficient playground development. - **Card rendering differences** — Adaptive Card rendering in the playground may differ slightly from the Teams client. Complex card layouts should be verified in Teams. @@ -110,7 +103,7 @@ app.listen(port, () => { ## references - [Test with Agents Playground](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/debug-overview) -- [teamsapp preview command](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-cli) +- [ATK preview command](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-cli) - [Local debug overview](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/debug-overview) - [Agents Toolkit VS Code extension](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/install-teams-toolkit) @@ -119,12 +112,12 @@ app.listen(port, () => { Do a web search for: - "Microsoft 365 Agents Playground local testing Teams bot 2025" -- "teamsapp preview Agents Playground configuration" +- "atk preview Agents Playground configuration" - ".m365agentsplayground.yml configuration options" Pair with: - `dev.debug-test-ts.md` — broader debugging and testing patterns -- `toolkit.lifecycle-cli.md` — `teamsapp preview` is part of the CLI command set +- `toolkit.lifecycle-cli.md` — `atk preview` is part of the CLI command set - `toolkit.environments.md` — playground uses environment-specific config - `runtime.app-init-ts.md` — bot entry point that playground connects to @@ -132,4 +125,4 @@ Pair with: Deep Research prompt: -"Write a micro expert on Microsoft 365 Agents Playground for testing Teams bots locally (TypeScript). Cover what the playground is, how to start it (teamsapp preview, VS Code command), .m365agentsplayground.yml configuration, testing capabilities (messages, card actions, activity simulation), limitations vs real Teams client (no SSO, no message extensions, no task modules), hot reload workflow, and environment-specific preview. Include canonical patterns for: starting the playground, playground config file, local dev workflow with concurrent bot server and playground." +"Write a micro expert on Microsoft 365 Agents Playground for testing Teams bots locally (TypeScript). Cover what the playground is, how to start it (atk preview, VS Code command), .m365agentsplayground.yml configuration, testing capabilities (messages, card actions, activity simulation), limitations vs real Teams client (no SSO, no message extensions, no task modules), hot reload workflow, and environment-specific preview. Include canonical patterns for: starting the playground, playground config file, local dev workflow with concurrent bot server and playground." diff --git a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.publish.md b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.publish.md index b83436d..636580a 100644 --- a/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.publish.md +++ b/skills/microsoft-365-agents-toolkit/experts/teams/toolkit.publish.md @@ -8,15 +8,15 @@ Publishing workflow for Teams agents — from local sideloading through org cata 1. **Three publishing stages: sideload → org catalog → Teams Store.** Each stage expands the audience. Sideload is developer-only. Org catalog reaches your tenant. Teams Store is public to all Teams users. 2. **Sideloading is for development and testing.** Upload the app package directly in Teams (`Apps → Manage your apps → Upload a custom app`). No admin approval needed, but only you can see the app. Requires "Upload custom apps" policy to be enabled. -3. **`teamsapp publish` submits to the org catalog.** The command packages the app and submits it to the Teams Admin Center. An admin must approve the submission before the app appears in the org's app catalog. -4. **Admin approval happens in Teams Admin Center.** After `teamsapp publish`, admins review the submission at `admin.teams.microsoft.com → Teams apps → Manage apps`. They can approve, reject, or request changes. -5. **`teamsapp validate` catches manifest errors before publishing.** Always validate before publishing. The command checks the manifest against the Teams schema, verifies required fields, and flags common issues. Fix all validation errors before submitting. -6. **`teamsapp package` creates the submission artifact.** Generates a `.zip` bundle containing the resolved `manifest.json` and icon files. This is the file that gets uploaded to the org catalog or Partner Center. +3. **`atk publish` submits to the org catalog.** The command packages the app and submits it to the Teams Admin Center. An admin must approve the submission before the app appears in the org's app catalog. +4. **Admin approval happens in Teams Admin Center.** After `atk publish`, admins review the submission at `admin.teams.microsoft.com → Teams apps → Manage apps`. They can approve, reject, or request changes. +5. **`atk validate` catches manifest errors before publishing.** Always validate before publishing. The command checks the manifest against the Teams schema, verifies required fields, and flags common issues. Fix all validation errors before submitting. +6. **`atk package` creates the submission artifact.** Generates a `.zip` bundle containing the resolved `manifest.json` and icon files. This is the file that gets uploaded to the org catalog or Partner Center. 7. **Version bumping is required for updates.** When publishing an update to an already-published app, increment the `version` field in `manifest.json`. The org catalog and Teams Store reject submissions with the same version as an existing entry. -8. **`teamsapp update` pushes changes to an existing Teams app.** Updates the app registration without creating a new one. Use this after changing manifest properties, bot endpoints, or permissions. +8. **`atk update` pushes changes to an existing Teams app.** Updates the app registration without creating a new one. Use this after changing manifest properties, bot endpoints, or permissions. 9. **Teams Store submission goes through Partner Center.** To publish publicly, submit the app package at `partner.microsoft.com`. Microsoft reviews the app against validation policies (functionality, security, compliance). Review takes 1-2+ weeks. 10. **Teams Store validation requirements are strict.** The app must: work correctly in all declared scopes, handle errors gracefully, not crash or hang, follow Teams design guidelines, include privacy policy and terms of use URLs, and pass automated testing. -11. **Pre-submission checklist.** Before any publishing: validate manifest (`teamsapp validate`), test in real Teams client (not just playground), verify all URLs are HTTPS and reachable, confirm icons meet size requirements (192x192 color, 32x32 outline), and ensure the app works in all declared scopes (personal, team, groupChat). +11. **Pre-submission checklist.** Before any publishing: validate manifest (`atk validate`), test in real Teams client (not just playground), verify all URLs are HTTPS and reachable, confirm icons meet size requirements (192x192 color, 32x32 outline), and ensure the app works in all declared scopes (personal, team, groupChat). 12. **App update propagation varies by stage.** Sideloaded updates are immediate. Org catalog updates require admin re-approval. Teams Store updates require Microsoft re-review. ## patterns @@ -25,15 +25,15 @@ Publishing workflow for Teams agents — from local sideloading through org cata ```bash # Step 1: Validate the manifest -teamsapp validate --manifest-path ./appPackage/manifest.json +atk validate --manifest-path ./appPackage/manifest.json # Fix any reported errors before continuing # Step 2: Package the app -teamsapp package --manifest-path ./appPackage/manifest.json \ +atk package --manifest-path ./appPackage/manifest.json \ --output-zip-path ./build/appPackage.zip # Step 3: Publish to org catalog (submits for admin approval) -teamsapp publish +atk publish --env dev -i false # Step 4: Notify your Teams admin to approve in Admin Center # admin.teams.microsoft.com → Teams apps → Manage apps → search for your app @@ -49,17 +49,17 @@ teamsapp publish # After: "version": "1.1.0" # Step 2: Validate the updated manifest -teamsapp validate --manifest-path ./appPackage/manifest.json +atk validate --manifest-path ./appPackage/manifest.json # Step 3: Update the Teams app registration -teamsapp update +atk update # Step 4: Re-package with the new version -teamsapp package --manifest-path ./appPackage/manifest.json \ +atk package --manifest-path ./appPackage/manifest.json \ --output-zip-path ./build/appPackage.zip # Step 5: Re-publish (triggers admin re-approval for org catalog) -teamsapp publish +atk publish ``` ### Pattern 3: Manifest fields required for publishing @@ -111,12 +111,12 @@ teamsapp publish ## pitfalls -- **Publishing without validating first** — `teamsapp validate` catches schema errors, missing fields, and invalid URLs. Skipping it means surprises during admin review or Store rejection. +- **Publishing without validating first** — `atk validate` catches schema errors, missing fields, and invalid URLs. Skipping it means surprises during admin review or Store rejection. - **Same version number on update** — The org catalog and Store reject duplicate versions. Always bump `version` in manifest.json before re-publishing. - **Missing privacy/terms URLs** — Required for Teams Store submission. Org catalog may accept without them, but add them early to avoid rework. - **Icons wrong size or format** — Color icon must be 192x192 PNG. Outline icon must be 32x32 PNG with only white and transparent pixels. Wrong sizes cause validation failure. - **Not testing in all declared scopes** — If manifest declares `personal`, `team`, and `groupChat` scopes, the app must work correctly in all three. Store review tests all declared scopes. -- **Forgetting admin approval step** — `teamsapp publish` only submits. The app isn't available until an admin approves it in the Teams Admin Center. Plan for this delay. +- **Forgetting admin approval step** — `atk publish` only submits. The app isn't available until an admin approves it in the Teams Admin Center. Plan for this delay. - **Testing only in playground before publishing** — The playground doesn't cover SSO, message extensions, or Teams-specific behaviors. Always do a full sideload test in the real Teams client. - **Partner Center submission without meeting all policies** — Microsoft's validation checks functionality, security, performance, and compliance. Read the [validation guidelines](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines) before submitting. @@ -126,7 +126,7 @@ teamsapp publish - [Publish to org catalog](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload) - [Submit to Teams Store](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/publish) - [Teams Store validation guidelines](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines) -- [teamsapp publish command](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-cli) +- [ATK publish command](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-cli) - [App manifest schema](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema) ## instructions @@ -134,7 +134,7 @@ teamsapp publish Do a web search for: - "Microsoft Teams app publishing org catalog admin approval 2025" -- "teamsapp publish validate package CLI commands" +- "atk publish validate package CLI commands" - "Teams Store submission Partner Center validation requirements" Pair with: @@ -147,4 +147,4 @@ Pair with: Deep Research prompt: -"Write a micro expert on Microsoft Teams app publishing workflow (TypeScript). Cover the three publishing stages (sideload, org catalog, Teams Store), teamsapp publish / validate / package / update commands, admin approval flow in Teams Admin Center, Partner Center submission for Teams Store, validation requirements (manifest schema, icons, scopes, privacy/terms URLs), version bumping for updates, and the complete pre-submission checklist. Include canonical patterns for: org catalog publishing steps, app update workflow, manifest fields required for Store submission." +"Write a micro expert on Microsoft Teams app publishing workflow (TypeScript). Cover the three publishing stages (sideload, org catalog, Teams Store), atk publish / validate / package / update commands, admin approval flow in Teams Admin Center, Partner Center submission for Teams Store, validation requirements (manifest schema, icons, scopes, privacy/terms URLs), version bumping for updates, and the complete pre-submission checklist. Include canonical patterns for: org catalog publishing steps, app update workflow, manifest fields required for Store submission." diff --git a/skills/microsoft-365-agents-toolkit/slack-to-teams/SKILL.md b/skills/microsoft-365-agents-toolkit/slack-to-teams/SKILL.md index e2d4001..8db310b 100644 --- a/skills/microsoft-365-agents-toolkit/slack-to-teams/SKILL.md +++ b/skills/microsoft-365-agents-toolkit/slack-to-teams/SKILL.md @@ -166,3 +166,4 @@ Reference guides for side-by-side platform comparison: - [Advanced Features](../docs/advanced-features.md) - [Feature Gaps](../docs/feature-gaps.md) - [Workflow Scenarios](../docs/workflows.md) — Message-native workflow patterns (triggers, state, logic, AI, visibility) for Teams bots +- [Migration Guide](../docs/migration-guide.md) — Step-by-step guide for migrating Slack bots and Line of Business apps to Teams (or dual-platform), covering planning through deployment