← English | Česky | ← Zpět na seznam článků
Inventář vlastních agentů přes Microsoft Agent 365
TL;DR — Microsoft uvolnil v Graphu endpoint (
/beta/copilot/admin/catalog/packages), díky kterému Copilot admin konečně vidí všechny vlastní agenty, deklarativní copiloty, boty i Office add-iny ve svém tenantu — napříč Copilot Studiem, Agent Builderem, Teams Toolkitem, SharePointem, AI Foundry i sideloadovanými balíčky — v jednom stránkovaném JSON feedu. Spustili jsme ho proti reálnému tenantu a obraz “agent sprawlu”, který z dat vystoupil, je zajímavější než kterákoli prezentace.Jako pomůcku — abyste viděli, co API skutečně vrací, aniž byste museli napsat jediný řádek kódu — jsme postavili malý read-only dashboard na a365graph.ai-news.cz. Tenhle článek je o Graph API. Dashboard je jen obohacení, ukázka toho, co v JSON řádcích reálně sedí.
Předpoklady. Tohle je admin povrch Microsoft 365 Copilotu, ale licenčně sedí za samostatným produktem. Abyste ho mohli použít, potřebujete:
- Tenant musí mít licenci na Microsoft Agent 365 — podle oficiální dokumentace přístup k Package Management API vyžaduje licenci Microsoft Agent 365. Samotná licence M365 Copilot nestačí.
- Volající uživatel musí mít roli Copilot Admin (nebo Global Admin / Cloud App Admin).
- Token musí být delegated; app-only zatím není podporovaný (viz problém níže).
Oficiální dokumentace: Package Management API overview (preview).

Proč to má smysl řešit
Každý Microsoft 365 tenant, který za posledních 18 měsíců zapnul Copilot, skončil se stejným typem problému:
- Marketing si v Copilot Studiu postavil “Brand Voice Coach”.
- Vývojář publikoval “Knowledge Q&A” přes Agent Builder rovnou z chatu.
- IT Ops nahrál custom-engine agenta pro ServiceNow přes Teams Toolkit jako sideload.
- SharePoint admin vytvořil AgentSkill pro “shrň tento dokument”.
- Někdo z týmu zapnul tři Microsoftem dodávané deklarativní agenty ze storu.
- Dodavatel doručil zabalený bot s manifestem ještě z roku 2024.
Každý žije v jiném builderu, dodává se v jiném SKU a — donedávna — se spravoval přes jiný blade v jiném admin portálu. Když jste se chtěli zeptat “kolik vlastně máme AI agentů a kdo je vlastní?”, museli jste proklikat Teams Admin Center, Power Platform admin centrum, SharePoint admin centrum a CSV, které vám manuálně vyexportoval tenant admin.
Copilot Agent & app Package Management API (preview) tohle řeší na datové úrovni. Nesjednocuje uživatelské prostředí — sjednocuje inventář. Každý balíček, který lze v Microsoft 365 Copilotu nainstalovat, povolit nebo přiřadit, se objeví v jedné stránkované kolekci se stejnou strukturou, stejnými governance poli a stejnou gramatikou filtrů.
A přesně tahle jediná chybějící ingredience bránila tomu, aby se daly dělat seriózní agent governance workflows.
API na jedné obrazovce
Base URL: https://graph.microsoft.com/beta/copilot/admin/catalog/packages
Scope: CopilotPackages.Read.All (delegated — viz problém níže)
Method: GET (list i detail), PATCH (block / unblock), DELETE (odstranění)
List endpoint
GET /beta/copilot/admin/catalog/packages
?$filter=supportedHosts/any(h:h eq 'Copilot')
&$top=100
Vrací standardní OData v4 stránkovanou kolekci: value[] + @odata.nextLink,
dokud nevyčerpáte celou sadu. Žádný $count, žádný $expand, ale $filter
je překvapivě silný.
Detail endpoint
GET /beta/copilot/admin/catalog/packages/{id}
Vrací všechno, co je v list payloadu, plus:
availableTo/deployedToenumy (viz níže — tohle je governance zlatý důl)allowedUsersAndGroups— granulární allow-list: kteří konkrétní uživatelé a skupiny mají od admina povolený přístup k balíčku.acquireUsersAndGroups— skutečný nainstalovaný footprint: uživatelé a skupiny, kteří si balíček opravdu pořídili / nainstalovali. Tohle je váš reálný signál adopce, nedeployedTo.elementDetails[]— manifesty pro každou součást (deklarativní agent, bot, action…) včetně AAD App ID, manifest ID a u deklarativních agentů i inlineinstructionsa blokucapabilities
Na dashboard stačí list endpoint. Detail endpoint potřebujete na opravdovou lifecycle práci: dohledat vlastníka osiřelých agentů, zablokovat balíček podle ID, ověřit verzi manifestu uvnitř.
Mutating endpointy
PATCH /beta/copilot/admin/catalog/packages/{id} { "isBlocked": true }
DELETE /beta/copilot/admin/catalog/packages/{id}
Tohle jsou páky, které admini opravdu chtějí: zastavit chybujícího agenta, aby ho nikdo nemohl nainstalovat, nebo balíček úplně odstranit z tenantu. (Smazání balíčku neodstraní podkladovou Bot resource ani AAD App Registration — jen ho vyhodí z Copilot katalogu.)
Problém, na který vás v dokumentaci nikdo neupozorní: jen delegated
Přečtete si API reference, zkopírujete si client-credentials boilerplate
z poslední Graph automatizace, vložíte si application oprávnění
CopilotPackages.Read.All… a dostanete suché HTTP 403 s tělem, které
neřekne nic užitečného.
Copilot package endpointy nepřijímají app-only tokeny. Vyžadují uživatelský token a ten uživatel musí být Copilot Admin (nebo Global / Cloud App Admin). Microsoft potvrdil, že je to v preview záměrné — API je tvarované pro lidské adminy, kteří spouštějí governance workflows, ne pro neobsluhované service principaly.
Praktický důsledek: cokoli na tomhle stavíte, vyžaduje sign-in. V našem
inventory toolu používáme MSAL device-code flow se serializovaným
on-disk token cachem, takže je to jedno přihlášení na stroj a každý další
běh je už tichý. Příslušný kód žije v agentsreports/auth.py — zhruba
120 řádků, většinou proto, že jsme chtěli mít hezké progress logy ve
smyčce pro polling.
Pokud nemůžete použít device-code (CI pipeline, headless stroj), záložní postup vypadá takhle:
az login --scope https://graph.microsoft.com/CopilotPackages.Read.All \
--allow-no-subscriptions
az account get-access-token \
--scope https://graph.microsoft.com/CopilotPackages.Read.All \
--query accessToken -o tsv > .token
…a načíst token z $COPILOT_TOKEN nebo .token. Tokeny platí hodinu,
takže to stačí na ad-hoc analýzu, ne na dlouho běžící službu.
Rozluštěné schéma
Každý package object má zhruba tuhle strukturu:
{
"id": "guid", // package ID (to pro /packages/{id})
"displayName": "Brand Voice Coach",
"shortDescription": "…",
"publisher": "Contoso Marketing",
"publisherDomain": "contoso.com",
"version": "1.4.2",
"manifestId": "guid", // Teams manifest ID
"appId": "guid", // AAD App Registration ID
"isBlocked": false,
"lastModifiedDateTime": "2026-04-30T12:13:14Z",
"createdDateTime": "2025-09-01T08:00:00Z",
"type": "shared|lob|sideloaded", // původ / lifecycle bucket
"supportedHosts": ["Copilot", "Teams", "Outlook"],
"elementTypes": ["DeclarativeCopilots", "Bots", "AgentSkills"],
"supportedBuilders": ["Copilot Studio", "Agent Builder", "Agents Toolkit",
"SharePoint", "Foundry", "Unspecified"],
"availableTo": "none|some|all", // packageStatus enum
"deployedTo": "none|some|all", // packageStatus enum
"ownerId": "guid|null"
}
Pár polí si zaslouží bližší pohled.
type — lifecycle původ
shared— publikováno přes oficiální builder pipelines (Copilot Studio publish, Agent Builder publish, Foundry agent registration). Počítá se to jako first-class obsah tenantu.lob— line-of-business: privátně nahráno do tenantu, typicky balíček postavený v Teams Toolkitu a uploadovaný přes Teams Admin Center.sideloaded— nainstalováno přímo koncovým uživatelem přes “Upload custom app”, bez povýšení do tenant inventáře. Sideloadované balíčky jsou cesta, kudy se do tenantu dostávají shadow agenti — obcházejí admin review.
V našem reálném tenantu jsme našli shared:212, lob:31, sideloaded:15.
Patnáct sideloadů — každý z nich je potřeba projít a buď povýšit, zablokovat,
nebo smazat.
elementTypes — co je vlastně uvnitř
Jeden balíček může nést víc element definitions najednou. Zajímavé jsou:
DeclarativeCopilots— YAML-ovitý manifest agenta s instructions, conversation starters, capabilities (Graph Connectors, code interpreter, image generator) aactions[](OpenAPI / Power Platform action pluginy). Tohle jsou ti Microsoft 365 Copilot agenti v běžném smyslu slova.AgentMetadatas— boti postavení v Copilot Studiu, jak deklarativní, tak custom-engine. Metadata zabaluje Power Platform environment ID a published bot ID.Bots— klasické Azure Bot Service boty včetně custom-engine agentů (CEAs), kteří mluví na Container App nebo Functions backend. Většina starých “Teams botů” končí tady.AgentSkills— znovupoužitelné definice LLM toolů uložené jako Markdown front-matter v SharePointu, vystavované agentům on-demand. Nové, málo zdokumentované a hodně zajímavé (viz screenshot).AgenticUserTemplates— předpřipravené konverzační šablony pro agentic Copilot UI (jeden v našem tenantu — zjevně někdo experimentoval).
Rozložení v našem reálném tenantu: 94 AgentMetadatas, 86 DeclarativeCopilots, 74 Bots, 3 AgentSkills, 1 AgenticUserTemplate.
availableTo vs deployedTo — dvojice, která řídí váš audit
Tahle dvojice polí je v celém API jednoznačně nejhůř zdokumentovaná — a zároveň ta, na které pro governance nejvíc záleží. Obě pole popisují volbu admina, ne chování uživatelů — což jsme při prvním čtení měli špatně.
| Pole | Podle dokumentace |
|---|---|
availableTo |
“Enum specifikující, kteří uživatelé nebo skupiny v tenantu mají přístup k balíčku” — adminem nastavená access policy. |
deployedTo |
“Enum udávající aktuální rozsah deploymentu balíčku v tenantu” — rozsah, na který ho admin reálně nasadil. |
Obojí používá stejný packageStatus enum: none, some, all
(plus evolvable sentinel unknownFutureValue).
Co jednotlivé kombinace znamenají v praxi:
availableTo=all, deployedTo=all— plošně publikováno. Admin povolil přístup všem A zároveň ho aktivně nasadil všem. Tenant-wide rollout.availableTo=all, deployedTo=some— široký přístup, úzký deploy. Nainstalovat si ho může kdokoli, ale admin ho proaktivně nasadil (např. předpřipnul) jen pro část organizace.availableTo=all, deployedTo=none— opt-in dostupnost. Admin povolil přístup všem, ale sám nikomu nic aktivně nenasadil. Čistě self-install model.availableTo=some, deployedTo=some— pilot s vymezeným rozsahem. Omezený přístup A omezený deployment. Zdravý stav pro agenta před GA. Ověřte, že přiřazené skupiny pořád existují.availableTo=some, deployedTo=none— omezené, opt-in uvnitř skupiny. Admin allow-listoval určité uživatele, ale nasazení nechal na nich.availableTo=none, deployedTo=none— nikdo nemá přístup, nic nenasazeno. Efektivně vyřazené nebo nikdy nepublikované. Kandidát na smazání.availableTo=none, deployedTo=some— nebezpečí. Admin odebral přístup, ale dřívější deployment je pořád na svém místě. Přesně tohle vidíte krátce po administrátorském blocku, než doběhne cleanup. Pokud to vidíte a sámi jste nic neblokovali, něco se pokazilo.
Žádné z těchto polí nevypovídá o adopci. “Používají to opravdu uživatelé?”
vám řekne až acquireUsersAndGroups na detail endpointu — seznam uživatelů
a skupin, kteří si balíček opravdu pořídili. Balíček může být
availableTo=all a acquireUsersAndGroups přesto prázdné; tohle je váš
opravdový signál adopce.
V dashboardu na a365graph.ai-news.cz tuhle dvojici vizualizujeme na záložce Governance — je to zdaleka nejužitečnější jednotlivá věc, na kterou se dá v inventáři dívat.
ownerId — a co znamená null
ownerId je AAD ObjectId uživatele uvedeného jako vlastník balíčku.
V dobře vedeném tenantu má každý vlastní balíček vlastníka. V reálném tenantu
mnoho z nich vlastníka nemá — a to je bug, ne feature:
- U deklarativních agentů vytvořených z chatu (“New Copilot agent”)
builder zapíše agenta do vašeho osobního sandboxu a
ownerIdjste vy. - U shared / publikovaných deklarativních agentů z Copilot Studia je
ownerIdpřevzaté od vlastníka Power Platform environmentu (často service account). - U obsahu od Microsoftu a SharePoint AgentSkills bývá
ownerIdrutinně null. S tím se nedá nic moc dělat. - U third-party botů sideloadovaných přes Teams Toolkit je
ownerIdto, co vývojář nastavil při publishi. Často null. Tohle jsou agenti, na které nemáte komu zavolat, když se něco pokazí.
V našem tenantu: 29 osiřelých agentů s ownerId=null. Většina jsou
Microsoft samples a defaultní “Your developer name”, které někdo zapomněl
změnit. Ale dva byly business-critical boti, jejichž původní vývojář
mezitím odešel z firmy.
Záložka Governance vyplaví přesně tenhle seznam:

manifestId & appId — křížové reference
Každý balíček si nese ještě dvě ID, která umožňují cross-reference s reálnými podkladovými prostředky:
manifestId→ GUID Teams app manifestu (odpovídáidvmanifest.json). Použijte ho na vyhledání balíčku v Teams Admin Center.appId→ Application ID AAD App Registration. Použijte ho na nalezení Azure Bot resource, audit App-permission grantů, dohledání Conditional Access assignments atd.
Pokud auditujete security posture, appId je to, co potřebujete. Řádek
v Graph package vám řekne, že nějaký Copilot custom agent existuje;
odpovídající App Registration vám prozradí, jaká dostal oprávnění, jestli
byl secret rotován a jestli se s ním v poslední době někdo přihlásil.
Co jsme našli v reálném tenantu: 258 packages
Spustili jsme inventory script proti reálnému tenantu. Klíčová čísla:
| Metrika | Počet | Poznámka |
|---|---|---|
| Vlastní packages | 258 | lob + shared + sideloaded |
| Blocked | 1 | isBlocked=true — admin to zablokoval natvrdo |
| Osiřelí agenti | 29 | bez ownerId — bez konkrétního maintainera |
| Zastaralý manifest | 53 | manifestVersion ≤ 1.22 nebo devPreview |
| Copilot-hosted agenti | 146 | žijí v Microsoft 365 Copilot hostu |
| Postavené v Copilot Studiu | 144 | |
| Postavené v Agent Builderu | 61 | |
| Postavené v Teams Toolkitu | 16 | |
| Sideloaded (shadow IT?) | 15 | |
| Bots (Azure Bot Service) | 74 | klasické CEAs + legacy Teams boti |
| Deklarativní copiloti | 86 | moderní povrch Copilot agentů |
Pár závěrů, které překvapily i tým, který tenant provozuje:
-
Skladba platforem je opravdu roztříštěná. Copilot Studio dominuje počtem (144), ale není většinový — 114 packages bylo postaveno jinde, s pěti dalšími buildery v aktivním používání. Jakýkoli governance příběh o “našich Copilot Studio agentech” míjí 44 % povrchu.
-
53 packages se zastaralým manifestem je časovaná bomba ve stylu propadlých TLS certifikátů. Teams app manifest schéma je teď na v1.22 a deklarativní agenti, kteří neobsahují
webApplicationInfo, prostě renderují s prázdnými input fieldy — z Adaptive Cards se na straně klienta vyhazujíInput.Text/Input.ChoiceSet. (Narazili jsme přesně na tenhle problém při stavbě jednoho z in-house agentů.) -
Sideloady samy o sobě nutně špatné nejsou — jsou ale neviditelné pro většinu admin toolingu. Patnáct
sideloadedpackages byli uživatelé, kteří si nahráli vlastní.zippřesatk install. Dva z nich byly prototypy, které se potichu staly důležitými. Žádný z nich nebyl v katalogu Teams Admin Center. Bez tohohle API bychom o jejich existenci nevěděli. -
Povrch “Cowork Skills” je reálný a roste.
AgentSkillselement type je úplně nový — tři v našem tenantu, všechny vystavené přes inline-skills systém, který čte Markdown front-matter ze známého SharePoint folderu. Tohle jsou stavební kostky agent-tool-mesh, který Microsoft postupně nasazuje pod hlavičkou “skills” v Copilot Studiu.

