Tag: Power Platform

  • Copilot Cowork Prompt of the Day: Real Microsoft 365 Workflows That Actually Save Time

    Copilot Cowork Prompt of the Day: Real Microsoft 365 Workflows That Actually Save Time

    Copilot Cowork Prompt of the Day: Real Microsoft 365 Workflows That Actually Save Time

    I have been testing Copilot Cowork across real work patterns inside Microsoft 365: meetings, calendar cleanup, files, time entries, customer feedback, follow-ups, and workspace history.

    The pattern is becoming clear.

    The strongest Copilot Cowork prompts do not just ask for an answer. They assign a business outcome. They define the source of truth. They set guardrails. They tell Cowork what finished work should look like.

    That is where this gets serious.

    Below is a practical prompt library based on my Copilot Cowork Prompt of the Day posts across X and LinkedIn. I grouped them by scenario so the examples are easier to scan, reuse, and adapt.

    Note: Some examples use demo companies, files, customers, and project names. Replace those with your own Microsoft 365 content, folders, meetings, and business context.

    Table of Contents

    Calendar and Focus Management

    Calendar work looks simple until it eats your day. Declining meetings, cancelling organizer-owned events, protecting focus time, and finding clean openings are perfect examples of work that should be delegated.

    These prompts show Cowork acting like a real calendar operator, not a passive chatbot.

    Decline and Cancel Holiday Meetings

    The situation

    Friday is a holiday. Your calendar still has meetings. Some meetings were created by other people. Some meetings may be yours. You need everything cleaned up properly.

    The important part is the distinction between declining and cancelling. If you are only an attendee, Cowork should decline the meeting. If you are the organizer, Cowork should cancel it and send a note so attendees know why it disappeared.

    Copilot Cowork using calendar management to decline meetings and cancel organizer-owned meetings for a holiday.

    The prompt

    [Day] is a holiday. Check [Date].
    - Decline every meeting.
    - If I’m the organizer, cancel it and send a note.
    Use /calendar-management

    What Cowork should do

    • Check the target date.
    • Find every meeting on that day.
    • Decline meetings where you are an attendee.
    • Cancel meetings where you are the organizer.
    • Send a professional cancellation note where needed.
    • Summarize what changed.

    This is the kind of task that burns attention. The value is not only the minutes saved. The real value is that Cowork understands the difference between attendee action and organizer responsibility.

    Cancelling a meeting you own sends a different signal than declining a meeting someone else owns.

    How I would tighten the prompt

    For a production-style version, I would add the wording for the cancellation note directly into the prompt.

    Friday is a company holiday. Check April 3rd in my calendar.
    For every meeting that day:
    - If I am only an attendee, decline the meeting.
    - If I am the organizer, cancel the meeting.
    - For cancelled meetings, send this note:
    “April 3rd is a holiday, so I’m cancelling this meeting.
    Please reschedule for the following week if still needed.”
    After you finish, send me a summary grouped by declined meetings
    and cancelled meetings.
    Use /calendar-management

    Create Focus Time from Your Phone

    The situation

    This one is simple. That is why it matters.

    I used the iOS app from bed and told Cowork to find two separate one-hour focus blocks for Monday morning. Cowork checked my calendar, found the openings, and created both events.

    No desktop. No calendar hunting. No dragging blocks around half asleep.

    The prompt

    Set some focus time for me up for Monday morning.
    Find 2 separate 1 hour blocks so I can focus on:
    1) <Task>
    2) <Task>

    What Cowork should do

    • Review your Monday morning calendar.
    • Find two separate one-hour openings.
    • Create calendar events for each focus block.
    • Name each block clearly based on the task.
    • Add useful context where available.

    Focus time only helps if it actually lands on the calendar. A lot of people know what they need to work on, then lose the day to meetings, messages, and context switching.

    This turns focus protection into a command.

    That is the kind of small task agents should crush first. Scheduling. Calendar juggling. Protecting time. Removing the coordination mess.

    How I would tighten the prompt

    I would add preferred working hours, meeting buffer rules, and event details.

    Set up 2 separate 1-hour focus blocks for Monday morning.
    Focus areas:
    1) <Task 1>
    2) <Task 2>
    Rules:
    - Only schedule between 8:00 AM and 12:00 PM.
    - Do not overlap existing meetings.
    - Leave at least 15 minutes between meetings and focus blocks where possible.
    - Use clear calendar titles: “Focus: <Task>”.
    - Add a short note to each event with the goal for that focus block.
    After scheduling, tell me the times you picked.

    ↑ Back to top


    Time Entry and Work Reporting

    Time entry is one of the best Cowork use cases because the evidence already exists across Microsoft 365. Meetings, chats, emails, files, edits, and shared work all tell the story of the day.

    The hard part is turning that messy activity trail into believable time-entry comments that a human can review.

    Build a Daily Time Entry Summary from Microsoft 365 Activity

    The situation

    This prompt asks Cowork to review the day’s Microsoft 365 activity and produce a structured time-entry draft. The goal is not perfect accounting. The goal is a practical, honest draft that can be reviewed and corrected quickly.

    The real power is that Cowork is not only looking at meetings. It is asked to look across calendar activity, Teams chats, email, files, transcripts, meeting notes, and other signals.

    Daily time entry draft created from Microsoft 365 work activity.

    The prompt

    Review ALL of MY Microsoft 365 work activity from TODAY in
    [your timezone] and build a realistic, structured daily time entry
    summary.
    Then send it as a [direct Teams message / Email].
    Use every available signal from today:
    - calendar meetings
    - transcripts and recaps
    - meeting chats
    - Teams chats and channel messages
    - emails
    - files opened, edited, or shared
    - any other work activity signals
    Rules:
    1. Only use today in my local timezone.
    2. Look across all evidence, not just meetings.
    3. Infer the best-fit project, client, internal initiative, or business
    development category.
    4. Map work to a project whenever possible.
    5. If unclear, use: Business Development, Internal Operations,
    Practice Development, Admin, or Learning / Enablement.
    6. Consolidate fragmented activity into meaningful work blocks.
    7. Target a full day close to 8.0 hours.
    8. Acceptable total range: 6.0-8.0 hours.
    9. Accuracy first, then use reasonable consolidation to close gaps.
    10. Do not invent fake meetings, deliverables, or project names.
    11. If evidence is weak, make the best possible mapping, but keep
    descriptions honest.
    12. Avoid over-fragmenting. Prefer fewer, stronger entries.
    13. Write descriptions like real time-entry comments, not AI summaries.
    14. Keep descriptions concise but useful.
    15. Group short related activities under the same project.
    16. If there is clear prep or follow-up around meetings, emails,
    chats, or docs, include that under the relevant project when evidence
    supports it.
    17. Capture business development work where relevant:
    sales support, proposal work, internal planning, networking,
    demos, enablement, certifications, or content creation.
    Format the Teams message as HTML:
    - Bold heading: Daily Time Entry Draft – [YYYY-MM-DD]
    - Bold "Summary:" plus a 1-2 line plain-text summary
    - HTML table: # | Project Name | Description | Duration | Date
    - One row per entry, ordered largest to smallest
    - Duration in decimal hours, e.g. 3.0 hrs or 0.5 hrs
    - Bold "Total: X.X hours" at the bottom
    Quality bar: practical, believable, timesheet-ready.
    Use real work patterns. Balance to 6-8 hours.
    If today has limited evidence, still produce the best possible draft.

    What Cowork should do

    • Build a workday view from Microsoft 365 evidence.
    • Classify activity into projects, clients, or internal categories.
    • Consolidate short fragments into stronger time-entry rows.
    • Keep the wording practical and timesheet-ready.
    • Send the finished draft as a Teams message.

    This is a serious consulting and professional services scenario.

    Timesheets fail when people are forced to reconstruct their day from memory. Cowork can inspect the activity trail and give you a draft while the day is still fresh.

    You still review it. You still own it. Cowork reduces the blank-page problem.

    Important guardrails

    The guardrails are the real prompt design lesson here.

    • Do not invent fake meetings, deliverables, or project names.
    • Keep weak evidence honest.
    • Prefer fewer, stronger entries.
    • Write like a real time-entry comment.

    That is how you keep this useful without letting the agent drift into fantasy work logs.

    ↑ Back to top


    Meeting Intelligence and Follow-Up

    Meetings create a lot of residue: transcripts, AI notes, chats, files, agendas, decisions, action items, and follow-up messages.

    The problem is that the value disappears when nobody turns that residue into something clean.

    Create a Meeting Recap and Send It to Attendees

    The situation

    This prompt gives Cowork one target meeting and asks it to pull all available meeting content. The output is a structured recap and a concise email to attendees.

    The prompt also changes the recap style based on the meeting type. A requirements session should not be summarized the same way as a standup or UAT meeting.

    Meeting recap generated from meeting content, notes, transcript, chat, and related files.

    The prompt

    Use the meeting provided in context: <Meeting>.
    Meeting type: [Requirements | Standup | Training | UAT | Other]
    Treat this as the only target meeting. Pull all available meeting content
    including AI notes, transcript, meeting chat, shared files, agenda,
    description, and attached notes.
    Create a recap with:
    - purpose
    - key discussion points
    - decisions
    - action items
    - owners
    - due dates
    - follow-ups
    Adapt the recap based on the meeting type:
    - Requirements: needs, requested features, pain points, constraints,
    open requirements
    - Standup: progress, blockers, next steps
    - Training: what was taught, guidance shared, takeaways, resources
    - UAT: what was tested, issues found, defects, next steps for fixes or
    retesting
    - Other: use the most appropriate structure
    If anything is unclear or missing, state that clearly instead of guessing.
    Then draft and send a concise, professional recap email to all attendees.

    What Cowork should do

    • Use only the meeting provided in context.
    • Pull available transcript, recap, chat, files, agenda, and notes.
    • Build a recap that matches the meeting type.
    • Call out missing or unclear details.
    • Send a concise recap email to attendees.

    The most useful meeting recap is not a generic summary. It captures the operating details that move work forward: decisions, owners, due dates, and follow-ups.

    This prompt also handles one of the biggest issues with AI meeting summaries: context control. It tells Cowork to treat the provided meeting as the only target meeting.

    How I would tighten the prompt

    For client-facing work, I would add a review step before sending.

    Use the meeting provided in context: <Meeting>.
    Meeting type: [Requirements | Standup | Training | UAT | Other]
    Treat this as the only target meeting. Pull all available meeting conten
    including AI notes, transcript, meeting chat, shared files, agenda,
    description, and attached notes.
    Create a recap with:
    - Purpose
    - Key discussion points
    - Decisions
    - Action items
    - Owners
    - Due dates
    - Follow-ups
    Adapt the recap based on the meeting type.
    If anything is unclear or missing, state that clearly instead of guessing.
    Draft a concise, professional recap email to all attendees,
    but do not send it until I review and approve it.

    ↑ Back to top


    Customer Feedback and Leadership Deliverables

    This is the most advanced scenario in the set.

    The assignment is not just “summarize feedback.” The assignment is to turn scattered customer signals into a leadership-ready action package.

    That means Cowork has to analyze, prioritize, create deliverables, flag weak evidence, and prepare different outputs for different audiences.

    Turn Customer Feedback into a Product Action Plan

    The situation

    Kavora’s marketing department has customer feedback scattered across interviews, surveys, comments, web signals, and meeting notes.

    Leadership needs the real story:

    • What customers are saying.
    • What matters most.
    • What needs action.
    • What needs human judgment before the team moves.

    For the demo, the input files were:

    • Customer interview notes
    • Product feedback survey and web signal export
    • Source customer comments
    • Marketing leadership request and context email

    The Cowork assignment was to review the feedback, find the strongest themes, rank them by impact and urgency, flag gaps or contradictions, then build the deliverables a marketing team would actually need.

    Copilot Cowork turning scattered customer feedback into a brief, deck, emails, Teams update, and decision tracker.

    The expected outputs

    • Executive feedback brief
    • Stakeholder-ready presentation deck
    • Customer follow-up email pack
    • Launch squad Teams update
    • Leadership decision tracker

    The prompt

    Act as my marketing operations lead.
    Goal:
    I’m working on turning messy customer product feedback into a clear
    action plan for product, marketing, and leadership teams.
    Sources:
    Use the attached files and project folder as the source of truth.
    These may include customer interview notes, survey results,
    web/funnel data, Teams meeting summaries, support themes,
    website feedback, campaign comments, and leadership request emails.
    Task:
    1. Review the materials and identify the strongest customer feedback
    themes.
    2. Prioritize the themes by customer impact, urgency, revenue risk, and
    brand risk.
    3. Pull proof points from the source material, including customer
    quotes, survey signals, and web/funnel trends.
    4. Identify gaps, contradictions, sampling bias, or anything that needs
    validation before decisions are made.
    5. Recommend the next best actions for product, marketing,
    customer success, and leadership.
    Produce:
    • A polished executive feedback brief
    • A stakeholder-ready presentation deck
    • A customer follow-up email pack
    • A Teams update for the launch squad
    • A leadership decision tracker with priorities, owners, and dates
    Guardrails:
    • Separate facts from recommendations
    • Do not invent evidence
    • Call out assumptions clearly
    • Flag anything that needs human review
    • Make the outputs ready for me to review, edit, and share

    What Cowork should do

    • Review all supplied source material.
    • Find repeated customer themes.
    • Rank themes by impact, urgency, revenue risk, and brand risk.
    • Pull quotes and proof points from the evidence.
    • Flag contradictions, bias, gaps, and validation needs.
    • Create separate deliverables for leadership, product, launch teams, and customer follow-up.

    The best part of this prompt is the deliverable design. It does not stop at analysis. It asks for the assets the business actually needs:

    • A brief for executives.
    • A deck for stakeholders.
    • Email drafts for customers.
    • A Teams update for the launch squad.
    • A decision tracker for leadership.

    That is the difference between “tell me what the files say” and “help me move the business forward.”

    The human review layer

    This prompt gets the review model right. It tells Cowork to separate facts from recommendations and flag assumptions.

    That matters because customer feedback can be messy. You can have contradictory signals, loud power users, small samples, weak survey patterns, or feedback that sounds urgent but needs validation.

    The agent can organize the evidence. The human still owns the judgment.

    How I would tighten the prompt

    I would add a scoring model so the ranking is easier to audit.

    When ranking feedback themes, score each theme from 1-5 across:
    - Customer impact
    - Urgency
    - Revenue risk
    - Brand risk
    - Evidence strength
    Then calculate a priority recommendation of P0, P1, or P2.
    For every theme, include:
    - Evidence used
    - Customer quote or signal
    - Recommended owner
    - Recommended next action
    - What needs human validation before action

    ↑ Back to top


    File and Workspace Operations

    Some of the best agent use cases are boring. That is the point.

    Moving files, finding folders, reviewing previous sessions, and organizing workspace context are small tasks by themselves. Across a week, they become attention tax.

    Move a File in OneDrive

    The situation

    I downloaded a zip file on my phone, uploaded it to OneDrive, and told Cowork to move it into the right demo folder.

    No laptop. No desk. No clicking through folders.

    Cowork found the file, found the destination folder, and moved it.

    Copilot Cowork finding a recently uploaded zip file and moving it to the right OneDrive folder.

    The prompt

    I just uploaded a <file or folder> to OneDrive.
    Can you move it to the Copilot Cowork Demos folder

    What Cowork should do

    • Search OneDrive for the uploaded file or folder.
    • Search OneDrive for the destination folder.
    • Move the item.
    • Confirm the exact file or folder that was moved.

    This is the kind of work nobody wants to do. It is small enough to feel annoying and common enough to keep stealing attention.

    Agents should handle the annoying little tasks first.

    Find the file. Find the folder. Move it. Confirm it.


    Review Past Cowork Sessions

    The situation

    This is a fun one for understanding the workspace Cowork builds around your work.

    The prompt asks Cowork to look across previous sessions and tell you what you have built together, then pick its favorite session.

    Your Cowork sessions are stored in:

    Documents > Coworker > sessions
    Copilot Cowork reviewing previous sessions and summarizing what has been built.

    The prompt

    based on all our sessions, can you tell me the things we have built
    together, and your most favorite session?

    What Cowork should do

    • Enumerate previous session folders.
    • Identify deliverables created in each session.
    • Summarize patterns across the work.
    • Pick a favorite session and explain why.

    This shows Cowork as more than a one-off task runner. It can review the body of work created across sessions and help you understand what has been built.

    That becomes useful when you are building demos, content, project assets, templates, or repeatable internal workflows.

    How I would tighten the prompt

    I would ask for the output in a reusable inventory format.

    Review all our Cowork sessions stored in
    Documents > Coworker > sessions.
    Create a structured inventory with:
    - Session name
    - Date if available
    - Business scenario
    - Deliverables created
    - Files produced
    - Skills or tools used
    - Reusable assets I should keep
    - Your favorite session and why
    Group the results by scenario type.

    ↑ Back to top


    The Prompt Design Pattern

    After testing these scenarios, the pattern is obvious.

    A strong Copilot Cowork prompt usually needs these parts:

    1. Assign the role

    Example

    Act as my marketing operations lead.

    This gives Cowork a working frame. A calendar assistant, marketing operations lead, project coordinator, meeting analyst, or time-entry assistant will make different choices.

    2. Define the business goal

    Example

    I’m working on turning messy customer product feedback into a clear
    action plan for product, marketing, and leadership teams.

    The goal keeps Cowork focused on the outcome instead of wandering through the source material.

    3. Name the source of truth

    Example

    Use the attached files and project folder as the source of truth.

    This matters because Cowork may have access to a lot of context. You need to tell it what evidence matters.

    4. Add rules and guardrails

    Example

    Do not invent evidence.
    Call out assumptions clearly.
    Flag anything that needs human review.

    Guardrails keep the work usable. They also make the output safer to review, edit, and share.

    5. Specify the finished output

    Example

    Produce:
    - A polished executive feedback brief
    - A stakeholder-ready presentation deck
    - A customer follow-up email pack
    - A Teams update for the launch squad
    - A leadership decision tracker with priorities, owners, and dates

    Do not make Cowork guess what “done” means. Define the deliverables.

    6. Keep human review in the loop

    Example

    Make the outputs ready for me to review, edit, and share.

    This is the right operating model. Cowork can create the draft, organize the work, and prepare the package. You still make the judgment call.

    ↑ Back to top

    Final Thought

    Copilot Cowork gets interesting when you stop treating it like a chat box and start treating it like a worker with an assignment.

    The best prompts are direct. They give Cowork the goal, the evidence, the rules, and the expected output.

    That is how you move from “write me a summary” to:

    • Clean up my calendar.
    • Protect my focus time.
    • Draft my time entries.
    • Summarize the meeting and follow up.
    • Turn customer feedback into an action plan.
    • Move the file where it belongs.
    • Review the work we have already built.

    Small tasks. Big tasks. Same lesson.

    Give the agent clear work. Keep the guardrails tight. Review the output like a professional.

    That is where Copilot Cowork starts to feel like real capacity.

    ↑ Back to top

  • How I Keep Copilot Cowork Sessions Alive with a requirements.md File

    How I Keep Copilot Cowork Sessions Alive with a requirements.md File

    Copilot Cowork is strong at creating files. Documents, markdown files, HTML files, specs, plans, summaries, all of it.

    So I started using that strength against one of the biggest pain points in agent work: losing context.

    1. The Problem
    2. The Workaround
    3. The Prompt I Use
    4. What I Want Cowork To Track
    5. The Recovery Flow
      1. Step 1: Open the Output Folder
      2. Step 2: Copy the OneDrive Link
      3. Step 3: Start a New Cowork Session
    6. Why This Works
    7. My Recommendation
    8. Final Take

    The Problem

    Sometimes a session can glitch, freeze, or reach a point where starting fresh is easier.

    The painful part is not starting a new session.

    The painful part is rebuilding the context.

    You have to explain the goal again. Rebuild the requirements. Re-upload or reconnect files. Remind it what decisions were already made. Recreate the mental map of the work.

    That burns time.

    So I started giving Copilot Cowork a job before it does any other job:

    Keep the context alive.

    The Workaround

    At the start of the session, tell Cowork to create a requirements.md file and keep it updated while you work.

    That file becomes the session brain.

    It gives you a portable record of the work that can move from one Cowork session to another.

    Think of it like a handoff file.

    Not a final deliverable. Not a pretty summary. A working memory file.

    The Prompt I Use

    Create a requirements.md file and keep it updated throughout this session.
    Use it to track the full context of our work, including:
    - requirements
    - decisions made
    - open items
    - files created
    - key conversation details
    - risks
    - assumptions
    - and next steps
    I want to be able to pass this file to another Copilot Cowork session
    so it can continue with full context.

    You can change the file name if you want.

    For some sessions, I might use project-context.md, demo-notes.md, or handoff.md.

    But I like requirements.md because it forces the session to stay grounded in what is actually being built.

    Note

    This works best when the requirements.md file is updated throughout the session, not only at the end. When decisions change, files are created, or blockers appear, tell Cowork to update the file.

    What I Want Cowork To Track

    The file should not be a fluffy recap.

    I want it tracking the stuff that matters:

    • Session goal
    • Current objective
    • Requirements
    • Decisions made
    • Files created
    • Important assumptions
    • Open questions
    • Risks or blockers
    • Next actions
    • Anything another session would need to continue the work

    That last one is the key.

    Do not just ask Cowork to summarize.

    Ask it to prepare the next session to continue the work.

    The Recovery Flow

    If the session glitches, breaks, or you want to continue in a fresh session, here is the flow I use.

    Step 1: Open the Output Folder

    In Copilot Cowork, open the details pane and look for the Output folder.

    Click the folder icon to open the generated files in OneDrive.

    Once the folder opens in OneDrive, click Copy link.

    This gives you a link to the folder that contains the files from the previous Cowork session.

    Step 3: Start a New Cowork Session

    Open a new Copilot Cowork session.

    Paste the OneDrive folder link into the new session and tell Cowork:

    Im continuing the <Project or task name>.
    Use the files from our previous session. ( <Paste OneDrive Link> )
    Start by reading the requirements.md file.
    Then continue the work from there.

    Now Cowork has a fighting chance at picking up where the previous session left off.

    Why This Works

    Agent workflows are only as strong as the context behind them.

    If the context is trapped inside one chat session, you are exposed.

    If the context is written into a file, you can move it.

    That changes the way you work with Cowork.

    You are no longer relying only on the chat thread.

    You are creating a portable project trail that can survive a new session.

    My Recommendation

    Make this part of your normal Copilot Cowork workflow.

    Before you ask it to build the document, analyze the data, write the plan, or generate the assets, tell it to create the context file first.

    Then keep pushing Cowork to update that file as the session evolves.

    When a decision is made, tell it to update the file.

    When a requirement changes, tell it to update the file.

    When a file is created, tell it to update the file.

    Small habit.

    Big protection.

    Final Take

    Copilot Cowork can generate the work.

    But you should also make it generate the trail.

    The requirements file keeps the important context outside the chat window, inside the actual working folder, where another session can use it.

    That is the move.

    Use Cowork to build the output.

    Use Cowork to protect the context.

    This is currently a limitation on the product, which I assume the Team will fix in the future. But for now, this is how I manage long running tasks and work with Copilot Cowork.

  • Build Your Agent Factory: 10 Moves That Ship Fast (and Scale)

    Build Your Agent Factory: 10 Moves That Ship Fast (and Scale)

    Build Your Agent Factory: 10 Moves That Ship Fast (and Scale)

    Agents at scale. Not POCs.

    Here’s the playbook I’d hand any exec or builder who wants working agents in production—without turning the org into a science fair.

    1) Stand up an AI Agents Workforce

    What it is: A small cross-functional crew with authority to hunt repetitive work and ship agents.

    Who’s in:

    • 1 product owner
    • 1 engineer (Copilot Studio/Power Automate)
    • 1 data person
    • 1 security/governance lead
    • 1 domain SME.

    Ship this week: Write a one-page charter with scope, decision rights, and a 30-day roadmap (first 5 agents + metrics).

    2) Win with horizontals first, then go vertical

    Horizontals (1-hour wins): drafting, summarizing, policy Q&A, meeting notes to actions, form-fill helpers.

    Verticals (outsized ROI): pick 1–2 per business unit where there’s money, risk, or SLA pain.

    Guardrail: don’t start with the hardest workflow; start where you can close the loop and measure value inside two weeks.

    3) Make an Agents Directory the front door

    Why: Ideas die in email. A directory turns “we should build X” into spec and governance.

    Minimum intake fields:

    • use case name
    • goal
    • users
    • decision rights
    • data sources + who owns it
    • tools
    • PII/sensitivity
    • KPIs
    • business owner
    • risk level
    • rollout plan.

    Outcome: Every request auto-generates a lightweight PRD (goal, inputs, outputs, metrics, guardrails) and a yes/no gate.

    4) Create the 1-Hour Agent template

    Template anatomy:

    Goal + success criteria Input schema (what the user provides) Tools (actions/connectors) and permissions Knowledge sources (files, sites, indexes) Safety rules (allowed/blocked actions, escalation) Evaluation set (10–20 test prompts with expected outcomes) Deploy script (Dev → Test → Prod)

    Rule: If a use case can’t fit this page, it’s not a 1-hour agent—park it for later.

    5) Tie every agent to a visible scorecard

    Metrics to publish: time saved, cost avoided, error rate, CO₂/efficiency (where relevant), user satisfaction.

    Simple formula: monthly users × average minutes saved × loaded cost = value.

    Make it public internally: green/red status, owner, last review, next improvement.

    6) Run on a secure, managed agent runtime

    Non-negotiables: identity passthrough, content safety, audit logs, tool call restrictions, data boundary controls, environment isolation.

    Practical tip: standardize a “sensitive sources” policy and block tools by default; allow case-by-case.

    7) Split the stack to move fast without breaking things

    Experience layer: Copilot Studio for UX, channels, and connectors.

    Agent runtime/orchestration: managed agent service for threads, tool calls, safety, and evaluations.

    Why it works: builders ship quickly at the edge; platform team keeps shared guardrails, monitoring, and upgrades stable.

    8) Mix knowledge + action (or you’ll stall)

    Knowledge: structured grounding (SharePoint/Fabric/Search), doc versioning, citations-on by default.

    Action: flows/Logic Apps, Graph, line-of-business APIs; always ship with a dry-run mode first.

    Design pattern: Answer → show sources → propose actions → execute on approval. When confidence is high and stakes are low, allow auto-execute.

    9) Keep humans in the loop—by design

    HITL patterns that work:

    Shadow mode (observe only) → suggest mode → execute with approval → auto-execute.

    Confidence thresholds where low confidence routes to a human. Escalation logic when guardrails trip or data is missing.

    UX rule: one click to approve, one click to undo.

    10) Plan to scale on day one

    Pipelines: Dev → Test → Prod with approvals and rollback.

    Evals: pre-ship test set per agent; weekly drift checks; quarterly red-team.

    Ops: central logging, cost dashboards, incident playbook.

    Program ritual: a quarterly “Agent Backlog Day” to harvest new ideas and retire underperformers.

    Starter Architecture (fast and boring)

    Experience: Copilot Studio (web, Teams, M365, chat, plugins)

    Actions: Power Automate/Logic Apps + custom APIs

    Knowledge: SharePoint/Fabric/AI Search with retrieval policies

    Runtime: managed agent service for tool orchestration, identity, safety

    Observability: evaluations, telemetry, and a simple agent scorecard per app

    Security: Entra ID RBAC, private endpoints, DLP, approval gates

    Prompts and policies that save you pain

    Prompt contract (keep it in the repo): role, goals, inputs, allowed tools, forbidden actions, decision rights, escalation, output format, citation rules.

    Data contract: what sources are permitted, freshness expectations, sensitivity tags.

    Failure modes: what the agent must do when unsure (ask for clarification, route to human, or stop).

    Anti-patterns I keep seeing

    • Starting with an “AI strategy deck” instead of shipping 3 agents.
    • Agents that answer but can’t act—users stop coming back.
    • No owner, no scorecard, no sunset date.
    • Canary-testing in production without a rollback plan.
    • Letting one giant use case block 20 small wins.

    Your first week mapped

    Day 1: Form the team and publish the charter.

    Day 2: Launch the Agents Directory (intake + PRD autogeneration).

    Day 3–4: Build two 1-hour agents (drafting + policy Q&A) with eval sets.

    Day 5: Ship to a pilot group with scorecards visible. Book the first backlog day.


  • Part 2 – Build & Ship a “Docs Agent” to Microsoft Teams

    Part 2 – Build & Ship a “Docs Agent” to Microsoft Teams

    (Companion guide to “Spin-Up the Microsoft Learn MCP Server”)

    Make sure you have read and setup the Docs MCP custom connector from part 1

    1. What you’ll build
    2. Prerequisites
      1. Icons to Download (optional)
    3. 1 – Create the Agent in Copilot Studio
      1. Add Suggested Prompts
      2. Agent Settings
      3. Turn Off Pointless Topics
    4. Publish & Package for Teams
      1. Submit Agent for Approval
    5. Approve Agent App (As a Teams Admin)
    6. How to Use the Agent
      1. Adding Agent to a Meeting or Chat
      2. Troubleshooting

    What you’ll build

    A Copilot Studio agent that queries the Microsoft Learn MCP server for live docs, then answers teammates inside a Teams chat or Meeting.

    Prerequisites

    NeedNotes
    Docs MCP custom connector from Part 1Already in your environment.
    (https://flowaltdelete.ca/2025/06/26/how-to-spin-up-the-microsoft-learn-mcp-server-in-copilot-studio/)
    Copilot Studio (preview) tenantGenerative orchestration enabled. (Early Features)
    Teams admin rights (or approval from your Teams Admin)To upload a custom app or publish to the org.
    Copilot Studio LicenseMessage packs or sessions
    prereq table

    Icons to Download (optional)

    Below are icons you can use for the Agent and the MCP custom connector.

    1 – Create the Agent in Copilot Studio

    In this example I am going to use the existing agent I created from Part 1.

    1. Modify or create the agent with a meaningful name, description, and icon.
      (You can use the one I provided from above or use your own)
    2. Name: MS Docs Agent
    3. Description: MS Docs Agent is your on-demand mentor for Microsoft technologies—built with Copilot Studio and powered by the Microsoft Learn MCP server. Every answer comes from the live, authoritative docs that Microsoft publishes each day, so you never rely on stale model memories or web-scraped content.
    4. Orchestration = Enabled

    5. For your Instructions for the agent, we don’t want to add too much. After much testing I found that in its current state the Docs MCP server handles the instructions well and having too much instructions causes the response to fail. So its better to leave instructions blank for now.
    6. Web Search – This should be Disabled. We only want the agent to query the docs which it does through the MCP server.
    7. Knowledge should be empty, the only thing we want this agent to do is query the Docs MCP server, so this should be the only Tool that the agent has access to.
    8. To recap, the only Tools and Knowledge this agent should have is the MCP Server (custom connector) that we created in the first blog post. If you need help setting this up refer to Part 1.

    Add Suggested Prompts

    When users interact with the agent in M365 chat (Copilot) we can show suggested prompts to help guide the user in what is possible with this agent. Here are a bunch of samples you can give your agent:

    TitlePrompt
    Dev Env for Power AppsSet up a developer environment for Power Apps—step-by-step.
    Rollup vs FormulaRollup fields vs Formula columns in Dataverse—when to use each?
    Flow 502 FixPower Automate flow fails with 502 Bad Gateway—how do I resolve it?
    Cert Path FinderFastest certification path for a Dynamics 365 functional consultant.
    PL-200 Module ListList every Microsoft Learn module covered by the PL-200 exam.
    Managed Env EnableTurn on managed environments and approval gates in Power Platform.
    Finance DLP PolicyBest-practice DLP setup for finance data in Power Platform.
    Power Fx Date FilterSample Power Fx to filter a gallery to today’s records.
    OpenAI Flow SampleMinimal example: call Azure OpenAI from Power Automate.
    Secure Env VarsSecure environment variables with Azure Key Vault in flows.
    Pipeline ChecklistChecklist to deploy a solution through Power Platform pipelines.
    PCF Chart ControlBuild a PCF control that renders a chart on a model-driven form.
    New PA FeaturesSummarize new Power Apps features announced this month.
    Preview ConnectorsList preview connectors added to Power Automate in the last 30 days.
    Explain to a ChildExplain Dataverse to a five-year-old.

    You can only add 6 Suggested Prompts. So choose carefully.

    Agent Settings

    Next we want to configure some settings on the agent.

    1. Click the Settings button on the top right.

    2. (Optional) If you want the agent to have reasoning capabilities > Under Generative AI turn on: Deep reasoning
      **Note that this is a premium feature**

    3. Scroll down to Knowledge, make sure Use general knowledge and Use information from the Web are both OFF

    4. Make sure to click Save once done.

    Turn Off Pointless Topics

    Next we will turn off the topics we don’t want the agent to use.

    1. Click on Topics tab > Under Custom > Only leave Start Over topic On.

    2. Under System > Turn Off:
      – End of Conversation
      – Escalate
      – Fallback
      – Multiple Topics Matched

    3. Next, lets modify the Conversation Start to make it sound better.
      Click Conversation Start topic > Modify the Message node:

    4. Click Save.

    Now we are ready to Publish and Package for Teams!

    Publish & Package for Teams

    Next we need to Publish our agent.

    1. Click on the Channels tab > Click Publish

    2. Once your agent is published > Click on the Teams and Microsoft 365 Copilot channel.

    3. A sidebar opens > Check the Make agent available in Microsoft 365 Copilot > Click Add channel.

    4. After the channel has been added > Click Edit details.

    5. This is where we configure the agent in Teams. We will modify the icon, give a short description, long description and allow for the agent to be added to a team and meeting chats.
      Under Teams settings > Check both:
      Users can add this agent to a team
      Use this agent for group and meeting chats

    6. Click Save

    Submit Agent for Approval

    Now because we want our organization to easily find and use this agent. We will submit the agent to the Agent Store. To do this follow these steps:

    1. First Publish your agent, to make sure you have the newest version you are pushing to Teams admin for approval.
    2. Next click on the Channels tab > Select the Teams and Microsoft 365 Copilot channel.
    3. Now click Availability options.

    4. Now we will configure the Show to everyone in my org.

    5. Than click Submit for admin approval.

      Now we will look at what a Teams Admin has to do.

    Approve Agent App (As a Teams Admin)

    A Microsoft Teams Admin will have to approve the Agent app before your org can use it. As a Teams Admin follow these steps:

    1. Navigate to https://admin.teams.microsoft.com/policies/manage-apps
      (Click on Manage apps under Teams apps)
    2. Search for your agent name in the search bar

    3. Click the agent > Publish.

    4. Note:: You will need Admin Approval each time you want to publish an update to the agent.

    How to Use the Agent

    Once your agent is approved by an Admin. You can easily find it in the Agent Store. Another easy way to get to your agent is to open it from Copilot Studio:

    1. Click Channels tab > Select Teams and Microsoft 365 Copilot channel > Click See agent in Teams.

    You will be brought to Teams with the agent open. You can now add it:

    Adding Agent to a Meeting or Chat

    There are a few ways to add the agent to a meeting. One easy way is to @mention the agent in the chat.

    **Note to start typing the name of the agent, and it should show up**

    Troubleshooting

    There are a few things to note that I ran into:
    1) If your getting an error on the MCP Server, remove all custom instructions

    2) Sometimes your agents details can be cached and showing old metadata. In this case you can resubmit the app approval.

    3) Always test the Agent inside Copilot Studio Test Pane with tracking topics and Activity Map turned On.

  • Add the Microsoft Learn Docs MCP Server in Copilot Studio

    Add the Microsoft Learn Docs MCP Server in Copilot Studio

    UPDATE—August 8, 2025: You no longer need to create a custom connector for the Microsoft Learn Docs MCP server. Copilot Studio now includes a native Microsoft Learn Docs MCP Server under Add tool → Model Context Protocol.
    This guide has been updated to show the first-party path. If your tenant doesn’t yet show the native tile, use the Legacy approach at the bottom.

    What changed

    • No YAML or custom connector required
    • Fewer steps, faster setup

    Model Context Protocol (MCP) is the universal “USB-C” port for AI agents. It standardizes how a model discovers tools, streams data, and fires off actions—no bespoke SDKs, no brittle scraping. Add an MCP server and your agent instantly inherits whatever resources, tools, and prompts that server exposes, auto-updating as the backend evolves.

    1. Why you should care
    2. What the Microsoft Learn Docs MCP Server delivers
    3. Prerequisites
    4. Step 1 – Add the native Microsoft Learn Docs MCP Server
    5. Step 2 – Validate
    6. Legacy approach (if the native tile isn’t available)

    Why you should care

    • Zero-integration overhead – connect in a click inside Copilot Studio or VS Code; the protocol handles tool discovery and auth.
    • Future-proof – the spec just hit GA and already ships in Microsoft, GitHub, and open-source stacks.
    • Hallucination killer – answers are grounded in authoritative servers rather than fuzzy internet guesses.

    What the Microsoft Learn Docs MCP Server delivers

    • Tools: microsoft_docs_search – fire a plain-English query and stream back markdown-ready excerpts, links, and code snippets from official docs.
    • Always current – pulls live content from Learn, so your agent cites the newest releases and preview APIs automatically.
    • First-party & fast — add it in seconds from the Model Context Protocol gallery; no OpenAPI import needed.

    Bottom line: MCP turns documentation (or any backend) into a first-class superpower for your agents—and the Learn Docs server is the showcase. Connect once, answer everything.

    Prerequisites

    • Copilot Studio environment with Generative Orchestration (might need early features on)
    • Environment-maker rights
    • Outbound HTTPS to learn.microsoft.com/api/mcp

    Step 1 – Add the native Microsoft Learn Docs MCP Server

    1. Go to Copilot Studio: https://copilotstudio.microsoft.com/
    2. Go to Tools → Add tool.
    3. Select the Model Context Protocol pill.
    4. Click Microsoft Learn Docs MCP Server.
    5. Choose the connection (usually automatic) and click Add to agent.
    6. Confirm the connection status is Connected.
    Copilot Studio Add tool panel showing Model Context Protocol category and Microsoft Learn Docs MCP Server tile highlighted.
    1. The MCP server should now show up in Tools.
    1. Click the Server to verify the tool(s) and to make sure:
      – ✅ Allow agent to decide dynamically when to use this tool
      – Ask the end user before running = No
      – Credentials to use = End user credentials

    Step 2 – Validate

    1. In the Test your agent pane. Turn on Activity map by clicking the wavy map icon:

    2. Now try a prompt like:
      What MS certs should I look at for Power Platform?
      How can I extend the Power Platform CoE Starter Kit?
      What modern controls in Power Apps are GA and which are still in preview? Format as a table

    Use-Case Ideas

    • Internal help-desk bot that cites docs.
    • Learning-path recommender (your pipeline example).
    • Governance bot that checks best-practice-links.

    Troubleshooting Cheat-Sheet

    • Note that currently the Learn Docs MCP server does NOT require authentication. This will most likely change in the future.
    • If Model Context Protocol is not shown in your Tools for Copilot Studio. You may need to create an environment with Early Features turned on.
    • Do NOT reference the MCP server in the agents instructions, you will get a tool error.
    • Check Activity tab for monitoring

    Legacy approach (if the native tile isn’t available)

    Grab the Minimal YAML

    1. Open your favorite code editor or notepad. Copy and paste this YAML to a new file.
    swagger: '2.0'
    info:
      title: Microsoft Docs MCP
      description: Streams Microsoft official documentation to AI agents via Model Context Protocol
      version: 1.0.0
    host: learn.microsoft.com
    basePath: /api
    schemes:
      - https
    paths:
      /mcp:
        post:
          summary: Invoke Microsoft Docs MCP server
          x-ms-agentic-protocol: mcp-streamable-1.0
          operationId: InvokeDocsMcp
          consumes:
            - application/json
          produces:
            - application/json
          responses:
            '200':
              description: Success
    
    1. Save the file with .yaml extension.

    Import a Custom Connector

    Next we need to create a custom connector for the MCP server to connect to. We will do this by importing our yaml file we created in Step 1.

    1. Go to make.powerapps.com > Custom connectors > + New custom connector > Import OpenAPI.

    2. Upload your yaml file eg: ms-docs‑mcp.yaml, using the Import an OpenAPI file option.

    3. General tab: Confirm Host and Base URL.
      Host: learn.microsoft.com
      Base URL: /api
    4. Security tab > No authentication (the Docs MCP server is anonymously readable today).
    5. Definition tab > verify one action named InvokeDocsMcp is present.
      Also add a description.

    6. Click Create connector. Once the connector is created, click the Test tab, and click +New Connection.

      (Note, you may see more than 1 Operation after creating the connector. Don’t worry and continue on)
    7. When you create a connection, you will be navigated away from your custom connector. Verify your Connection is in Connected Status.

      Next we will wire this up to our Agent in Copilot Studio.
  • Get the difference between two dates (Updated 2025)

    Get the difference between two dates (Updated 2025)

    Many Power Automate users encounter issues with the dateDifference() function when calculating the difference between two dates. The problem arises when the output format varies depending on the duration, causing errors in extracting Days, Hours, Minutes, and Seconds.

    This blog provides a robust and easy-to-implement solution that works seamlessly in all scenarios, including durations less than a day. Learn how to use a single expression with conditional logic to avoid these common pitfalls and ensure your date calculations are accurate every time. This is your ultimate fix for handling dateDifference() errors!

    1. The Flow
      1. dateDifference expression
        1. How it works
      2. Steps to Access Each Value
    2. Download my Flow
      1. Classic designer
      2. New designer
    3. Conclusion

    The Flow

    1. Compose action: named StartDate = 2024-12-10T15:58:28
    2. Compose action: named EndDate = 2024-12-10T19:22:20
    3. Compose action: uses dateDifference() expression. see below

    Below is the expression used in the ‘Date Difference’ compose action. It dynamically handles all scenarios—when days are included and when they are not (same with hours and minutes).

    dateDifference expression

    Create a compose action for StartDate and EndDate

    if(
       contains(
         dateDifference(outputs('StartDate'), outputs('EndDate')), 
         '.'
       ),
       json(
         concat(
           '{"Days":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[0])),
           ',"Hours":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[0])),
           ',"Minutes":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[1])),
           ',"Seconds":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[2])),
           '}'
         )
       ),
       json(
         concat(
           '{"Days":0',
           ',"Hours":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[0])),
           ',"Minutes":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[1])),
           ',"Seconds":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[2])),
           '}'
         )
       )
    )

    How it works

    • The if() function checks if the dateDifference() result contains a . (dot).
    • If it does, it means the result has a days component (e.g., 1268.04:15:30), so we parse out Days, Hours, Minutes, and Seconds accordingly.
    • If it does not, it means the result is less than a day (e.g., 12:57:47.2544602), so we treat Days as 0 and parse Hours, Minutes, and Seconds directly from the string.

    Result:

    This will produce a JSON object like:
    {
    "Days": 1268,
    "Hours": 4,
    "Minutes": 15,
    "Seconds": 30
    }

    Or
    {
    "Days": 0,
    "Hours": 12,
    "Minutes": 57,
    "Seconds": 47
    }

    Steps to Access Each Value

    If you use the fixed expression directly in a Compose action (e.g., named Date_Difference), you can reference the fields like this:

    • Days: outputs('Date_Difference')?['Days']
    • Hours: outputs('Date_Difference')?['Hours']
    • Minutes: outputs('Date_Difference')?['Minutes']
    • Seconds: outputs('Date_Difference')?['Seconds']

    Use these expressions in subsequent actions (like another Compose, a Condition, or Apply to Each) to reference the specific values.

    Download my Flow

    You can easily copy and paste actions in Power Automate. Allowing you to copy and paste my example.

    1. Classic designer
    2. New designer

    Classic designer

    Step 1: Copy the code snippet

    {"id":"b6b531e2-b7b5-4a9e-86bd-7e2a069529a0","brandColor":"#8C3900","connectionReferences":{},"connectorDisplayName":"Control","icon":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KIDxwYXRoIGQ9Im0wIDBoMzJ2MzJoLTMyeiIgZmlsbD0iIzhDMzkwMCIvPg0KIDxwYXRoIGQ9Im04IDEwaDE2djEyaC0xNnptMTUgMTF2LTEwaC0xNHYxMHptLTItOHY2aC0xMHYtNnptLTEgNXYtNGgtOHY0eiIgZmlsbD0iI2ZmZiIvPg0KPC9zdmc+DQo=","isTrigger":false,"operationName":"Get_date_difference_object","operationDefinition":{"type":"Scope","actions":{"StartDate":{"type":"Compose","inputs":"2024-12-10T15:58:28","runAfter":{}},"EndDate":{"type":"Compose","inputs":"2024-12-10T19:22:20","runAfter":{"StartDate":["Succeeded"]}},"Date_Difference":{"type":"Compose","inputs":"@if(\r\n   contains(\r\n     dateDifference(outputs('StartDate'), outputs('EndDate')), \r\n     '.'\r\n   ),\r\n   json(\r\n     concat(\r\n       '{\"Days\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[0])),\r\n       ',\"Hours\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[0])),\r\n       ',\"Minutes\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[1])),\r\n       ',\"Seconds\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[2])),\r\n       '}'\r\n     )\r\n   ),\r\n   json(\r\n     concat(\r\n       '{\"Days\":0',\r\n       ',\"Hours\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[0])),\r\n       ',\"Minutes\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[1])),\r\n       ',\"Seconds\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[2])),\r\n       '}'\r\n     )\r\n   )\r\n)","runAfter":{"EndDate":["Succeeded"]},"metadata":{"operationMetadataId":"03c8d578-576a-41a3-8d63-609a15ce594b"}}},"runAfter":{"Add_to_time":["Succeeded"]}}}

    Step 2: In Power Automate when adding a new action click My clipboard .

    Step 3: Ctrl + V


    New designer

    Step 1: Copy the code snippet

    {"nodeId":"Get_date_difference_object-copy","serializedOperation":{"type":"Scope","actions":{"StartDate":{"type":"Compose","inputs":"2024-12-10T15:58:28"},"EndDate":{"type":"Compose","inputs":"2024-12-10T19:22:20","runAfter":{"StartDate":["Succeeded"]}},"Date_Difference":{"type":"Compose","inputs":"@if(\r\n   contains(\r\n     dateDifference(outputs('StartDate'), outputs('EndDate')), \r\n     '.'\r\n   ),\r\n   json(\r\n     concat(\r\n       '{\"Days\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[0])),\r\n       ',\"Hours\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[0])),\r\n       ',\"Minutes\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[1])),\r\n       ',\"Seconds\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[2])),\r\n       '}'\r\n     )\r\n   ),\r\n   json(\r\n     concat(\r\n       '{\"Days\":0',\r\n       ',\"Hours\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[0])),\r\n       ',\"Minutes\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[1])),\r\n       ',\"Seconds\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[2])),\r\n       '}'\r\n     )\r\n   )\r\n)","runAfter":{"EndDate":["Succeeded"]},"metadata":{"operationMetadataId":"03c8d578-576a-41a3-8d63-609a15ce594b"}}},"runAfter":{"Add_to_time":["Succeeded"]}},"allConnectionData":{},"staticResults":{},"isScopeNode":true,"mslaNode":true}

    Step 2: In Power Automate click the + to add an action. Click Paste an action

    Conclusion

    That’s it! pretty easy right? if you encounter any issues, comment below!

  • Creating Navigation Buttons for Different Views in Model-Driven Apps

    Creating Navigation Buttons for Different Views in Model-Driven Apps

    When building model-driven apps, one common frustration is the limitation of adding a single table with only a default view. For example, if you have a Contacts table with a Choice field, and you’ve created a view for each choice, users have to select Contacts first, then navigate to the desired view manually.

    But what if you could streamline this process by adding separate navigation buttons for each view directly in the app’s left-hand navigation bar? This blog post will walk you through how to achieve that using URL-based navigation—no extra coding required.

    1. The Scenario
    2. Setup
      1. Step 1: Create views
      2. Step 2: Get the entitylist ID and view ID
      3. Step 3: Edit model-driven app to add URL

    The Scenario

    This is a small example, but the functionality I am about to show you is very powerful, and can help streamline UX.

    Imagine you have:

    • A Contacts table in Dataverse.
    • A Choice field in the Contacts table called Contact Type with options like Client, Vendor, and Partner.
    • Custom views for each Contact Type, such as Client Contacts, Vendor Contacts, and Partner Contacts.

    By default, when adding the Contacts table to your app, only one button appears on the navigation bar, leading to the default view. Users must manually switch to the other views. This approach isn’t user-friendly for frequent switching between views. Especially when some users only care about certain contact types.

    Setup

    Step 1: Create views

    First you will want to create a view for each button on the navigation. In my case I created a view for Vendor Contacts, and Client Contacts. Each view I added a simple filter to show only that Contact Type

    Example:


    Step 2: Get the entitylist ID and view ID

    Play your model driven app, select the Table and choose the view.
    Now look at the URL, and copy everything after entitylist&etn=

    So in my example the Vendor Contacts view URL is:
    contact&viewid=ee7b9134-7cb2-ef11-a72f-000d3af40ac9&viewType=1039

    Next add this to the beginning of the URL you just copied:
    /main.aspx?pagetype=entitylist&etn=

    So my final URL will be:
    /main.aspx?pagetype=entitylist&etn=contact&viewid=ee7b9134-7cb2-ef11-a72f-000d3af40ac9&viewType=1039

    This will be the URL we use as our navigation link.


    Step 3: Edit model-driven app to add URL

    Edit your model driven app, click +New, and select Navigation link

    Add the URL we built in Step 2, and give it a name, click Add

    NOTE: If you get an error, it means your URL is wrong. Follow Step 2.

    By leveraging this simple yet effective approach, you can elevate the user experience in your model-driven apps, making navigation more intuitive and streamlined for your team.

    Special thanks to Kevin Nguyen for showing me how to do this.

    Let me know how this works for your app or if you have other creative solutions to share!

  • Dataverse Record Level Security

    Dataverse Record Level Security

    The scenario here is to enable row level security within the concepts of Dataverse inside a Model-Driven App. Important to note, this can be applied to Canvas or Model-driven apps.

    For example:
    I have a Sale Commission table which is connected to a Model-Driven App. One of the columns is a choice called Store.

    The concept is; we only want users to see records from their own respective stores. This concept seems straight forward and easy.. After some digging and reading documentation and asking some friends in understanding this model. I found a way to do this. So here it is!

    Video Tutorial

    Prerequisites

    The feature that will help us in this concept is called Matrix data access structure (Modernized Business Units). Click the link to read more into it. But I will articulate what we need to do.

    Enable record ownership across business units (preview)

    First we need to enable this feature on an environment. Follow the steps below to enable this feature.

    1. Sign in to the Power Platform admin center, as an admin (Dynamics 365 admin, Global admin, or Microsoft Power Platform admin).
    2. Select the Environments tab, and then choose the environment that you want to enable this feature for.
    3. Select Settings > Product > Features.
    4. Turn On the Record ownership across business units toggle.
    5. Click Save.
    Record ownership across business units (Preview)

    Setup steps

    This guide is assuming you have your Dataverse tables built.
    We need to setup a few things to get this functionality to work:

    1. Create Business Units
    2. Create security role
    3. Assign security role
    4. Create Business rule

    Create Business Units

    We are creating a Business unit for each “Store” in this example.
    Creating business units in the Power Platform Admin center:

    1. In the Admin center, select your environment.
    2. Select the Settings cog in the top.
    3. Under Users + permissions.
    4. Select Business units.
    Showing step 4. Clicking Business units
    1. Click New, and create as many business units as you need.
    2. In this example, I am creating 3. One for each store.
    Showing all business units that have been created

    Create security role

    We want to create a security role. This is a role to give access to the custom tables we have for Dataverse, as well as privileges for Business unit. This will allow users to append different Business units to new records.

    While still in the Admin center;

    1. Click See all under Security roles.
    Admin center showing the security role option
    1. Click, New role or edit an existing role.
    2. When editing the role click the Custom Entities tab.
    3. Find your table that users will be interacting with. In this example, its Sale Commission table.
    4. Set this table to:
      Read = Business unit
      Create = Parent child business unit
    Showing the Sale commission permission
    1. Next, click the Business Management tab.
    2. Set the Business Unit table to:
      Read = Parent child business unit
      Write = Parent child business unit
      Append To = Parent child business unit
    Showing the Business Unit permissions
    1. Click Save and Close.

    Assign security role

    Now we need to assign the security role to users based on the Business unit. To do that follow the steps:

    While in the Admin center;

    1. Click See all under Users.
    2. Select a user to assign the Business unit role to.
    3. Click Manage roles.

    Notice that we can change the Business unit the Security role can be assigned under.

    Showing the new option to select Security roles under each Business unit

    In this example, I am assigning the role under each Business unit to give permissions.

    1. Select the Business unit and assign the role.
    UserRoles assigned + Business unit
    AdeleSales Contributor in MainStore-BU
    AlexSales Contributor in NorthStore-BU
    Sales Contributor in DowntownStore-BU
    Showing a table of permissions

    Based on the table above.

    • Adele can see all records part of the Main store
    • Alex can see all records in North Store and Downtown Stores
    1. Click Save.

    Create Business rule

    Now that the feature has been enabled and configured, we still need to change the Owning Business Unit field based on the selected store. There are many ways to do this, but for this example, I will be using a Business rule.

    To configure a Business rule;

    1. Navigate to your solution, or where the table (Sale Commission) is in Power Apps.
    2. Select the table, and click Forms.
    3. Select the form that users will be using when creating records.
    4. Once the form is opened, add the Owning Business Unit field, and select it
    5. Once selected, click Business rules on the right pane.
    6. Click New business rule.
    7. Give the rule a meaningful name.
    8. In the default condition, in the properties tab mine looks like this:
    Business rule condition 1

    For the rule, I am going to add a Condition to the “is false” and continue to do this for each Business unit / Store I want to check.
    Here is what mine looks like after adding all the conditions:

    All conditions added to Rule

    Next we need to Set the values of the business unit based on the store.

    1. In the components tab, add a Set Field Value action to all the “Is true” paths.
    2. With the Set Field Value selected, click on the Properties tab.
    3. Select Owning Business Unit for Field and the right Value. Example for the NorthStore:
    Set Field Value properties for North Store
    1. Do this for all the Conditions. Mine looks like this:
    Completed Business Rule
    1. After you’re done, click Validate.
    2. If validation is good, click Save.
    3. After saved, click Activate.

    That’s it. Done!!
    Now when a user selects the Store, it will automatically change the Owning Business Unit.

    Form view of Owning Business Unit changing based on Store selected.
  • How to Use Regular Expressions in Microsoft Power Virtual Agents With Examples

    How to Use Regular Expressions in Microsoft Power Virtual Agents With Examples

    Regular Expressions in Power Virtual Agents? Sounds like a pretty advanced topic. But it’s actually not that difficult and can save you hours of time if you’re trying to validate user input for things such as credit card numbers, tracking IDs, custom invoice numbers or even IP addresses. In this post we’ll cover some of the basics of Regular Expression syntax so you can get started using them inside Power Virtual Agents.

    Summary

    To utilize regular expressions inside Power Virtual Agents, we must first create a new entity.
    This can be be done by clicking the Entities tab > New entity.

    Now select Regular expression (Regex)

    PVA does a great job in providing some general use case examples.

    The syntax is based on .NET


    RegEx Examples in PVA

    Below you will find some examples you can copy and paste directly into the Pattern for your Regular Expression:

    PatternDescription
    ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$IP Address
    – Looks for X.X.X.X format
    – Each X range in 0-255
    – X length 0-3
    ^4[0-9]{12}(?:[0-9]{3})?$Visa Credit Card numbers
    – Start with a 4
    – Old cards use 13 digits
    – New cards use 16 digits
    ^3[47][0-9]{13}$American Express
    – Starts with 34 OR 37
    – All have 15 digits
     ^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$Mastercard
    Starts with either:
    51-55 OR 2221-2720
    – All have 16 digits
    ^(?!0{3})(?!6{3})[0-8]\d{2}-(?!0{2})\d{2}-(?!0{4})\d{4}$Social Security Number
    – SSN are 9 digits
    – Looks for XXX-XX-XXXX format
    – Cannot contain all zeros
    – Cannot begin with 666 OR 900-999
    ^[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}$Mac Address
    – 6 byte hex separated by colon “:” OR dash “-”
    ^((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$Port Number
    – Matches valid port number in computer network
    – 16 bit
    – Ranges from 0-65535
    [A-Z]{2,}-\d+Jira Ticket Number
    – Looks for format Hyphen-separated Jira project key and ticket issue number
    ^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$Bitcoin Address
    26-35 alphanumeric characters
    – Start with 1 OR 3 OR bc1
    ^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$UUID / {guid}
    – 36 characters
    – 128 bit, represented in 16 octets
    – Looks for format form of  8-4-4-4-12

    Using them in PVA

    Once we create the Entity, and define the pattern for our RegEx. We can now use this validation inside our PVA chat.

    For example, I will test the IP Address pattern

    ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
    

    I have created a topic for testing my RegEx.

    To use the newly created entity, Add a Question, under Identify select your Custom Entity

    Under this, I add a message to confirm its valid.
    (Note, the bot will automatically let the user know if the validation does not match)

    Testing the RegEx

    Okay, drumroll….
    The values I will be testing are

    User InputValid?
    192.168.1.1Valid ✔
    127.0.0.1Valid ✔
    999.55.1.5Not Valid ✖
    Not A IP AddressNot Valid ✖

    Conclusion

    Being able to use Regular Expressions inside Power Virtual Agents can be extremely powerful. And with the above list of common patterns, I hope you find value in this post.

    Thank you, and have a great day!