Ordre 20260912T193441Z-7358817909. Steg 1 var ikke transformen, men å rette
roadmapens R13-gate og få den ratifisert. Gaten `grep -rl "Cosmo"
skills/*/references -> 0` var usann på to uavhengige måter:
1. Ordren fanget den første: 451 av forekomstene er Azure Cosmos DB, ekte
produktinnhold. Diskriminatoren er ikke bokstaven «s» — `Cosmos <norsk
substantiv>` er genitiv av personaen (`### Cosmos tonalitet`), mens
`Cosmos DB`/`CosmosClient`/`cosmos_ru` er produkt.
2. Denne økten fant den andre: 132 persona-forekomster ligger i prosa,
tabeller, dialog-replikker og proveniens-linjer. Heading-nøytralisering
kan ikke nå dem, så «0 persona» er uoppnåelig også under den ratifiserte
formen. Operatøren ratifiserte alternativ A: gaten speiler formen, og de
132 bokføres til R13b/R14.
Tre korreksjoner av premisser som sto i ordren og STATE:
«ca 320 produkt» -> 451 (case-sensitivt nett manglet 327 lowercase
TOC-ankre + 99 identifikatorer; sann nevner 1 638)
«169 headinger» -> 401. 169 var `^## For Cosmo`-prefikset (168) og var
internt inkonsistent med sin egen topp-variant (204)
«417 matcher ingen
populasjon» -> 417 er cosmo-headinger utenfor kodefences; briefens
nevner var reell hele tiden
Fence-bevissthet er målt skadelig, ikke nødvendig: begge toggle-regler er
gale på dette korpuset (naiv toggle skjuler en ekte heading i
chain-of-thought-prompting.md, CommonMark-regelen ubalanserer
service-level-documentation-dr.md). Fence-agnostisk deteksjon finner 401
heading-linjer i nøyaktig de samme 40 variantene som fence-bevisst finner
400 i — ingen kodeblokk-linje er byte-identisk til en persona-heading. Derfor
nøkles transformen på 40 enumererte heading-tekster og ignorerer fences. En
ukjent variant kaster; en slug-kollisjon kaster. Ingenting auto-fikses.
TOC-en regenereres ikke, den rettes kirurgisk: alle 327 persona-lenker hadde
lenketekst lik én av de 40 heading-tekstene og anker lik slugify av den
(327/327, 0 avvik), så heading og TOC-entry skrives i samme operasjon og
ingen mellomtilstand etterlater en død lenke.
Ratifisert målform: `For Cosmo`, `For Cosmo Skyberg` og `For arkitekten
(Cosmo)` konvergerer på `For arkitekten`. To filer kolliderte og er adjudisert
ved å lese dem, ikke ved regel.
Verifisering (alle 7 kriterier fra ordren):
G1 persona på heading-linjer 401 -> 0
G2 døde fragmentlenker 1 -> 1 (pre-eksisterende, unntatt)
G3 produkt-forekomster 451 -> 451; `Cosmos DB|Azure Cosmos` 308 = 308
de 3 kun-produkt-filene byte-identiske
nettet validert begge veier injisert persona feller G1; genitiv feller G1;
produkt-heading og de 3 filene passerer
hele diffen 802 heading-linjer + 654 TOC-linjer, ANNET = 0
linjeantall 728 lagt til = 728 slettet
suite 1120/1120 (1097 + 23 nye)
validate-plugin 250 PASS / 0 FAIL
stikkprøve 10 filer, alle 5 skills, inkl. de 3 mest
produkt-tunge (26/20/19) — kun heading+TOC
Utenfor scope, urørt: de 4 SKILL.md, de 23 commands, CLAUDE.md, README.md,
NOTICE.md, docs/ (alt R14).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
372 lines
15 KiB
Markdown
372 lines
15 KiB
Markdown
# Copilot Agent Integration Patterns
|
|
|
|
**Last updated:** 2026-02
|
|
**Status:** GA
|
|
**Category:** Agent Orchestration & Automation
|
|
**Type:** reference
|
|
|
|
---
|
|
|
|
## Innhold
|
|
|
|
- [Introduksjon](#introduksjon)
|
|
- [Kjernekomponenter](#kjernekomponenter)
|
|
- [Copilot Studio Agent Binding](#copilot-studio-agent-binding)
|
|
- [Message Format Adaptation](#message-format-adaptation)
|
|
- [Capability Exposure](#capability-exposure)
|
|
- [User Context Passing](#user-context-passing)
|
|
- [Session Management](#session-management)
|
|
- [Declarative vs Custom Engine Integration](#declarative-vs-custom-engine-integration)
|
|
- [Norsk offentlig sektor](#norsk-offentlig-sektor)
|
|
- [Beslutningsrammeverk](#beslutningsrammeverk)
|
|
- [For arkitekten](#for-arkitekten)
|
|
|
|
## Introduksjon
|
|
|
|
Integrasjon av agenter med Microsoft Copilot-økosystemet -- Copilot Studio, Microsoft 365 Copilot og Copilot Chat -- gir agenter tilgang til millioner av brukere gjennom kjente grensesnitt i Teams, Outlook, Word og andre Microsoft 365-applikasjoner. Denne integrasjonen utnytter Copilots orkestrator, grunnmodeller og sikkerhetstjenester, slik at agenter arver enterprise-grade compliance, RAI-standarder og governance uten ekstra utviklingsarbeid.
|
|
|
|
Microsoft tilbyr to hovedveier for agent-integrasjon med Copilot: **Declarative agents** som konfigurerer Copilots innebygde orkestrator med tilpassede instruksjoner, kunnskapskilder og handlinger, og **Custom engine agents** som bruker egne modeller og orkestreringslogikk men eksponeres gjennom Copilots brukergrensesnitt. Valget mellom disse avhenger av behovet for kontroll, fleksibilitet og integrasjonsgrad med Microsoft 365-datakilder.
|
|
|
|
Copilot Studio fungerer som det primære utviklingsverktøyet for begge agenttyper, med low-code-verktøy for forretningsbrukere og pro-code-muligheter via Microsoft 365 Agents Toolkit for utviklere. Semantic Kernel gir programmatisk integrasjon gjennom `CopilotStudioAgent`-klassen som kobler Copilot Studio-agenter direkte inn i multi-agent orkestreringsflyter.
|
|
|
|
## Kjernekomponenter
|
|
|
|
| Komponent | Formål | Teknologi |
|
|
|-----------|--------|-----------|
|
|
| Copilot Orchestrator | Orkestrer agentforespørsler i M365 | Microsoft 365 Copilot platform |
|
|
| Declarative Agent Manifest | Konfigurer agentens kapabiliteter | JSON manifest-filer |
|
|
| Copilot Studio | Low-code agentutvikling | Microsoft Copilot Studio |
|
|
| Agents Toolkit | Pro-code agentutvikling | VS Code / Visual Studio extension |
|
|
| CopilotStudioAgent (SK) | Programmatisk integrasjon | Semantic Kernel Agent Framework |
|
|
| Graph Connectors | Tilgang til organisasjonsdata | Microsoft Graph, Copilot connectors |
|
|
|
|
## Copilot Studio Agent Binding
|
|
|
|
### Declarative Agent arkitektur
|
|
|
|
```
|
|
┌───────────────────────────────────────────────┐
|
|
│ Microsoft 365 Copilot │
|
|
│ ┌─────────────────────────────────────────┐ │
|
|
│ │ Copilot Orchestrator │ │
|
|
│ │ - Intent classification │ │
|
|
│ │ - Grounding via Microsoft Graph │ │
|
|
│ │ - RAI filters │ │
|
|
│ └───────────────┬─────────────────────────┘ │
|
|
│ │ │
|
|
│ ┌───────────────▼─────────────────────────┐ │
|
|
│ │ Declarative Agent Config │ │
|
|
│ │ ┌──────────┬──────────┬──────────┐ │ │
|
|
│ │ │Custom │Custom │Custom │ │ │
|
|
│ │ │Instruc- │Knowledge │Actions │ │ │
|
|
│ │ │tions │(SP, Graph│(API │ │ │
|
|
│ │ │ │Connectors│Plugins) │ │ │
|
|
│ │ └──────────┴──────────┴──────────┘ │ │
|
|
│ └─────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Surfacing: Teams, Outlook, Word, Excel │
|
|
└───────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Agent manifest-fil
|
|
|
|
```json
|
|
{
|
|
"name": "SaksbehandlingAgent",
|
|
"description": "Hjelper saksbehandlere med å finne relevant regelverk og tidligere vedtak",
|
|
"instructions": "Du er en assistent for saksbehandlere i norsk offentlig sektor. Du hjelper med å finne relevant regelverk, tidligere vedtak og saksbehandlingsrutiner. Svar alltid med kildehenvisning. Følg Forvaltningslovens prinsipper.",
|
|
"capabilities": [
|
|
{
|
|
"name": "WebSearch",
|
|
"disabled": true
|
|
},
|
|
{
|
|
"name": "CodeInterpreter",
|
|
"disabled": true
|
|
},
|
|
{
|
|
"name": "GraphicArt",
|
|
"disabled": true
|
|
}
|
|
],
|
|
"conversation_starters": [
|
|
{
|
|
"title": "Finn regelverk",
|
|
"text": "Hva sier regelverket om..."
|
|
},
|
|
{
|
|
"title": "Tidligere vedtak",
|
|
"text": "Finn lignende saker der..."
|
|
}
|
|
],
|
|
"actions": [
|
|
{
|
|
"id": "searchRegulations",
|
|
"file": "regulations-api-plugin.json"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Message Format Adaptation
|
|
|
|
### Adaptive Cards for rike svar
|
|
|
|
```json
|
|
{
|
|
"type": "AdaptiveCard",
|
|
"version": "1.5",
|
|
"body": [
|
|
{
|
|
"type": "TextBlock",
|
|
"text": "Saksbehandlingsresultat",
|
|
"weight": "Bolder",
|
|
"size": "Large"
|
|
},
|
|
{
|
|
"type": "FactSet",
|
|
"facts": [
|
|
{"title": "Saksnummer", "value": "${saksnummer}"},
|
|
{"title": "Status", "value": "${status}"},
|
|
{"title": "Regelverk", "value": "${regelverk}"}
|
|
]
|
|
},
|
|
{
|
|
"type": "ActionSet",
|
|
"actions": [
|
|
{
|
|
"type": "Action.OpenUrl",
|
|
"title": "Se fullstendig sak",
|
|
"url": "${sakUrl}"
|
|
},
|
|
{
|
|
"type": "Action.Submit",
|
|
"title": "Send til godkjenning",
|
|
"data": {"action": "approve", "sakId": "${sakId}"}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Copilot-kompatibelt responsformat
|
|
|
|
```python
|
|
# Formater agentrespons for Copilot-kontekst
|
|
class CopilotResponseFormatter:
|
|
def format_for_copilot(self, agent_response: dict) -> dict:
|
|
"""Tilpass agentrespons til Copilot-forventninger"""
|
|
return {
|
|
"text": agent_response["content"],
|
|
"citations": [
|
|
{
|
|
"title": ref["title"],
|
|
"url": ref["url"],
|
|
"content": ref["snippet"]
|
|
}
|
|
for ref in agent_response.get("references", [])
|
|
],
|
|
"followup_prompts": agent_response.get("suggestions", []),
|
|
"confidence": agent_response.get("confidence", None),
|
|
}
|
|
```
|
|
|
|
## Capability Exposure
|
|
|
|
### API Plugin for Copilot
|
|
|
|
```json
|
|
{
|
|
"schema_version": "v2.1",
|
|
"name_for_human": "Regelverk-søk",
|
|
"description_for_human": "Søk i norske lover og forskrifter",
|
|
"description_for_model": "Bruk denne pluginen når brukeren spør om norske lover, forskrifter eller regelverk. Pluginen søker i Lovdata og returnerer relevante paragrafer.",
|
|
"auth": {
|
|
"type": "oauth",
|
|
"authorization_url": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize",
|
|
"token_url": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
|
|
"scopes": "api://regulations-api/.default"
|
|
},
|
|
"api": {
|
|
"type": "openapi",
|
|
"url": "https://api.regulations.no/openapi.json"
|
|
},
|
|
"functions": [
|
|
{
|
|
"name": "searchRegulations",
|
|
"description": "Søk etter lover og forskrifter",
|
|
"parameters": {
|
|
"query": {
|
|
"type": "string",
|
|
"description": "Søketekst for lover og forskrifter"
|
|
},
|
|
"category": {
|
|
"type": "string",
|
|
"enum": ["lov", "forskrift", "rundskriv"],
|
|
"description": "Type regulering"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## User Context Passing
|
|
|
|
### Semantic Kernel CopilotStudioAgent
|
|
|
|
```python
|
|
from semantic_kernel.agents import CopilotStudioAgent
|
|
|
|
# Opprett CopilotStudioAgent for bruk i multi-agent orkestrering
|
|
agent = CopilotStudioAgent(
|
|
name="CopilotStudioHRAgent",
|
|
# Kobles til en eksisterende Copilot Studio-agent
|
|
agent_id="<copilot-studio-agent-id>",
|
|
endpoint="<copilot-studio-endpoint>",
|
|
# Brukerkontekst passeres automatisk
|
|
)
|
|
|
|
# Bruk i Semantic Kernel orkestrering
|
|
thread = CopilotStudioAgentThread()
|
|
async for response in agent.invoke(
|
|
messages=[ChatMessageContent(
|
|
role=AuthorRole.User,
|
|
content="Hva er min feriesaldo?"
|
|
)],
|
|
thread=thread
|
|
):
|
|
print(response.content)
|
|
```
|
|
|
|
### Brukerkontekst fra Microsoft Graph
|
|
|
|
```csharp
|
|
// Berik agent-kontekst med brukerdata fra Graph
|
|
public class UserContextEnricher
|
|
{
|
|
private readonly GraphServiceClient _graphClient;
|
|
|
|
public async Task<UserContext> EnrichContext(string userId)
|
|
{
|
|
var user = await _graphClient.Users[userId]
|
|
.GetAsync(config =>
|
|
{
|
|
config.QueryParameters.Select = new[]
|
|
{
|
|
"displayName", "department", "jobTitle",
|
|
"officeLocation", "preferredLanguage"
|
|
};
|
|
});
|
|
|
|
return new UserContext
|
|
{
|
|
Name = user.DisplayName,
|
|
Department = user.Department,
|
|
Role = user.JobTitle,
|
|
Location = user.OfficeLocation,
|
|
Language = user.PreferredLanguage ?? "nb-NO",
|
|
// Brukes i agent-instruksjoner for personalisering
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
## Session Management
|
|
|
|
### Copilot conversation threading
|
|
|
|
```python
|
|
# Håndter samtalehistorikk på tvers av Copilot-sesjoner
|
|
class CopilotSessionManager:
|
|
def __init__(self, cosmos_client):
|
|
self.container = cosmos_client.get_database_client("agents") \
|
|
.get_container_client("sessions")
|
|
|
|
async def get_or_create_session(
|
|
self, user_id: str, agent_id: str
|
|
) -> dict:
|
|
"""Hent eller opprett sesjon for bruker-agent-par"""
|
|
try:
|
|
session = await self.container.read_item(
|
|
item=f"{user_id}:{agent_id}",
|
|
partition_key=user_id
|
|
)
|
|
except Exception:
|
|
session = {
|
|
"id": f"{user_id}:{agent_id}",
|
|
"user_id": user_id,
|
|
"agent_id": agent_id,
|
|
"created_at": datetime.utcnow().isoformat(),
|
|
"message_count": 0,
|
|
"context_summary": "",
|
|
"ttl": 86400 # 24 timer
|
|
}
|
|
await self.container.upsert_item(session)
|
|
|
|
return session
|
|
|
|
async def update_context_summary(
|
|
self, session_id: str, user_id: str, new_summary: str
|
|
):
|
|
"""Oppdater komprimert kontekst for langvarige samtaler"""
|
|
await self.container.patch_item(
|
|
item=session_id,
|
|
partition_key=user_id,
|
|
patch_operations=[
|
|
{"op": "replace", "path": "/context_summary",
|
|
"value": new_summary},
|
|
{"op": "incr", "path": "/message_count", "value": 1}
|
|
]
|
|
)
|
|
```
|
|
|
|
## Declarative vs Custom Engine Integration
|
|
|
|
| Aspekt | Declarative Agent | Custom Engine Agent |
|
|
|--------|-------------------|---------------------|
|
|
| Hosting | Copilots orkestrator | Egne servere/Azure |
|
|
| Modell | Copilots foundation model | Valgfri modell |
|
|
| Kanaler | Teams, Outlook, Word, Excel | Teams, Copilot, eksterne kanaler |
|
|
| Utvikling | Low-code (Copilot Studio) / Pro-code (Agents Toolkit) | Full kode-kontroll |
|
|
| Compliance | Arver M365 compliance | Eget ansvar |
|
|
| Begrensninger | Sekvensiell prosessering, begrenset orkestrering | Ingen begrensninger |
|
|
| Governance | M365 admin center | Egne governance-verktøy |
|
|
|
|
## Norsk offentlig sektor
|
|
|
|
| Aspekt | Krav | Implementering |
|
|
|--------|------|----------------|
|
|
| Datalokalitet | Schrems II | Copilot EU Data Boundary + tenant-config |
|
|
| M365-lisens | Copilot-lisens per bruker | Kostnadsvurdering per avdeling |
|
|
| Innholdssikkerhet | Ansvarlig AI | Copilots innebygde RAI-filtre |
|
|
| Tilgangsstyring | eInnsyn | Admin center agent governance |
|
|
| Språk | Norsk (bokmål/nynorsk) | Custom instruksjoner på norsk |
|
|
|
|
### Deployment-mønster for offentlig sektor
|
|
|
|
```
|
|
1. Pilot: 5-10 brukere med sideloaded agent
|
|
2. Avdeling: Publiser til organizational catalog
|
|
3. Etat: Utvidet tilgang via M365 admin center
|
|
4. Tverrgående: Vurder commercial marketplace (for felles løsninger)
|
|
```
|
|
|
|
## Beslutningsrammeverk
|
|
|
|
| Scenario | Anbefaling | Begrunnelse |
|
|
|----------|------------|-------------|
|
|
| Enkel FAQ-bot med M365-data | Declarative agent via Copilot Studio | Raskest å implementere, arver M365 |
|
|
| Avansert orkestrering, egne modeller | Custom engine agent via Agents Toolkit | Full kontroll over logikk og modeller |
|
|
| Multi-agent som inkluderer Copilot | CopilotStudioAgent i Semantic Kernel | Kombiner Copilot med egne agenter |
|
|
| ISV-løsning for flere kunder | Commercial Marketplace-publisering | Bred distribusjon, M365 integrasjon |
|
|
| Intern pilot med eksisterende data | Declarative agent med SharePoint-kunnskap | Utnytter eksisterende infrastruktur |
|
|
|
|
## For arkitekten
|
|
|
|
- **Declarative agents er startpunktet** for de fleste M365-integrerte scenarier -- de arver Copilots orkestrator, compliance og distribusjon. Gå til custom engine kun ved reelle begrensninger.
|
|
- **CopilotStudioAgent i Semantic Kernel** er broen mellom Copilot-verdenen og programmatisk agent-orkestrering -- bruk den for å inkludere Copilot Studio-agenter i multi-agent-systemer.
|
|
- **API plugins** er nøkkelen til å gi agenter handlingsevne utover samtale -- definer OpenAPI-spesifikasjoner for alle virksomhetssystemer agenten skal interagere med.
|
|
- **User context fra Microsoft Graph** forbedrer personalisering dramatisk -- avdeling, rolle og språkpreferanser gir agenten nødvendig kontekst uten at brukeren trenger å gjenta seg.
|
|
- **For norsk offentlig sektor**: Utnytt Copilots EU Data Boundary for datalokalitet, konfigurer instruksjoner på norsk, og bruk M365 admin center for sentral governance av agentdistribusjon.
|