Co API přináší, vizualizováno
Abychom celou věc zhmotnili — a abyste nemuseli sami pouštět inventory script jen kvůli tomu, abyste viděli tvar dat — dali jsme výstup z jednoho reálného tenantu za malý read-only dashboard na a365graph.ai-news.cz.
Dashboard není pointou článku; tou je API. Každá z obrazovek níže je jen jiný pohled na stejný JSON, který endpoint vrací — je tu proto, aby ukázala, jaký governance obraz je teď v dosahu jednoho HTTP volání.
Dashboard — single-screen overview

Čtyři KPI (Custom packages · Blocked · Orphan agents · Outdated manifest) a čtyři breakdowny (Builder · Element Type · Source Type · Host) — všechno odvozené přímo z polí list endpointu. Tohle si Copilot admin teď může vygenerovat kdykoli proti jakémukoli tenantu.
Agents — prohledávatelný inventář

Každý balíček v tenantu jako jeden řádek, prohledávatelný podle
name / publisher / ID a filtrovatelný podle typu, builderu a elementu.
Za každým řádkem sedí kompletní /packages/{id} payload — element
definitions, přiřazení uživatelé, skupiny, verze manifestu. Všechno z API.
Cowork Skills — povrch AgentSkills

Samostatný pohled na element type AgentSkills — nové SharePointem hostované
definice LLM toolů, které Copilot agenti skládají za běhu. Až do tohohle API
neexistoval admin povrch, který by je vůbec dokázal vyjmenovat.
Governance — action queue

