Thanks Paolo — that's exactly the path I took, and I want to share what I found because it doesn't hold up in my tenant. I'd appreciate a second look.
Setup: one agent, shared in the Copilot Studio UI with (a) a security group as Viewer and (b) an individual user — call him User A — with more than Viewer rights. The group part works fine: it lands on the bot row as authorizedsecuritygroupids with accesscontrolpolicy: 2. It's the individual share I can't find anywhere.
What I ran, and what came back: 1. GET /api/data/v9.2/principalobjectaccessset?$filter=objectid eq <botid> and objecttypecode eq 'bot'
→ exactly one row: the auto-created owner team, accessrightsmask: 786487, inheritedaccessrightsmask: 0. No row for User A.
2. GET /api/data/v9.2/RetrieveSharedPrincipalsAndAccess(Target=@t)?@t={'@odata.id':'bots(<botid>)'}
→ the same single team, nothing more.
3. GET /api/data/v9.2/teams(<teamid>)?$select=name,teamtype,membershiptype&$expand=teammembership_association($select=fullname,domainname)
→ teamtype: 0 (owner team), azureactivedirectoryobjectid: null, and membership is the agent owner only. User A is not a member.
4. GET /api/data/v9.2/systemusers(<userAId>)/Microsoft.Dynamics.CRM.RetrievePrincipalAccess(Target=@t)?@t={'@odata.id':'bots(<botid>)'}
→ {"AccessRights": "None"} — for a user the Share pane shows with edit rights.
5. I then pulled the entire principalobjectaccessset table with no filter. It contains exactly one objecttypecode: 'bot' row per agent, every one of them principaltypecode: 'team'. There is not a single systemuser principal against any bot in the whole table.
Ruling out permissions. I know that's the usual explanation, so I checked it directly: the same unfiltered query does return principaltypecode: 'systemuser' rows for other object types — e.g. a connector record shared directly to a named user with accessrightsmask: 17 — as well as principaltypecode: 'organization' rows on other tables. So the app user can read user-level POA rows; there simply aren't any for bots. I also granted Share on the bot table at Organization scope and re-ran everything: byte-identical results.
The observation I can't get past. I compared User A against User B, who was never shared this agent. They are indistinguishable in Dataverse: same security roles (Environment Maker + Basic User, identical role IDs), same business unit, same islicensed/caltype/accessmode, same team memberships, no POA rows on the bot for either, and RetrievePrincipalAccess returns None for both.were expressed anywhere in the Dataverse security model, those twousers would have to differ somewhere — and they don't.
So my question, narrowed: if individual-user agent shares are not or systemuser, where are they persisted, and is there any readsurface for them? Specifically:
- Is there a Dataverse table other than principalobjectaccessset that holds them? (I found nothing bot-share-related when enumerating EntityDefinitions.)
- Or are they held in the Copilot Studio / Power Platform control se — and if so, is there any documented or supported endpoint thatreads them? The Power Platform API Bots operations don't appear to expose a permissions operation.
- Does the storage differ between the two share types — Editor / c Viewer / chat access? The docs say collaborative authoring adds theuser to the agent's Dataverse team, but in my tenant the owner team contains only the owner even though User A has more than Viewer rights.
- On the CoE Starter Kit suggestion: does its agent inventory actuser shares for agents? My reading is that the permission-sync flowscover apps and flows, and the Copilot Studio side is inventory plus telemetry only. If it does collect them, which flow/table — that would point me at the underlying API.
I'm after static state, not audit events — I know BotUpdateOperation-BotShare shows up in Purview, but replaying an event log isn't a reliable way to
reconstruct current access.