Category: Artificial Intelligence in Business

  • How to Build Your First AI Agent in Copilot Studio

    How to Build Your First AI Agent in Copilot Studio

    Step by step diagram showing how to build an AI agent in Copilot Studio, from instructions to knowledge to tools to publishing

    Microsoft published a guide on how to build an AI agent aimed at anyone, and the framework is genuinely sound: define the job, give the agent knowledge, give it tools, test it, let it run. What the article does not give you is the clicks. So this is how to build an AI agent in Copilot Studio following that exact recipe, end to end. By the end you have a working internal FAQ agent that can also create a ticket, published to Teams. I built a variant of this internally last quarter, and the framework holds up. The gaps between the steps are where it gets interesting.

    Step 1: Define One Job Before You Build an AI Agent in Copilot Studio

    Microsoft’s guide says start with a clear purpose. In practice this means the Instructions field, and this is where most first builds go wrong. People write vibes: “You are a helpful assistant for IT questions.” That constrains nothing. Write scope enforcement instead:

    You answer questions about internal IT policies using only the attached knowledge sources. If the answer is not in the knowledge sources, say so and offer to create a support ticket. Do not answer questions about HR, payroll, or anything outside IT. Do not guess at policy details.

    Keep it under 500 tokens. I covered why in the business skills post: instruction sets that grow past a few hundred tokens start degrading reliability. One job. Tight boundaries. Explicit refusal behavior.

    Step 2: Attach a Knowledge Source the Agent Can Cite

    In the agent’s Knowledge section, add your SharePoint site. Use the site URL, not a document library deep link, and check that the files are PDF or Word. The indexer handles those well. It handles scanned images inside PDFs poorly, and you will not find out until the agent confidently answers from the two readable pages and ignores the rest.

    Turn on “Use general knowledge” only if you have a reason. For an internal policy agent, leave it off. Grounded-only answers with citations beat fluent answers with no source. If you are choosing between SharePoint and Dataverse here, I compared them in a separate post. For a first build, SharePoint is the shorter path. If you plan to give the agent its own identity and audit trail inside Dataverse, Entra Agent ID gives every Dataverse agent its own identity and is worth reading before you commit to the data layer.

    Step 3: Give It One Tool With a Power Automate Flow

    Microsoft’s guide calls this “giving the agent the ability to act.” Concretely: build a flow with the When an agent calls the flow trigger, add two text inputs (ticketTitle, ticketDescription), create the ticket row wherever your ticketing lives, and end with Respond to the agent returning the ticket number and status. Do not return a bare “success” flag. Return state the agent can reason about on the next turn. The Copilot Studio docs cover the wiring, but they undersell the description field.

    Then add the flow as a tool on the agent, and write the tool description as a retrieval hint, not documentation: Creates an IT support ticket when the user reports a problem that the knowledge sources cannot resolve. The orchestrator scores this against user input to decide when to call it. I went deep on this in How to Design Tool Definitions for Copilot Studio Agents. One tool for now. Resist adding more until the first one behaves.

    Step 4: Test in the Canvas With the Activity Map Open

    Open the test pane and turn on the activity map. Now test the way real users will actually talk, not the way you wish they would. Three categories: questions the knowledge sources answer, requests that should trigger the ticket flow, and deliberately bad inputs. “my thing is broken.” “can you help.” A question about payroll that should get refused.

    The activity map shows you which knowledge source or tool the orchestrator picked and why. When it picks wrong, the fix is almost always the tool description or the instructions, not the model. This is the step people consistently skip, and it is the one that decides whether the agent survives contact with real users. I wrote about why agents fail in production after passing testing, and clean test conversations are the whole story. Testers ask questions they already know the agent can answer. Real users do not.

    Step 5: Publish to Teams and Watch the First Week

    Publish, then add the Microsoft Teams channel. Start with “available to specific users” and pick a pilot group of ten people, not the whole org. Then read the transcripts in the Analytics section every day for the first week. Not the satisfaction score. The actual conversations. You will find phrasings you never tested, a refusal that fired too aggressively, and at least one question your knowledge source cannot answer that it obviously should. That first week of transcripts is worth more than any amount of pre-launch testing. If generative answers start overriding your scoped topics during this phase, the fix is covered in Stop Copilot Studio Generative Answers From Hijacking Your Topics.

    The Working Agent and the Pitfall That Breaks Most First Builds

    Final state: one agent, one scoped job, one SharePoint knowledge source, one flow that creates tickets, published to a Teams pilot group. Microsoft’s five-part recipe maps cleanly onto this. The guide is right that anyone can follow the framework.

    The pitfall: skipping step 4 because the happy path worked twice in the test canvas. In my experience the agents that embarrass their builders are never the ones that failed in testing. They are the ones that were never tested against inputs designed to break them. Budget as much time for hostile testing as for building. The building is the easy half.

    Frequently Asked Questions

    How do I build an AI agent in Copilot Studio for the first time?

    Start by writing a tight Instructions prompt that gives the agent one clear job and explicit boundaries, then attach a knowledge source like SharePoint, and connect a single Power Automate flow as a tool. Test it before publishing to a channel like Teams. Keeping the scope narrow on your first build makes it much easier to identify where things go wrong.

    What should I write in the Instructions field when creating a Copilot Studio agent?

    Instead of writing a vague description, define exactly what the agent can and cannot do, which sources it should use, and how it should respond when it does not know the answer. Keeping the instruction set under 500 tokens helps maintain reliability, as longer prompts can reduce consistency.

    When should I turn on general knowledge in Copilot Studio?

    Only enable general knowledge if your agent genuinely needs to draw on information beyond your attached sources. For internal use cases like a policy or FAQ agent, leaving it off produces more trustworthy answers because responses are grounded in your own documents and can be cited.

    Why does my Copilot Studio agent give incomplete answers from PDF files?

    The knowledge indexer in Copilot Studio handles standard PDF and Word files well but struggles with scanned images embedded inside PDFs. If your documents contain scanned pages rather than real text, the agent may only read the portions it can process and skip the rest without flagging it.

    Source: How to build an AI agent: A simple guide for anyone (Microsoft AI Blog).

  • How to Turn HTTP Actions Into a Power Automate Custom Connector

    How to Turn HTTP Actions Into a Power Automate Custom Connector

    I ran into this building something internally: twelve flows, all calling the same internal REST API through the HTTP action, all with the same API key pasted into a header field. The key rotated. Eleven flows broke overnight, and the twelfth broke a week later because nobody remembered it existed. The fix is a Power Automate custom connector. By the end of this walkthrough you will have one connector with connection-level authentication, typed outputs in the dynamic content picker, and zero secrets sitting in flow definitions.

    One thing up front so nobody is surprised: the HTTP action is premium and custom connectors are premium. You are not saving on licensing here. If you want to understand exactly what triggers premium licensing before you ship, How to Run a Power Platform Licensing Audit Before You Ship walks through flagging premium connectors and mapping user licenses. You are saving on secret sprawl, duplicated Parse JSON actions, and the maintenance cost of every flow knowing the raw URL.

    Step 1: Capture the working request

    Before you touch the connector wizard, get one successful call working in a plain HTTP action. You need four things written down: the method, the full URL, every header the API requires, and a real response body. Run the flow once and copy the raw JSON from the run history outputs. Save it somewhere. You will paste it into the connector definition in Step 4, and the quality of your dynamic content depends entirely on how representative this sample is. If a field can be null, make sure your sample shows it populated, or the schema inference will type it wrong.

    Step 2: Create the Power Automate custom connector

    Go to make.powerautomate.com, then Custom connectors under Data, then New custom connector. If you have an OpenAPI file or a Postman collection, import it and skip ahead. For an internal API you probably do not, so pick Create from blank. On the General tab set the scheme to HTTPS, the host to your API domain (api.internal.example.com, no protocol prefix), and the base URL to the shared path segment, for example /v2. Everything you put here is one edit away when the API moves. That is the whole point. The custom connector docs on Microsoft Learn cover the import paths if you go that route.

    Step 3: Move the key into connection-level security

    On the Security tab, choose API Key as the authentication type. Set the parameter label to something a human understands, the parameter name to the exact header the API expects (x-api-key in my case), and the location to Header. This is the step that pays for everything else. The key is now entered once per connection, stored encrypted, and never appears in the flow definition, the export package, or the run history. When the key rotates, you update the connection. Every flow using it picks up the change. Compare that to my eleven broken flows.

    If your API uses OAuth 2.0, the same tab handles it, but you will need an app registration and a redirect URL. API key is the fast path for internal services.

    Step 4: Define the action with Import from sample

    On the Definition tab, click New action. Give it a summary and an operation ID that reads like a verb, because that text is what shows up in the action picker. Then hit Import from sample, set the method and relative path (/invoices/search), and paste the request body you captured in Step 1. Do the same for the response: open the default response, paste your saved JSON, and let it infer the schema.

    This response schema is what kills the Parse JSON actions. Every field in your sample becomes a typed token in dynamic content. Instead of body('HTTP')?['data']?['invoiceNumber'] in a dozen flows, you get invoiceNumber as a pickable token. Untyped payloads always come back to bite you at the consumption end, and that same discipline around schema and parameter definitions applies when you are building tools for AI agents — How to Design Tool Definitions for Copilot Studio Agents covers exactly how typed outputs affect whether an agent selects and uses a tool correctly.

    Step 5: Test the connection and swap the flows

    Use the Test tab. Create a connection, enter the API key, fire the operation, and check the returned status code against what your plain HTTP action produced. Then go through your flows one by one: add the connector action, remap the inputs, repoint downstream references from the old body('HTTP') expressions to the new typed tokens, delete the HTTP action last. Do not delete first. You want the old expression text visible while you remap.

    Since connectors are solution-aware, put the connector inside a solution before you build against it if this ever needs to move environments. Retrofitting that later is painful — understanding how solution layers decide which customization wins makes it much clearer why getting the connector into a solution early avoids hard-to-debug conflicts later.

    The final state and the one pitfall

    End result: one connector, one connection per environment, secrets out of flow definitions, typed outputs everywhere, and a single place to edit when the API changes. The maintenance profile of those twelve flows went from twelve edits to one. In my experience this is the single highest-return refactor available in a flow estate that grew organically.

    The pitfall: custom connector requests have a hard timeout of 2 minutes. A plain HTTP action will happily wait longer with the right retry settings. If your API has a slow endpoint, a report generator, a bulk export, anything that can run past 120 seconds, keep that one call on the HTTP action or redesign it as an async polling pattern. I learned that one the hard way, staring at a 504 that the same request never produced from the raw action.

    Frequently Asked Questions

    What is a Power Automate custom connector and why would I use one?

    A Power Automate custom connector is a reusable wrapper around an external or internal API that lets you call it from flows without hardcoding URLs, headers, or secrets. It centralises authentication and request configuration in one place, so when something like an API key changes, you update it once rather than hunting through every flow that uses the raw HTTP action.

    How do I move an API key out of my flow definitions and into a secure location?

    In a custom connector, you can configure API Key authentication at the connection level on the Security tab. You specify the exact header name the API expects, and the key is entered once when creating a connection, stored encrypted, and never written into the flow definition itself.

    When should I replace HTTP actions in my flows with a custom connector?

    If you have multiple flows calling the same API, sharing the same headers or secrets, or duplicating Parse JSON actions to handle responses, a custom connector is worth building. It reduces secret sprawl, cuts down on repeated configuration, and makes maintenance much easier when API details change.

    How do I get typed outputs and dynamic content when building a custom connector?

    You need to provide a real response body sample from a successful API call, which the connector wizard uses to infer the response schema. The quality of the dynamic content picker depends on how representative that sample is, so make sure any fields that can contain values are populated in the sample rather than null.

  • Inside Solution Layers: How Power Platform Decides What Wins

    Inside Solution Layers: How Power Platform Decides What Wins

    Diagram of stacked Power Platform solution layers with an unmanaged layer sitting on top of managed layers

    Most people assume that importing a managed solution overwrites whatever was there before. It does not. Dataverse keeps every version of every component in a stack, then computes which one you actually see at runtime. That mechanism, Power Platform solution layers, is behind half of the “my update did not show up” tickets I have seen. It is also the thing that quietly decides whether a pro-dev team and a group of citizen devs can work in the same environment without destroying each other’s work.

    The Surface Behaviour: The Update That Never Arrives

    The classic symptom looks like this. A pro-dev team ships version 2.0 of a managed solution with an updated main form on the Account table. The import completes with zero errors. The pipeline is green. And the form in the target environment still shows the old layout.

    The first instinct is to blame caching, then the pipeline, then the solution packager. I burned an afternoon in exactly that rabbit hole before I looked at the layer stack. The real culprit was a maker who had edited that form directly in the target environment three months earlier. That single edit created an unmanaged customization sitting above the managed solution, and it masked every managed update that came afterwards. Version 2.0 landed exactly where it was supposed to. Nobody could see it.

    How Power Platform Solution Layers Resolve What You See

    Every solution-aware component in Dataverse carries an ordered stack. At the bottom sits the system layer, the out-of-box definition Microsoft ships. Above that sit managed layers, one per managed solution that touches the component, ordered by installation sequence. And on top, always, sits the unmanaged layer, which holds any direct customization made in that environment.

    At runtime, Dataverse walks the stack from the top down. For most component types the rule is simple: the topmost layer that defines the component wins entirely. There is no partial blending for a view or a plugin step. Forms and site maps are the notable exceptions, because they merge across layers, which is its own source of surprises.

    You can inspect this yourself. In the maker portal, select a component inside a solution and open Solution layers from the command bar. It shows you the full stack and lets you diff what each layer changed. The official documentation on solution layers covers the merge rules per component type, and it is worth reading properly rather than skimming, because the behaviour is not uniform.

    The Edge Cases That Cost Real Time

    The unmanaged layer never expires. If someone makes a direct edit in production, that layer masks the managed layers below it until someone explicitly removes it with the remove active customizations operation. You can import version 3, version 4, version 5, and nothing visible changes. The imports are not failing. They are landing underneath a mask.

    Layer order is install order, not version number and not intent. If two managed solutions both customize the same view, the one installed second sits higher and wins, even if the first one carries the change your team actually cares about. I have watched teams reorder their deployment sequence to fix a display bug without understanding why it worked, which means the fix was luck, not engineering.

    Form merging deserves its own warning. Because forms merge across layers instead of replacing wholesale, you can end up with a rendered form that no single team designed. A section from the base solution, a tab from a second solution, a field placement from an unmanaged tweak. It looks like corruption. It is the merge algorithm doing exactly what it is documented to do.

    Why This Is the Contract Between Pro Devs and Makers

    The reason I care about this mechanism is not ALM purity. It is that the layer stack is the actual contract that lets pro-dev and low/no-code work coexist. Pro devs ship managed solutions through pipelines and source control. Makers build in a dev environment inside their own solution, which deploys as its own managed layer sitting above the pro-dev layer. Both sides can move independently, and the stack keeps the boundaries honest.

    That contract holds under exactly one condition: no unmanaged edits in test or production. Every direct tweak in a downstream environment is a silent mask over every future deployment. The trade-off is real, and I will not pretend otherwise. Makers lose the ability to hotfix a label in production in thirty seconds. That feels slow until you have spent a day proving that a green import changed nothing, and then it feels cheap. Before you reach that point, running a Power Platform licensing audit across your environments can surface other hidden mismatches that compound the same class of problem.

    I made a similar point about ownership in my post on Dataverse business skills: logic nobody can find is logic nobody can fix. Unmanaged layers in production are the same failure mode wearing a different jacket. In my experience, teams that check the layer stack before blaming the pipeline resolve these tickets in minutes instead of days. The mechanism is not hidden. Most people just never look at it. The same discipline applies when variables behave unexpectedly at scale — as I covered in why variables break when you turn on concurrency in Power Automate, hidden state that looks correct during authoring can silently produce wrong results at runtime for the exact same reason: execution order is not what you assumed.

    Frequently Asked Questions

    What are Power Platform solution layers?

    Power Platform solution layers are an ordered stack that Dataverse maintains for every solution-aware component, starting with Microsoft’s base system layer, followed by managed solution layers, and topped by any unmanaged customizations made directly in the environment. At runtime, Dataverse works down the stack from the top to determine which version of a component is actually displayed or used.

    Why does my managed solution update not show up after importing?

    A direct customization made in the target environment creates an unmanaged layer that sits above all managed layers and takes priority over them. Even if your managed solution imported successfully, that unmanaged layer masks the changes you shipped, making it appear as though the update never arrived.

    How do I see which solution layer is controlling a component in Power Platform?

    In the maker portal, select the component inside a solution and choose Solution layers from the command bar. This shows you the full layer stack for that component and lets you compare what each layer has changed.

    When should I be concerned about unmanaged customizations in a managed environment?

    Any time a maker edits a component directly in an environment that receives managed solutions, an unmanaged layer is created that will permanently override updates shipped through those managed solutions. This is especially important in shared or production environments where pro-dev and citizen dev teams are working alongside each other.

  • Attended vs Unattended RPA for Power Automate Desktop Flows

    Attended vs Unattended RPA for Power Automate Desktop Flows

    Two computer setups side by side illustrating attended vs unattended RPA in Power Automate desktop flows

    You built the desktop flow. It works. Now comes the question that actually decides the economics of the whole project: does it run on a person’s machine while they watch, or on a dedicated machine at 3 AM with nobody around? That is the attended vs unattended RPA decision, and I keep seeing teams get it wrong in both directions. Some pay for unattended bots to run flows that need a human answer halfway through. Others burn an employee’s afternoon babysitting a flow that should have been scheduled on a VM.

    I have built both kinds. Here is how I compare them now, dimension by dimension.

    The Attended vs Unattended Cost Gap

    Attended RPA is included in the Power Automate Premium per-user licence, which sits around $15 per user per month. If a person is signed in and triggers the flow on their own machine, that licence covers it.

    Unattended is a different animal. The unattended process licence runs around $150 per bot per month, and if you want Microsoft to host the machine for you, the hosted process option lands around $215 per month. Want two flows running concurrently on the same machine? That is another unattended licence. This is the ten-times gap, and it is where How to Run a Power Platform Licensing Audit Before You Ship earns its keep. I have watched estimates double after someone finally read the concurrency rules.

    Machine and Session Requirements

    Attended flows need an active, unlocked Windows session. The user is signed in, the screen is visible, and the flow drives the UI in front of them. Lock the screen mid-run and the flow dies. That is not a bug. It is the definition of attended.

    Unattended flows create their own session on a machine where nobody is signed in. That means the machine must allow it: no other active session on that account, credentials stored in the connection, and on standard Windows 10 or 11 you get exactly one unattended run at a time per machine. Multiple parallel sessions need Windows Server or multiple machines in a machine group. The Microsoft Learn requirements for unattended runs are strict, and every requirement you skip becomes a 4 AM failure.

    Failure Modes

    Attended flows fail loudly and recover cheaply. The user is right there. A selector breaks, a popup appears, the flow stops, the human clicks past it and reruns. Annoying, but the blast radius is one person’s afternoon.

    Unattended flows fail silently and recover expensively. Nobody sees the unexpected dialog box. The run sits there until timeout, the queue backs up, and you find out from the downstream team the next morning. Everything covered in Selectors vs Image Recognition for Power Automate Desktop Flows matters three times more unattended, because there is no human to absorb the surprise. If you go unattended, you also need error handling, screenshots on failure, and alerting. Budget that build time. It is not optional.

    Human in the Loop

    Some processes genuinely need a person mid-flow. A judgment call, an approval, a value read off a paper document. Attended handles this naturally with input dialogs. Unattended cannot do it at all, and I have seen teams contort a process into ugly two-phase flows just to force it unattended. If a human decision sits in the middle of your process, that is your answer. Do not fight it.

    Throughput Ceiling

    This is where unattended wins without argument. An attended flow runs when a human is available, which means business hours, one run at a time, competing with the person’s actual job. An unattended machine group with three VMs runs around the clock and processes a queue in parallel. If your volume is hundreds of transactions a day, attended is not a real option no matter how cheap the licence looks. Concurrency also introduces its own gotchas inside the flows themselves — why variables break when you turn on concurrency in Power Automate is worth reading before you scale a machine group.

    At a Glance

    Dimension Attended Unattended
    Licence cost ~$15/user/month (Premium) ~$150/bot/month, ~$215 hosted
    Session User signed in, unlocked Bot creates its own session
    Failure recovery Human fixes it live Needs alerting and retry logic
    Mid-flow human input Native Not possible
    Throughput Business hours, serial 24/7, parallel with machine groups

    Choose Attended If, Choose Unattended If

    Choose attended if the process needs human judgment mid-run, if volume is low enough that a person triggering it is not a bottleneck, or if you are still stabilising the flow and want a human catching the surprises. It is also the honest choice for a pilot. Prove the flow works attended before paying unattended prices.

    Choose unattended if volume demands overnight or parallel runs, if the process is fully deterministic with no human decision anywhere, and if you have already invested in error handling and monitoring. And before either: check whether the target system has an API. As I have argued before, a lot of desktop flows should not exist at all. The best RPA licence is the one you never had to buy. More of my reasoning on these trade-offs is on my LinkedIn.

    Frequently Asked Questions

    What is the difference between attended vs unattended RPA in Power Automate Desktop?

    Attended RPA runs on a user’s machine while they are actively signed in, with the flow triggered by the person in front of it. Unattended RPA runs on a dedicated machine with no one present, typically on a schedule, creating its own session automatically. The key distinction is whether a human needs to be available during the run.

    How much does unattended RPA cost compared to attended in Power Automate?

    Attended automation is covered under the Power Automate Premium per-user licence at around $15 per user per month. Unattended requires a separate process licence at roughly $150 per bot per month, rising to around $215 if you use Microsoft-hosted machines. Running flows concurrently requires additional licences, which can cause costs to climb quickly.

    When should I use attended RPA instead of unattended for desktop flows?

    Use attended RPA when the process requires a human decision or input at some point during the run, or when the volume does not justify the higher licence cost. Unattended is better suited for high-volume, fully automated processes that can run overnight or in bulk without any human involvement.

    Why does my unattended desktop flow fail when no one is watching?

    Unattended flows can fail silently because there is no user present to handle unexpected popups, broken selectors, or login prompts. Unlike attended flows where a person can intervene immediately, unattended runs may sit idle until they time out, causing queues to back up before anyone notices the issue.

  • Entra Agent ID Gives Every Dataverse Agent Its Own Identity

    Entra Agent ID Gives Every Dataverse Agent Its Own Identity

    Diagram of Entra Agent ID Dataverse identities assigning security roles to individual AI agents

    On 6 August 2026, Microsoft announced Entra Agent ID for Dataverse. Every AI agent that touches Dataverse can now get its own dedicated identity in Microsoft Entra, show up as a first-class agent user in the environment, and receive security roles like any other principal. It matters because it retires the worst pattern in agent deployments today: agents doing real work under a borrowed human or service account with broad permissions and no attributable audit trail.

    Entra Agent ID makes agents first-class users in Dataverse

    The mechanics are straightforward, which is exactly what you want from an identity feature. An agent gets an Entra Agent ID, which is a real directory object, not a tag on someone else’s account. That identity maps to an agent user inside Dataverse. From there, everything an admin already knows how to do applies. You assign security roles scoped to exactly the tables and privileges the agent needs. You see the agent’s activity in audit logs under its own name. You manage its lifecycle in the same admin surfaces where you manage users, app registrations, and service principals.

    None of this is a new concept. Service principals have existed for years. What is new is that the plumbing now reaches agents specifically, so a Copilot Studio agent writing to Dataverse does not need to impersonate anyone. The identity is the agent’s own, end to end.

    Borrowed credentials were the governance debt every agent deployment carried

    I keep hearing the same story from people at other organisations rolling out agents. The agent works. It creates records, updates statuses, closes cases. Then security or internal audit asks a simple question: who updated this record? And the answer is a human’s name attached to actions no human took. Usually the maker’s account, because that is what the connection was created with. Sometimes a shared service account with System Administrator, because someone hit a permissions error six months ago and fixed it the fast way.

    That pattern is not a small smell. It breaks least privilege, because the agent inherits everything the borrowed account can do. It breaks auditability, because the log tells you a person did something they never did. And it breaks lifecycle management, because when the maker leaves the company and their account gets disabled, the agent dies with it. Poof. Production automation down because of an HR event.

    I made a version of this mistake myself building an early internal agent. The connection ran under my account, and every record it touched carried my name. Harmless until someone asked why I had modified two hundred records at 3 AM. I had not. The agent had. Explaining that distinction to an auditor without a dedicated identity is not a conversation you want twice.

    This also completes a picture Microsoft has been assembling all year. Dataverse as the agent data platform gave agents skills, knowledge sources, and feedback loops. What it did not have was an answer to the identity question. Skills tell an agent what to do. Identity determines what it is allowed to do and who is accountable when it does it. You cannot govern the first without the second.

    Agents that write to production Dataverse should migrate first

    Not every agent needs this on day one. A read-only agent answering questions from a knowledge source under a scoped service account is a low-grade risk. The agents that should move first are the ones writing to production data. Anything creating or updating records in tables that feed reporting, billing, or compliance processes. Those are the deployments where the audit trail question is not hypothetical, it is one incident away.

    The trade-off is real work. Each agent identity needs a security role designed for it, and designing least-privilege roles takes longer than granting System Administrator and moving on. You also add lifecycle overhead: more principals to review, more roles to maintain. I think that cost is worth paying, for the same reason I argued when the Dataverse plugin for coding agents shipped that running it as System Administrator was the wrong setup. Broad permissions are always faster until the day they are catastrophically not. The same principle applies when you are running a Power Platform licensing audit before you ship: knowing exactly which identities hold which permissions is far easier to audit up front than to untangle after the fact.

    If I were planning a rollout, I would inventory every agent connection today and flag any that resolve to a human account. That list is your migration order. In my experience, the teams that treat identity as a prerequisite ship slower in week one and faster every week after, because they never hit the retrofit project. If you are also thinking about how agent tools should be scoped and named so that least-privilege roles map cleanly to actual capabilities, How to Design Tool Definitions for Copilot Studio Agents is a useful companion read.

    Identity was the last missing layer under enterprise agents, and now the interesting question is how fast admins make it mandatory.

    Source: Secured and Governed your AI Agents: Microsoft Entra Agent ID for Dataverse (Microsoft Power Platform Blog).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • How to Design Tool Definitions for Copilot Studio Agents

    How to Design Tool Definitions for Copilot Studio Agents

    Diagram of well-structured Copilot Studio agent tools with clear names, descriptions, and typed parameters

    The most common failure I see in agent builds is not the model and not the orchestrator. It is the tool definition. Copilot Studio agent tools get selected by a runtime relevance score, not by a human reading a list, and a definition written like internal documentation produces silent misrouting. This walkthrough takes one tool from a vague definition to one the planner can bind against reliably. By the end you have a repeatable checklist you can apply to every tool on every agent.

    If you want the mechanics behind why this works, I covered the scoring behavior in how Copilot Studio tool selection works under the hood. This post is the practical half.

    Step 1: Name the tool as a verb phrase

    Rename the tool from a system name to an action. SAPQuery tells the planner nothing. GetOpenInvoicesForCustomer tells it exactly which user intents should route here. The name is scored alongside the description, so it is free relevance signal. Do not waste it on the name of the backend system. The trade-off: verb-phrase names are longer and less pretty in your solution explorer. Accept that. You are optimizing for the planner, not the maker portal.

    Step 2: Write the description as a retrieval hint

    This is where most Copilot Studio agent tools go wrong. The orchestrator scores your description against the user’s actual words, so write it in the vocabulary users type, not the vocabulary your architecture diagram uses.

    Bad: Calls the finance API endpoint to retrieve invoice records from the ERP integration layer.

    Good: Returns unpaid or overdue invoices for a specific customer. Use when the user asks about outstanding balances, open invoices, what a customer owes, or payment status.

    The second version contains the phrases real users produce. Anthropic’s guidance on tool use for Claude lands on the same principle: describe when to use the tool, not how it is implemented. This holds across every function calling stack I have worked with, not just Copilot Studio. If you are thinking about how topic descriptions interact with the same orchestration layer, Stop Copilot Studio Generative Answers From Hijacking Your Topics covers the overlap and where the fix lives.

    Step 3: Give parameters binding-friendly names and descriptions

    A parameter named id of type string gives the planner nothing concrete to bind against. When the user says “show me what Contoso owes,” the planner has to guess which fragment of the utterance belongs in id. Rename it to customerAccountNumber and describe it precisely: The customer's account number in the format CUST-00000. If the user gives a company name instead, resolve it with SearchCustomerByName first.

    That last sentence matters. Parameter descriptions are one of the few places you can teach the planner tool sequencing without writing orchestration logic. Use enums wherever the value set is closed. status as a free string invites hallucinated values; an enum of open, paid, overdue removes the guesswork entirely. The Microsoft Learn documentation for Copilot Studio covers the input schema options, but it will not tell you to write them this defensively. Experience will.

    Step 4: Return full state, not a status flag

    Design the output for the agent’s next turn, not for a log file. A tool that returns {"status": "success"} leaves the agent with nothing to reason about. If the user then asks “which of those is overdue by more than 30 days,” the agent has no data and either calls the tool again or makes something up. Return the invoice list with dates, amounts, and statuses in the response. Yes, that costs tokens. It is cheaper than a second tool call and far cheaper than a confident wrong answer. I traced several production incidents back to exactly this pattern when I wrote about why agents fail in production after passing testing. The same principle applies at the agent architecture level — as I argued in The Model Is the Cheapest Part of Every Enterprise AI Agent, grounding data and tool design are where reliability is actually won or lost.

    Step 5: Test with overlapping intents, not happy paths

    Do not test by asking the question the tool was built for. Test the boundaries between tools. If you have GetOpenInvoicesForCustomer and GetOrderHistoryForCustomer, ask something ambiguous like “what’s the situation with Contoso’s account” ten times and watch which tool fires. If routing flips between runs, your descriptions overlap and you need to sharpen the “use when” clauses until they carve up the intent space cleanly. Also test with the wrong entity format on purpose. Give a company name where an account number is expected and confirm the planner chains through the lookup tool instead of stuffing garbage into the parameter.

    The finished state

    You end up with a tool that has a verb-phrase name, a description written in user vocabulary with explicit “use when” phrases, typed parameters with formats and enums, and an output rich enough to support follow-up questions. Apply the same pass to every tool on the agent and misrouting drops sharply. In my experience, this single pass fixes more agent reliability problems than any prompt engineering on the instructions.

    One pitfall to watch: do not keep adding well-designed tools forever. Past roughly 10 to 15 tools on a single agent, the relevance signal gets noisy no matter how clean your definitions are. At that point the fix is splitting the agent, not another description rewrite.

    Frequently Asked Questions

    How do I write good descriptions for Copilot Studio agent tools?

    Write descriptions using the vocabulary your users actually type, not technical or architectural language. Include phrases like ‘use when the user asks about…’ so the orchestrator can match the tool to real user intents. Describing when to use a tool, rather than how it works internally, consistently improves routing accuracy.

    Why does my Copilot Studio agent keep routing to the wrong tool?

    Tool selection is driven by a relevance score calculated at runtime, not a manual lookup, so vague or technical definitions cause silent misrouting. If your tool names and descriptions are written for developers rather than the planner, the orchestrator cannot reliably match them to user input. Rewriting names as verb phrases and descriptions in plain user language usually resolves the problem.

    What is the best way to name tools in a Copilot Studio agent?

    Name tools as verb phrases that describe a clear action, such as GetOpenInvoicesForCustomer rather than SAPQuery. The name is scored alongside the description, so it carries relevance signal and should reflect user intent rather than the underlying system or API.

    How do I define parameters so a Copilot Studio agent can fill them correctly?

    Give each parameter a descriptive name and a clear explanation of what value it expects and where that value comes from in the conversation. A parameter named ‘id’ with no context forces the planner to guess, while a name like ‘customerName’ with a description reduces binding errors and makes extraction from user utterances more reliable.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Microsoft Previews a Security Agent for Power Pages

    Microsoft Previews a Security Agent for Power Pages

    AI security agent scanning a Power Pages site configuration, illustrating the Power Pages Security Agent preview

    On 29 July 2026, Microsoft announced the Power Pages Security Agent preview, an AI assistant built into the Power Pages experience that can scan a site’s security configuration, diagnose access issues, and walk makers through hardening steps in plain language. It matters because Power Pages security settings are spread across authentication providers, table permissions, web roles, page permissions, site visibility, and WAF settings, and until now nothing sat on top of all of it to tell you what you actually exposed.

    The Power Pages Security Agent Preview Puts Scans, Diagnosis, and Fixes in One Chat

    Concretely, the agent does three things. You can ask it to run a security scan of the site and it inspects the live configuration: which tables are reachable, which table permissions apply, how web roles map to them, whether anonymous access is enabled anywhere it should not be. You can ask it diagnostic questions like why a specific user can see a specific record, and it traces the answer through the actual permission chain instead of you clicking through four different screens to reconstruct it manually. And you can ask it to help harden the site, where it proposes changes to things like authentication settings and access restrictions and explains what each one does before you apply it.

    The important detail is that it reads your real site configuration. This is the same design decision that made the Dataverse plugin for coding agents useful: grounding in the actual environment instead of guessing from training data. A generic chatbot can tell you what table permissions are. This agent can tell you that your Contact table has a Global scope read permission attached to the Anonymous Users web role, on your site, right now.

    Fragmented Settings Are Why Portals Leak, and This Targets the Real Cause

    The model is not the interesting part here. The consolidation is.

    Power Pages sites do not ship with exposed tables because makers are careless. They ship that way because the security surface is fragmented. Authentication lives in one place. Table permissions live in another. Web roles, page permissions, IP restrictions, and site visibility each have their own screen, and none of them gives you a single view of what an anonymous visitor can actually reach. I have watched experienced people get this wrong, because the feedback loop is invisible. You do not find out a table is exposed until someone crafts the right OData URL, and by then it is an incident, not a config review.

    An agent that inspects the whole configuration and surfaces misconfigurations conversationally attacks that fragmentation directly. That is a better fix than another documentation page, because the problem was never that the security documentation is missing. The problem is that applying it requires holding six screens in your head at once. If you are building agents or automations alongside these portals, running a Power Platform licensing audit before you ship is the same class of discipline: catch the configuration gaps before they become incidents.

    Now the honest caveat. This is a preview, and a security tool that gives a wrong answer confidently is worse than no tool at all. If the agent tells you a table is locked down and it is not, you have converted uncertainty into false confidence, which is the most dangerous state a portal can be in. Until this thing has a track record, I would treat every scan result as a guided audit, not a sign-off. Verify what it flags, and verify a sample of what it clears. I have been burned enough times by preview features behaving differently under edge cases to extend that trust slowly.

    Inherited Sites and Anonymous-Access Audits Should Get Scanned First

    Where this fits: the first candidates are inherited sites. Every enterprise has at least one portal built three years ago by someone who has since left, where nobody currently on the team can explain the web role setup. Pointing the agent at that site and asking what an anonymous user can access is worth doing on day one of the preview reaching your tenant. Not because the agent is infallible, but because the alternative is that nobody audits it at all.

    The second candidate is any site with anonymous access enabled on purpose. Public-facing portals with self-registration are exactly where a Global scope permission accidentally attached to the wrong role does the most damage. A conversational audit lowers the cost of checking from an afternoon to ten minutes, and things that cost ten minutes actually get done.

    Who benefits most is the maker in the middle: someone comfortable building the portal but not deep enough in the security model to trace a permission chain by hand. Pro devs who already know where every setting lives will use it as a faster lookup. Citizen devs building portals without understanding table permissions were the risk this feature exists to reduce. The broader pattern here connects to something worth keeping in mind: the model is the cheapest part of every enterprise AI agent, and this feature is a good example of that — the value is in the grounding and the consolidation, not the underlying AI capability itself.

    Security tooling for low/no-code platforms is finally starting to assume the builder is not a security engineer, and that assumption is overdue.

    Source: Announcing the Power Pages Security Agent (Preview): Your AI Partner for Site Security (Microsoft Power Platform Blog).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Microsoft Ships the Dataverse Plugin to OpenAI’s Codex Marketplace

    Microsoft Ships the Dataverse Plugin to OpenAI’s Codex Marketplace

    Dataverse plugin Codex marketplace expansion showing a coding agent querying live schema

    On 28 July 2026, Microsoft shipped the Dataverse plugin for coding agents to the OpenAI and Codex marketplaces. The announcement is short, but the Dataverse plugin Codex marketplace expansion means any agent built on OpenAI’s coding stack can now query live Dataverse schema, table metadata, and real data instead of guessing column names from two-year-old tutorial content in its training set.

    I wrote about the Cursor marketplace drop when it happened. That felt like a test balloon. This is the follow-through, and it tells you something about where Microsoft thinks the moat actually sits.

    What a Codex Agent Gets: Live Schema, Metadata, and Query Tools

    The plugin gives a Codex-based agent the same tool surface the Copilot and Cursor versions get. It can list tables in a connected environment, inspect column logical names, walk relationships, read option set values, and run queries against real records. That sounds mundane until you have watched a coding agent confidently generate a plugin against new_customer_id when the actual column is cr7a2_customerid. Without live metadata, the output looks correct and fails on deploy. With it, the code is diffable against reality.

    The hallucination problem I described when the plugin first shipped was never a model quality problem. It was a missing context layer at build time. Codex agents had no sanctioned way to see your schema, so they interpolated from public tutorials. This closes that gap for anyone whose org standardized on OpenAI’s tooling.

    The Codex Marketplace Expansion Signals Dataverse Is the Moat

    Think about what Microsoft is doing here. They are distributing a first-party grounding tool into a direct competitor’s agent ecosystem. GitHub Copilot competes with Codex. Microsoft shipped there anyway.

    That only makes sense if you believe the coding assistant is interchangeable and the data platform is not. Microsoft is betting that developers will switch agents every eighteen months but their organisations will keep business data in Dataverse for a decade. Agent-neutral distribution is the correct call under that assumption. Cursor was proof of concept. OpenAI and Codex confirm the pattern: follow the developers, do not try to pull them back into VS Code.

    There is a quieter governance win too. Developers were already wiring community MCP servers from random GitHub repos into their agents, and platform teams had zero visibility into any of it. A first-party plugin installed from a known marketplace leaves an auditable trail. That matters more inside a large enterprise than any individual feature. If you want to understand the protocol underneath tools like this, How MCP Actually Works Under the Hood When an Agent Calls a Tool walks through the JSON-RPC handshake and capability negotiation in detail.

    Pro-Code Teams on Non-Microsoft Agents Are the Real Audience

    This is not a citizen dev feature. The audience is teams writing Dataverse plugins, custom APIs, PCF controls, and complex flows in source control, whose org happened to standardize on OpenAI’s agent stack instead of GitHub Copilot. Those teams were previously stuck choosing between an ungrounded agent or an unsanctioned community tool. Now they get the first-party path without changing editors.

    Two honest caveats. First, the setup mistake I keep seeing has not gone away: people connect the plugin with System Administrator credentials pointed at production. The sane configuration is still a dedicated app user with a least-privilege role scoped to a dev environment. The marketplace install being one click makes the lazy setup faster too.

    Second, this closes the hallucination gap and nothing else. Environment permissions, DLP policies, and security roles behave exactly as they did before. The plugin does not grant the agent any access your app user does not have, and it does not stop you from misconfiguring that app user. In my experience, the teams that get burned are the ones who treat schema grounding as a security boundary. It is not. It is a correctness tool. Schema grounding also sits inside a broader cost and measurement story — The Model Is the Cheapest Part of Every Enterprise AI Agent makes the case that grounding data and connector governance are where the real budget and hours go.

    If your team builds against Dataverse from Codex today, install this and you get real hallucination reduction on schema-dependent code. If your governance story is not sorted, you also get one more thing to register and scope. Both are true.

    The coding agents will keep changing names. The platforms that ship their grounding everywhere are the ones planning to still be here when they do.

    Source: Dataverse Plugin for Coding Agents: OpenAI and Codex Marketplace Expansion (Microsoft Power Platform Blog).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Stop Copilot Studio Generative Answers From Hijacking Your Topics

    Stop Copilot Studio Generative Answers From Hijacking Your Topics

    Copilot Studio settings screen showing generative answers overriding a topic with a weak description

    I keep seeing the same complaint in the community: someone builds a solid topic in Copilot Studio, with an adaptive card, a Power Automate action, exact wording that legal signed off on. It works for weeks. Then generative orchestration gets switched on and suddenly Copilot Studio generative answers take over. The agent paraphrases a SharePoint document instead of running the topic. Same question, wrong path.

    The usual reaction is to pile on more trigger phrases. That does nothing. Under generative orchestration, trigger phrases are not how routing works anymore.

    The problem with generative answers stealing topic-based answers

    With classic orchestration, topics fire on trigger phrase matching. With generative orchestration, the model picks between your topics, your tools, and your knowledge sources by scoring their descriptions against the user’s message. Trigger phrases become a weak secondary signal at best.

    Most topics I look at have no description, or an auto-generated one like “This topic handles expense questions.” That is a losing hand. Your knowledge source is a 40-page policy PDF full of relevant vocabulary. The orchestrator scores “how do I get reimbursed for a client dinner” against that PDF and against your one-line description, and the PDF wins. Generative answers fire, your scripted topic sits idle, and the user gets a paraphrase instead of the exact approved flow.

    It is the same silent misrouting failure mode I wrote about with multi-agent orchestration routing. Nothing errors. Nothing logs a warning. The agent just confidently takes the wrong path.

    The fix

    Write the topic description as a retrieval hint, not documentation. Open the topic, click Details in the top bar, and fill the Description field. The orchestrator reads this field to decide routing, so it needs to contain the words users actually type.

    Weak version:

    Handles expense-related questions.

    Version that wins routing:

    Use this topic for any question about submitting expense reports, reimbursement, expense limits, receipts, client dinners, travel costs, or mileage claims. Always use this topic instead of searching documents when the user asks how to claim or submit an expense.

    Two things matter here. First, the vocabulary overlap: name the concrete nouns users will type, because the scoring is lexical-ish relevance, not comprehension. Second, the explicit priority instruction at the end. “Always use this topic instead of searching documents” is blunt, and blunt works. Microsoft documents this behavior in the generative orchestration docs, but the priority-instruction trick is the part most people miss.

    If you want to understand exactly how the orchestrator scores and selects between topics and tools, How Copilot Studio Agent Tool Selection Actually Works Under the Hood walks through the scoring pass in detail and explains why descriptions carry so much weight.

    One trade-off to be honest about. A description that broad will pull in some borderline questions that generative answers would have handled fine. For compliance-sensitive flows, that is the trade you want. Exact approved wording beats a fluent paraphrase every time. Before you ship any of this, it is also worth running a Power Platform licensing audit to confirm the connectors and flows your topic triggers are covered under the right licenses for every user who will hit this path.

    Test it with five phrasings you did not use in the description. If the topic fires on all five, you are done. If not, add the missing nouns and retest. In my experience this takes ten minutes and fixes ninety percent of “my topic stopped working” reports.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Tino Cuellar Joining Anthropic’s Board Is a Governance Signal

    Tino Cuellar Joining Anthropic’s Board Is a Governance Signal

    Tino Cuellar joining the Anthropic board of directors, representing AI governance and oversight

    On 3 August 2026, Anthropic announced that Mariano-Florentino (Tino) Cuellar, president of the Carnegie Endowment for International Peace and a former California Supreme Court justice, is joining the Anthropic board of directors. The appointment came through the company’s Long-Term Benefit Trust, the governance mechanism Anthropic built specifically to seat directors who are not financially tied to the company. For anyone deploying these models inside an enterprise, this matters because board composition sits upstream of every usage policy and deployment constraint that eventually lands in your agents.

    This is not a product release. There is no benchmark table to read twice. But I think it deserves the same attention as one, because governance moves like this one shape what the products are allowed to do two years from now.

    Tino Cuellar Joins Anthropic’s Board of Directors as a Jurist, Not an Investor

    Look at who typically sits on the board of an AI lab. Founders, lead investors, maybe an operator from a previous portfolio win. The incentive structure is uniform: grow the company, protect the equity. That is normal and I am not pretending it is scandalous. It is just narrow.

    Cuellar breaks the pattern. He spent years as a justice on the California Supreme Court, taught at Stanford, worked on domestic policy in the Obama White House, and now runs the Carnegie Endowment, one of the oldest international affairs think tanks in existence. His entire career is about how institutions constrain power, across borders, under law. Putting someone with that profile in a director seat, with actual voting rights rather than an advisory title, is a different move from hiring a policy VP. Advisors get consulted. Directors get to say no.

    The Long-Term Benefit Trust Doing What It Was Designed For

    The mechanism matters more than the name. Anthropic set up the Long-Term Benefit Trust years ago: a group of trustees with no financial stake in the company, holding the power to elect a growing share of the board. When it launched, plenty of people dismissed it as governance theater. A structure that exists on paper but never gets exercised is exactly that.

    This appointment is the structure getting exercised. The LTBT chose a jurist and international policy scholar, not another tech operator, and the company seated him. That is the difference between a governance document and a governance practice. I made a similar argument when Anthropic published the Fable 5 rollback postmortem: the public artifact is the contract. A trust that visibly places independent directors is a stronger commitment than any responsible AI pledge on a marketing page, because it is structurally hard to walk back. Anthropic has shown a similar instinct in how it approaches safety methodology — the Fable jailbreak safeguards framework is another example of a public commitment designed to be hard to quietly abandon.

    The trade-off is real, and worth naming. Independent directors with mandates beyond shareholder value can slow a company down. They can block a lucrative deployment. If you are an investor, this is friction. If you are an enterprise betting a multi-year agent architecture on this vendor, that friction is partly the point.

    What Board Composition Tells You When You Are Betting on a Model Vendor

    People I talk to at other organisations have started asking governance questions during vendor evaluation, not just capability questions. Who decides when a model gets pulled? What happens to our deployment if the safety team loses an internal argument? Those questions used to get answered with a shrug and a link to a trust center page. Board composition gives you something more concrete to point at.

    The chain is longer than it looks but it is real. Board priorities shape company policy. Company policy shapes the usage terms and safety frameworks. Those frameworks shape what the API will and will not do, which shapes what your Claude-backed agents can be trusted with in production. As I have written before, the model is the cheapest part of every enterprise AI agent. The expensive part is everything around it, and a chunk of that surrounding structure is set by people in a boardroom you will never see.

    None of this makes Anthropic immune to bad decisions. A board seat is a signal, not a guarantee, and I would still evaluate the models on evals, postmortems, and deprecation behavior. But when two vendors score similarly on capability, the one that voluntarily installed a former supreme court justice through an independent trust has told you something the other one has not.

    As models take on more autonomous, agentic work, expect governance structure to become a line item in enterprise vendor evaluations, right next to latency and price per token.

    Source: Tino Cuellar (Anthropic).

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn