Skip to the content.

← 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:

Oficiální dokumentace: Package Management API overview (preview).

Souhrnný dashboard s přehledem 258 vlastních Copilot packages

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:

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:

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

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:

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:

Žá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:

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:

Governance záložka: blocked a orphan agents

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:

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:

  1. 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.

  2. 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ů.)

  3. Sideloady samy o sobě nutně špatné nejsou — jsou ale neviditelné pro většinu admin toolingu. Patnáct sideloaded packages byli uživatelé, kteří si nahráli vlastní .zip přes atk 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.

  4. Povrch “Cowork Skills” je reálný a roste. AgentSkills element 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.

Cowork Skills: znovupoužitelné definice LLM toolů v SharePointu

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

Souhrnný dashboard s přehledem 258 vlastních Copilot packages

Č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ář

Inventory tabulka: každý vlastní Copilot package v tenantu

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

AgentSkills: znovupoužitelné definice LLM skillů napříč agenty

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

Governance: blocked + orphan agenti vyžadující pozornost admina

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í

  1. Je to kuriozita beta API. Náš GraphClient bere 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ý.

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:

  1. App-only podpora s úzce omezeným oprávněním (CopilotPackages.Read.All už funguje delegated; vydejte app-only variantu). Dnes každá nightly-inventory automatizace potřebuje účet svázaný s konkrétním uživatelem.
  2. Kolekce delta() na packages endpointu, stejná struktura jako users/delta a groups/delta. Tohle jediné přidání by nahradilo 80 % polling-and-diffing infrastruktury, kterou se lidi chystají stavět.
  3. Sub-resource assignedUsers/$count na 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.


← English  |  ← Zpět na seznam článků