Dva seznamy, které mění JSON dump ve workflow: blocked balíčky (řídí se
polem isBlocked) a orphan agenti (řídí se ownerId=null). Obojí padá
z API zadarmo.
Vzory, které jsme zkusili a stojí za přejmutí
Pět drobných patternů, na kterých jsme skončili a které se ukázaly jako vysoce hodnotné:
1. $filter používejte na straně serveru, ne klienta
OData filtry se na tomhle endpointu dobře skládají a server už stránkuje. Netahejte si všech 258 packages a nefiltrujte v Pythonu — pošlete filter.
# "agenti na Microsoft 365 Copilotu modifikovaní za posledních 30 dní"
$filter = (
"supportedHosts/any(h:h eq 'Copilot') and "
"elementTypes/any(e:e eq 'DeclarativeCopilots') and "
"lastModifiedDateTime gt 2026-04-24T00:00:00Z"
)
2. Cachujte device-code refresh token na disk
MSAL nabízí SerializableTokenCache. Persistujte ho do souboru
.token_cache.bin (gitignored), aby další běhy byly tiché. Přidali jsme
malou kontrolu na soubor .token jako fallback pro headless stroje.
3. Retry na 424 i 429
Graph package endpoint někdy škrtí provoz s HTTP 424 místo standardní
- Je to kuriozita beta API. Náš
GraphClientbere obojí jako retryovatelné s exponential backoff:
retryable = {424, 429}
if resp.status_code in retryable or resp.status_code >= 500:
wait = retry_after or min(2 ** attempt, 30)
time.sleep(wait); continue
4. Pro governance vždy --details
List endpoint je rychlý, ale neobsahuje allowedUsersAndGroups,
acquireUsersAndGroups ani elementDetails. Pro skutečnou governance chcete
detail každého balíčku — hlavně acquireUsersAndGroups, které jako jediné
řekne, jestli si balíček opravdu někdo nainstaloval. Počítejte ~2 ms na
volání při warm cache, ~50 ms při cold — pro 258 packages to vyjde řádově
na 15 s end-to-end.
Co API zatím chybí
Endpoint je výborný. Není ale dokonalý.
- Žádný
$countna kolekci. Nevíte, kolik stránek máte, dokud je nevyčerpáte. Není to zásadní problém, ale komplikuje to progress UI. - Žádný
$expandproelementDetails. Vždy je dotahujete přes N+1. Pro 258 packages to znamená 258 dalších HTTP volání. Dá se cachovat, ale je to otravné. - Žádné webhooks / change feed. Na kolekci není
delta()— nemůžete se přihlásit k odběru “řekni mi, když se publikuje nový agent”. Musíte pollovat a diffovat. My to děláme nightly do malého JSON snapshotu v blob storage; ten diff potom pohání Slack alert. devPreviewmanifest agenti se prosakují skrz. Staří deklarativní agenti postavení proti dev-preview manifest schématu se objevují vedle aktuálních packages bez jakékoli vizuální značky. Najít je můžete přesmanifestVersionuvnitřelementDetails[].manifest, ale parse semveru je na vás.- App-only je pořád blokované. Už zmíněné. Den, kdy dorazí app-only varianta, se nightly inventory stane triviální i ze service principalu.
Nic z toho není blocker — je to typ vyladění, které preview API sbírají cestou ke GA.
Co bychom chtěli dál od Microsoftu
Tři přání, v pořadí priority:
- App-only podpora s úzce omezeným oprávněním (
CopilotPackages.Read.Alluž funguje delegated; vydejte app-only variantu). Dnes každá nightly-inventory automatizace potřebuje účet svázaný s konkrétním uživatelem. - Kolekce
delta()na packages endpointu, stejná struktura jakousers/deltaagroups/delta. Tohle jediné přidání by nahradilo 80 % polling-and-diffing infrastruktury, kterou se lidi chystají stavět. - Sub-resource
assignedUsers/$countna každém balíčku. Chceme odpovídat na “který agent je opravdu používaný 10k+ uživateli?” bez nutnosti enumerovat každý assignment.
Vyzkoušejte si to
Jestli máte tenant s licencí na Microsoft Agent 365 a účet s rolí Copilot Admin, nejjednodušší end-to-end volání proti tomuhle API vypadá v podstatě takhle:
az login --scope https://graph.microsoft.com/CopilotPackages.Read.All \
--allow-no-subscriptions
TOKEN=$(az account get-access-token \
--scope https://graph.microsoft.com/CopilotPackages.Read.All \
--query accessToken -o tsv)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://graph.microsoft.com/beta/copilot/admin/catalog/packages?\$top=100" \
| jq '.value | length, .[0]'
Pokud na výstupu uvidíte počet a jeden package objekt — gratulujeme, máte kompletní inventář Copilot agentů svého tenantu v jednom stránkovaném feedu.
Pro o něco pohodlnější obal (MSAL device-code, OData paging, retry na
424/429, generátor Markdown reportu) je Python klient, který jsme použili,
publikovaný jako agentsreports/ v source repu. Existuje proto, abyste
nemuseli přepisovat stejných 200 řádků.
A pokud se chcete podívat, co API dává, ještě než napíšete řádek kódu, živý extract trvale žije na a365graph.ai-news.cz.