docs(ms-ai-architect): KB-refresh LOW 51/52 — agent-framework: full API-omskriving (fabrikkert azure.ai.agent → ekte agent-framework SDK, verifisert mot MS Learn 2026-06-24) + fjernet For-Cosmo
This commit is contained in:
parent
2b0d37f370
commit
13ff4813a3
1 changed files with 316 additions and 264 deletions
|
|
@ -1,36 +1,52 @@
|
||||||
# Microsoft Agent Framework - Knowledge Base
|
# Microsoft Agent Framework - Knowledge Base
|
||||||
|
|
||||||
**Last updated:** 2026-01
|
**Last updated:** 2026-06-24
|
||||||
**Status:** GA (General Availability)
|
**Status:** Generelt tilgjengelig (kjerne-SDK). Multi-agent workflows/orkestrering er under aktiv utvikling — deler er i preview/experimental.
|
||||||
|
|
||||||
|
> **Verifisert 2026-06-24 mot Microsoft Learn (`learn.microsoft.com/agent-framework/`).** Hele API-flaten er korrigert: tidligere utgaver av denne filen brukte oppdiktede imports (`azure.ai.agent`, `azure.ai.foundry.FoundryClient/FoundryTools`, `Swarm`/`Handoff`, `Memory`, `@checkpoint`, `enable_tracing`). Det korrekte SDK-et er pakken `agent-framework` (Python) / `Microsoft.Agents.AI` (.NET).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Hva er Microsoft Agent Framework?
|
## Hva er Microsoft Agent Framework?
|
||||||
|
|
||||||
Microsoft Agent Framework er Microsofts SDK for å bygge AI-agenter i kode. Det er etterfølgeren til Semantic Kernel og tilbyr et unified rammeverk for agent-utvikling på tvers av Microsoft Foundry og standalone-applikasjoner.
|
Microsoft Agent Framework (MAF) er Microsofts åpne SDK for å bygge AI-agenter i kode. Det er den **direkte etterfølgeren til BÅDE Semantic Kernel OG AutoGen** — laget av de samme teamene. MAF kombinerer AutoGens enkle agent-abstraksjoner (single- og multi-agent) med Semantic Kernels enterprise-funksjoner (session-basert state, type-sikkerhet, middleware/filtre, telemetri, bred modell-/embedding-støtte), og legger til **graf-baserte Workflows** for eksplisitt kontroll over multi-agent-eksekvering.
|
||||||
|
|
||||||
**Nøkkelegenskaper:**
|
**Nøkkelegenskaper:**
|
||||||
- Multi-agent orkestrering
|
- Enhetlig agent-abstraksjon (`Agent` / `ChatClientAgent`) på tvers av modell-leverandører
|
||||||
- Tool/function calling
|
- Tool/function calling med automatisk skjema-generering
|
||||||
- Memory og state management
|
- Session-basert samtalehistorikk (stateless agent som default)
|
||||||
- Streaming og async support
|
- Streaming og async
|
||||||
- Microsoft Foundry-integrasjon
|
- Graf-baserte Workflows for multi-agent-orkestrering
|
||||||
|
- Innebygd OpenTelemetry-observability
|
||||||
|
- Native Microsoft Foundry-integrasjon
|
||||||
|
|
||||||
**Språk:** Python, C#, JavaScript/TypeScript
|
**Språk:** Python (`agent-framework`), .NET/C# (`Microsoft.Agents.AI`). En .NET-pakke bygger på `Microsoft.Extensions.AI` for kjerne-meldings- og innholdstyper.
|
||||||
|
|
||||||
|
**Installasjon (Python):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install agent-framework
|
||||||
|
```
|
||||||
|
|
||||||
|
Meta-pakken installerer kjernen (`agent-framework-core`) pluss de vanligste leverandørpakkene. Når du vet hva du trenger, kan du installere kun delene du bruker, f.eks. `pip install agent-framework-foundry agent-framework-mem0` (kjernen er en avhengighet og følger med). Andre provider-pakker: `agent-framework-openai`, `agent-framework-copilotstudio`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Forhold til Semantic Kernel
|
## Forhold til Semantic Kernel og AutoGen
|
||||||
|
|
||||||
| Aspekt | Semantic Kernel | Microsoft Agent Framework |
|
MAF er ikke et namespace inni Semantic Kernel — det er et eget SDK som erstatter begge forløperne. **Det finnes ikke noe `Kernel`-objekt** i Agent Framework.
|
||||||
|--------|-----------------|---------------------------|
|
|
||||||
| **Status** | Vedlikeholdes fortsatt | Anbefalt for nye prosjekter |
|
|
||||||
| **Fokus** | LLM-orkestrering, plugins | Multi-agent systemer |
|
|
||||||
| **Abstraksjonsnivå** | Høy | Middels |
|
|
||||||
| **Azure-integrasjon** | God | Tight (Foundry-native) |
|
|
||||||
| **Memory** | Basic | Avansert (persistent) |
|
|
||||||
|
|
||||||
**Anbefaling:** Bruk Microsoft Agent Framework for nye prosjekter. Semantic Kernel-kode kan migreres gradvis.
|
| Aspekt | Semantic Kernel | AutoGen | Microsoft Agent Framework |
|
||||||
|
|--------|-----------------|---------|---------------------------|
|
||||||
|
| **Rolle** | Forløper (vedlikeholdes) | Forløper (vedlikeholdes) | Direkte etterfølger til begge |
|
||||||
|
| **Kjerneobjekt** | `Kernel` + `ChatCompletionAgent` | `AssistantAgent` | `Agent` / `ChatClientAgent` (ingen `Kernel`) |
|
||||||
|
| **Multi-agent** | Orchestration (preview) | GroupChat / Magentic | Graf-baserte Workflows + orkestrering |
|
||||||
|
| **State** | `ChatHistoryAgentThread` | Innebygd i agent | `AgentSession`/thread (stateless default) |
|
||||||
|
| **Verktøy** | `@kernel_function` + plugin + Kernel | `FunctionTool` | `@tool` / vanlig funksjon, registreres direkte |
|
||||||
|
|
||||||
|
**Anbefaling:** Bruk Microsoft Agent Framework for nye prosjekter. Eksisterende Semantic Kernel-kode kan migreres gradvis — og `KernelFunction`-instanser kan gjenbrukes direkte som MAF-verktøy via `.as_agent_framework_tool` (krever `semantic-kernel` ≥ 1.38), se [Migrasjon fra Semantic Kernel](#migrasjon-fra-semantic-kernel).
|
||||||
|
|
||||||
|
Offisielle migrasjonsguider: [fra Semantic Kernel](https://learn.microsoft.com/agent-framework/migration-guide/from-semantic-kernel/) · [fra AutoGen](https://learn.microsoft.com/agent-framework/migration-guide/from-autogen/).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -38,131 +54,153 @@ Microsoft Agent Framework er Microsofts SDK for å bygge AI-agenter i kode. Det
|
||||||
|
|
||||||
### Agent
|
### Agent
|
||||||
|
|
||||||
En autonom enhet som kan:
|
En agent settes sammen av tre kjerneelementer: en **client** (modell-backend), **instructions** (systemprompt) og **tools** (kapabiliteter utover tekstgenerering). Agenten opprettes direkte med klienten:
|
||||||
- Motta instruksjoner
|
|
||||||
- Bruke verktøy (tools)
|
|
||||||
- Samarbeide med andre agenter
|
|
||||||
- Opprettholde tilstand
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import Agent, AgentConfig
|
from agent_framework import Agent
|
||||||
|
from agent_framework.foundry import FoundryChatClient
|
||||||
|
from azure.identity import AzureCliCredential
|
||||||
|
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
config=AgentConfig(
|
client=FoundryChatClient(
|
||||||
name="ResearchAgent",
|
project_endpoint="https://<project>.services.ai.azure.com",
|
||||||
instructions="Du er en forskningsassistent som finner fakta.",
|
|
||||||
model="gpt-4o",
|
model="gpt-4o",
|
||||||
tools=[search_tool, file_reader_tool]
|
credential=AzureCliCredential(),
|
||||||
)
|
),
|
||||||
|
name="ResearchAgent",
|
||||||
|
instructions="Du er en forskningsassistent som finner fakta.",
|
||||||
|
tools=[search_web, read_file],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
response = await agent.run("Finn de nyeste tallene for norsk kraftproduksjon.")
|
||||||
|
print(response.text)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Du kan også bruke klientens convenience-metode `as_agent()` (kaller `Agent(...)` internt med et subsett av parametre):
|
||||||
|
|
||||||
|
```python
|
||||||
|
agent = FoundryChatClient(
|
||||||
|
project_endpoint="https://<project>.services.ai.azure.com",
|
||||||
|
model="gpt-4o",
|
||||||
|
credential=AzureCliCredential(),
|
||||||
|
).as_agent(instructions="Du er en hjelpsom assistent.")
|
||||||
|
```
|
||||||
|
|
||||||
|
Samme mønster fungerer mot andre backends — f.eks. `from agent_framework.openai import OpenAIChatClient` for Azure OpenAI / OpenAI.
|
||||||
|
|
||||||
### Tools
|
### Tools
|
||||||
|
|
||||||
Funksjoner agenten kan kalle:
|
Et verktøy er bare en Python-funksjon. Funksjonsnavnet blir verktøynavnet og docstring-en blir beskrivelsen. Du registrerer det direkte i `tools`-parameteren — det finnes ingen plugin-/Kernel-innpakning:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import tool
|
from typing import Annotated
|
||||||
|
from agent_framework import tool
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
def search_web(query: str) -> str:
|
def search_web(
|
||||||
|
query: Annotated[str, "Søketekst"]
|
||||||
|
) -> str:
|
||||||
"""Søk på nettet etter informasjon."""
|
"""Søk på nettet etter informasjon."""
|
||||||
# Implementasjon
|
# Implementasjon
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@tool
|
# Dekoratøren er valgfri — en ren funksjon med docstring fungerer også:
|
||||||
def read_file(path: str) -> str:
|
def read_file(path: Annotated[str, "Sti til filen"]) -> str:
|
||||||
"""Les innholdet i en fil."""
|
"""Les innholdet i en fil."""
|
||||||
# Implementasjon
|
|
||||||
return content
|
return content
|
||||||
```
|
```
|
||||||
|
|
||||||
### Memory
|
`@tool` brukes når du vil overstyre navn/beskrivelse eller sette egenskaper som godkjenningskrav (se [Human-in-the-Loop](#pattern-3-human-in-the-loop)). `tools`-parameteren finnes både ved agent-opprettelse og på `run()`.
|
||||||
|
|
||||||
Lagre og hente kontekst på tvers av samtaler:
|
### Memory / samtalehistorikk
|
||||||
|
|
||||||
|
En agent er **stateless som default** — hvert `agent.run(...)`-kall starter uten historikk. For flertur-samtaler ber du agenten lage en tråd og gjenbruker den:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import Memory
|
agent = Agent(client=client, instructions="...")
|
||||||
|
|
||||||
memory = Memory(
|
thread = agent.get_new_thread()
|
||||||
type="persistent", # eller "session"
|
|
||||||
storage="cosmos_db" # eller "in_memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
agent = Agent(
|
await agent.run("Mitt navn er Kari.", thread)
|
||||||
config=config,
|
response = await agent.run("Hva heter jeg?", thread) # husker konteksten
|
||||||
memory=memory
|
print(response.text)
|
||||||
)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multi-Agent Orchestration
|
Tråden lagres in-memory som default. For leverandører med tjenestesidig tråd (f.eks. Foundry Agents) holdes historikken på tjenestesiden. For persistent eller eksternt minne brukes provider-pakker som `agent-framework-mem0`, eller du dytter trådhistorikken inn i Redis / Cosmos DB i produksjon.
|
||||||
|
|
||||||
Koordiner flere agenter:
|
### Multi-Agent Orchestration (Workflows)
|
||||||
|
|
||||||
|
MAF orkestrerer flere agenter via **graf-baserte Workflows**. Du bygger grafen med `WorkflowBuilder` (eksplisitte noder/kanter) eller med høynivå-byggere som `SequentialBuilder`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import Swarm, Handoff
|
from agent_framework import WorkflowBuilder
|
||||||
|
|
||||||
research_agent = Agent(name="Researcher", ...)
|
researcher = client.as_agent(name="Researcher", instructions="Finn fakta...")
|
||||||
writer_agent = Agent(name="Writer", ...)
|
writer = client.as_agent(name="Writer", instructions="Skriv innhold...")
|
||||||
|
|
||||||
swarm = Swarm(
|
# Eksplisitt graf: output flyter fra researcher til writer
|
||||||
agents=[research_agent, writer_agent],
|
workflow = (
|
||||||
handoffs=[
|
WorkflowBuilder(start_executor=researcher)
|
||||||
Handoff(
|
.add_edge(researcher, writer)
|
||||||
from_agent="Researcher",
|
.build()
|
||||||
to_agent="Writer",
|
|
||||||
condition="research_complete"
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
result = await swarm.run("Skriv en rapport om AI-trender")
|
events = await workflow.run("Skriv en rapport om AI-trender")
|
||||||
|
outputs = events.get_outputs()
|
||||||
|
if outputs:
|
||||||
|
print(outputs[0].text)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For en rein pipeline finnes `SequentialBuilder`, som også kan begrense hva hver agent ser av historikken (`chain_only_agent_responses=True`):
|
||||||
|
|
||||||
|
```python
|
||||||
|
from agent_framework.orchestrations import SequentialBuilder
|
||||||
|
|
||||||
|
workflow = SequentialBuilder(
|
||||||
|
participants=[writer, translator, reviewer],
|
||||||
|
chain_only_agent_responses=True,
|
||||||
|
).build()
|
||||||
|
```
|
||||||
|
|
||||||
|
Andre innebygde orkestreringsmønstre: **concurrent** (parallell), **handoff** (agenter overfører full kontroll seg imellom) og **Magentic** (manager-ledet, etterfølger til AutoGens MagenticOneGroupChat). Se [Workflows-dokumentasjonen](https://learn.microsoft.com/agent-framework/workflows/).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Microsoft Foundry-integrasjon
|
## Microsoft Foundry-integrasjon
|
||||||
|
|
||||||
Agent Framework er native integrert med Foundry Agent Service.
|
MAF er native integrert med **Microsoft Foundry Agent Service**. `FoundryChatClient` peker mot et Foundry-prosjekt og lar agenten bruke prosjektets modeller og verktøy:
|
||||||
|
|
||||||
### Deploye til Foundry
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.foundry import FoundryClient
|
import os
|
||||||
|
from agent_framework import Agent
|
||||||
|
from agent_framework.foundry import FoundryChatClient
|
||||||
|
from azure.identity import AzureCliCredential
|
||||||
|
|
||||||
client = FoundryClient(
|
agent = Agent(
|
||||||
endpoint="https://<workspace>.api.azureml.ms",
|
client=FoundryChatClient(
|
||||||
credential=DefaultAzureCredential()
|
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
|
||||||
)
|
model=os.environ["FOUNDRY_MODEL"],
|
||||||
|
credential=AzureCliCredential(),
|
||||||
# Deploye agent
|
),
|
||||||
deployment = client.agents.deploy(
|
instructions="Du er en hjelpsom assistent.",
|
||||||
agent=my_agent,
|
|
||||||
name="production-agent",
|
|
||||||
scaling={
|
|
||||||
"min_instances": 1,
|
|
||||||
"max_instances": 10
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Bruke Foundry Tools
|
Foundry Agent Service kan **hoste** agenter på tjenestesiden (persistente agenter med tjenestesidig tråd) — i motsetning til lokalt kjørte agenter. Hosting, skalering og livssyklus styres av Foundry Agent Service, ikke av en klientside-`deploy()`-metode.
|
||||||
|
|
||||||
Tilgang til 1,400+ Logic Apps connectors:
|
### Foundry-verktøykatalog
|
||||||
|
|
||||||
```python
|
Foundry Agent Service tilbyr en katalog av innebygde verktøy som kan kobles på agenten i prosjektet:
|
||||||
from azure.ai.foundry import FoundryTools
|
|
||||||
|
|
||||||
tools = FoundryTools(client)
|
| Kategori | Verktøy |
|
||||||
|
|----------|---------|
|
||||||
|
| **Kunnskap (privat)** | Azure AI Search, File Search, SharePoint, Microsoft Fabric (Fabric Data Agent) |
|
||||||
|
| **Kunnskap (web)** | Grounding with Bing Search, Web Search |
|
||||||
|
| **Handling/automatisering** | Azure Logic Apps, Azure Functions, OpenAPI, MCP, Computer Use, Browser Automation |
|
||||||
|
| **Generering/kjøring** | Code Interpreter, Image Generation |
|
||||||
|
| **Agent-til-agent** | Agent2Agent (A2A) |
|
||||||
|
|
||||||
# Legg til SharePoint-tilgang
|
Verktøystøtte varierer per modell og region — se den autoritative matrisen i [Tool best practices for Foundry Agent Service](https://learn.microsoft.com/azure/foundry/agents/concepts/tool-best-practice). **Azure Logic Apps-verktøyet** gir agenten tilgang til Logic Apps' connector-økosystem (SharePoint, e-post, linjeforretningssystemer m.m.).
|
||||||
sharepoint = tools.get("sharepoint")
|
|
||||||
my_agent.add_tool(sharepoint)
|
|
||||||
|
|
||||||
# Legg til Fabric-tilgang
|
|
||||||
fabric = tools.get("fabric")
|
|
||||||
my_agent.add_tool(fabric)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -171,163 +209,127 @@ my_agent.add_tool(fabric)
|
||||||
### Pattern 1: RAG Agent
|
### Pattern 1: RAG Agent
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import Agent, tool
|
from typing import Annotated
|
||||||
from azure.ai.search import SearchClient
|
from agent_framework import Agent, tool
|
||||||
|
from azure.search.documents import SearchClient
|
||||||
|
|
||||||
search_client = SearchClient(...)
|
search_client = SearchClient(...)
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
def search_documents(query: str) -> str:
|
def search_documents(
|
||||||
"""Søk i kunnskapsbasen."""
|
query: Annotated[str, "Søketekst mot kunnskapsbasen"]
|
||||||
|
) -> str:
|
||||||
|
"""Søk i kunnskapsbasen og returner relevante utdrag."""
|
||||||
results = search_client.search(query, top=5)
|
results = search_client.search(query, top=5)
|
||||||
return "\n".join([r.content for r in results])
|
return "\n".join(r["content"] for r in results)
|
||||||
|
|
||||||
rag_agent = Agent(
|
rag_agent = Agent(
|
||||||
|
client=client,
|
||||||
name="KnowledgeAgent",
|
name="KnowledgeAgent",
|
||||||
instructions="""
|
instructions=(
|
||||||
Du er en kunnskapsassistent. Bruk search_documents for å finne
|
"Du er en kunnskapsassistent. Bruk search_documents for å finne "
|
||||||
relevant informasjon før du svarer. Siter alltid kilder.
|
"relevant informasjon før du svarer. Siter alltid kilder."
|
||||||
""",
|
),
|
||||||
tools=[search_documents]
|
tools=[search_documents],
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Pattern 2: Supervisor-Worker
|
> For Foundry-hostede agenter kan du i stedet bruke det innebygde **Azure AI Search**-verktøyet fra verktøykatalogen i stedet for et egendefinert tool.
|
||||||
|
|
||||||
|
### Pattern 2: Supervisor-Worker (orkestrering)
|
||||||
|
|
||||||
|
Bygg spesialiserte agenter og koordiner dem i en workflow:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import Agent, Swarm
|
from agent_framework import WorkflowBuilder
|
||||||
|
|
||||||
# Worker agents
|
researcher = client.as_agent(name="Researcher", instructions="Finn fakta...")
|
||||||
researcher = Agent(name="Researcher", instructions="Finn fakta...")
|
writer = client.as_agent(name="Writer", instructions="Skriv innhold...")
|
||||||
writer = Agent(name="Writer", instructions="Skriv innhold...")
|
reviewer = client.as_agent(name="Reviewer", instructions="Kvalitetssjekk...")
|
||||||
reviewer = Agent(name="Reviewer", instructions="Kvalitetssjekk...")
|
|
||||||
|
|
||||||
# Supervisor
|
workflow = (
|
||||||
supervisor = Agent(
|
WorkflowBuilder(start_executor=researcher)
|
||||||
name="Supervisor",
|
.add_edge(researcher, writer)
|
||||||
instructions="""
|
.add_edge(writer, reviewer)
|
||||||
Du koordinerer arbeidet mellom Researcher, Writer og Reviewer.
|
.build()
|
||||||
1. Gi Researcher en research-oppgave
|
|
||||||
2. Gi Writer output fra Researcher
|
|
||||||
3. La Reviewer validere
|
|
||||||
4. Iterer hvis nødvendig
|
|
||||||
""",
|
|
||||||
sub_agents=[researcher, writer, reviewer]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
events = await workflow.run("Lag et faktanotat om AI Act for offentlig sektor.")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Pattern 3: Human-in-the-Loop
|
For en manager-ledet variant (en koordinator som dynamisk velger neste agent) brukes **Magentic**-orkestrering.
|
||||||
|
|
||||||
|
### Pattern 3: Human-in-the-Loop (tool-godkjenning)
|
||||||
|
|
||||||
|
Marker verktøy som krever menneskelig godkjenning med `approval_mode`. Når agenten forsøker å kalle verktøyet, pauser workflowen og emitter en `request_info`-hendelse du håndterer eksternt:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import Agent, Checkpoint
|
from agent_framework import tool, Agent
|
||||||
|
from agent_framework.orchestrations import SequentialBuilder
|
||||||
|
|
||||||
@checkpoint
|
@tool(approval_mode="always_require")
|
||||||
async def approve_action(action: str) -> bool:
|
def execute_database_query(query: str) -> str:
|
||||||
"""Krever menneskelig godkjenning."""
|
"""Kjør en database-spørring (krever godkjenning)."""
|
||||||
approval = await request_human_approval(action)
|
return f"Spørring utført: {query}"
|
||||||
return approval.approved
|
|
||||||
|
|
||||||
agent = Agent(
|
database_agent = Agent(
|
||||||
name="ActionAgent",
|
client=client,
|
||||||
instructions="Utfør handlinger, men be om godkjenning først.",
|
name="DatabaseAgent",
|
||||||
checkpoints=[approve_action]
|
instructions="Du er en database-assistent.",
|
||||||
|
tools=[execute_database_query],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
workflow = SequentialBuilder(participants=[database_agent]).build()
|
||||||
|
# Workflowen pauser på request_info-hendelsen og venter på godkjenning.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Pattern 4: Streaming Response
|
### Pattern 4: Streaming Response
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import Agent
|
agent = Agent(client=client, instructions="...")
|
||||||
|
|
||||||
agent = Agent(...)
|
# Streaming for responsivt UI
|
||||||
|
async for update in agent.run("Forklar kvantefysikk", stream=True):
|
||||||
# Streaming for responsiv UI
|
if update.text:
|
||||||
async for chunk in agent.run_stream("Forklar kvantefysikk"):
|
print(update.text, end="", flush=True)
|
||||||
print(chunk.text, end="", flush=True)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Memory Strategies
|
|
||||||
|
|
||||||
### In-Memory (Session)
|
|
||||||
|
|
||||||
```python
|
|
||||||
memory = Memory(type="session")
|
|
||||||
# Varer kun for denne sesjonen
|
|
||||||
# Raskest, men ingen persistens
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cosmos DB (Persistent)
|
|
||||||
|
|
||||||
```python
|
|
||||||
memory = Memory(
|
|
||||||
type="persistent",
|
|
||||||
storage="cosmos_db",
|
|
||||||
connection_string="...",
|
|
||||||
database="agents",
|
|
||||||
container="conversations"
|
|
||||||
)
|
|
||||||
# Persisterer på tvers av sesjoner
|
|
||||||
# Støtter vector search for semantic retrieval
|
|
||||||
```
|
|
||||||
|
|
||||||
### Redis (Distributed)
|
|
||||||
|
|
||||||
```python
|
|
||||||
memory = Memory(
|
|
||||||
type="distributed",
|
|
||||||
storage="redis",
|
|
||||||
connection_string="..."
|
|
||||||
)
|
|
||||||
# For multi-instance deployment
|
|
||||||
# Lavere latency enn Cosmos DB
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Observability
|
## Observability
|
||||||
|
|
||||||
### Tracing
|
MAF integrerer med **OpenTelemetry** og emitterer traces, logs og metrics etter [OpenTelemetry GenAI Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/). `opentelemetry-api`/`-sdk` følger med; **exportere installeres separat** (for å unngå unødvendige avhengigheter).
|
||||||
|
|
||||||
|
### Foundry + Azure Monitor
|
||||||
|
|
||||||
|
For Foundry-prosjekter konfigureres observability direkte fra `FoundryChatClient`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install azure-monitor-opentelemetry
|
||||||
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.agent import enable_tracing
|
# Krever at Foundry-prosjektet er koblet til en Application Insights-ressurs
|
||||||
from opentelemetry.sdk.trace.export import ConsoleSpanExporter
|
client = FoundryChatClient(
|
||||||
|
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
|
||||||
enable_tracing(
|
model=os.environ["FOUNDRY_MODEL"],
|
||||||
exporter=ConsoleSpanExporter(),
|
credential=AzureCliCredential(),
|
||||||
# eller: AzureMonitorExporter()
|
|
||||||
)
|
)
|
||||||
|
client.configure_azure_monitor() # setter connection string + resource automatisk
|
||||||
# Alle agent-operasjoner logges nå
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Metrics
|
Traces vises i Foundry-portalen under **Observability → Traces** (typisk 2–5 min etterslep), og i den koblede Application Insights-ressursen.
|
||||||
|
|
||||||
```python
|
### Lokal utvikling (Aspire Dashboard)
|
||||||
from azure.ai.agent import metrics
|
|
||||||
|
|
||||||
# Agent-level metrics
|
For lokal utvikling uten Azure kan du sende telemetri til [Aspire Dashboard](https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone) via OTLP:
|
||||||
agent.on_run_complete(lambda m: log_metrics(m))
|
|
||||||
|
|
||||||
# Metrics inkluderer:
|
```bash
|
||||||
# - Token usage
|
export ENABLE_INSTRUMENTATION=true
|
||||||
# - Tool calls
|
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
|
||||||
# - Latency
|
|
||||||
# - Error rates
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Azure Monitor Integration
|
For andre backends (Jaeger, Zipkin, Datadog, Grafana, New Relic) installeres en OTLP-exporter, f.eks. `opentelemetry-exporter-otlp-proto-grpc`.
|
||||||
|
|
||||||
```python
|
|
||||||
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
||||||
|
|
||||||
configure_azure_monitor(
|
|
||||||
connection_string="InstrumentationKey=..."
|
|
||||||
)
|
|
||||||
|
|
||||||
# All telemetry -> Application Insights
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -338,115 +340,159 @@ configure_azure_monitor(
|
||||||
```python
|
```python
|
||||||
from azure.identity import DefaultAzureCredential
|
from azure.identity import DefaultAzureCredential
|
||||||
|
|
||||||
agent = Agent(
|
client = FoundryChatClient(
|
||||||
credential=DefaultAzureCredential(),
|
project_endpoint="https://<project>.services.ai.azure.com",
|
||||||
# Ingen secrets i koden
|
model="gpt-4o",
|
||||||
|
credential=DefaultAzureCredential(), # ingen secrets i koden
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> `DefaultAzureCredential` er praktisk i utvikling, men i produksjon bør du bruke en spesifikk credential (f.eks. `ManagedIdentityCredential`) for å unngå latens, utilsiktet credential-probing og sikkerhetsrisiko fra fallback-kjeden. (Microsofts egen anbefaling i migrasjonsguiden.)
|
||||||
|
|
||||||
### Content Safety
|
### Content Safety
|
||||||
|
|
||||||
|
Innholdsfiltrering kan gjøres via Azure AI Content Safety (eget SDK) eller via Foundry-prosjektets innebygde guardrails:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from azure.ai.contentsafety import ContentSafetyClient
|
from azure.ai.contentsafety import ContentSafetyClient
|
||||||
|
from azure.ai.contentsafety.models import AnalyzeTextOptions
|
||||||
|
|
||||||
safety = ContentSafetyClient(...)
|
safety = ContentSafetyClient(endpoint, credential)
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
def safe_generate(prompt: str) -> str:
|
def safe_generate(prompt: Annotated[str, "Brukerprompt"]) -> str:
|
||||||
# Sjekk input
|
"""Generer svar med innholdssjekk på input og output."""
|
||||||
input_check = safety.analyze_text(prompt)
|
result = safety.analyze_text(AnalyzeTextOptions(text=prompt))
|
||||||
if input_check.harmful:
|
if any(c.severity > 2 for c in result.categories_analysis):
|
||||||
raise ValueError("Harmful input detected")
|
raise ValueError("Skadelig input oppdaget")
|
||||||
|
# ... generer og sjekk output tilsvarende
|
||||||
# Generer
|
|
||||||
response = llm.generate(prompt)
|
|
||||||
|
|
||||||
# Sjekk output
|
|
||||||
output_check = safety.analyze_text(response)
|
|
||||||
if output_check.harmful:
|
|
||||||
return "Kunne ikke generere trygt svar"
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
```
|
```
|
||||||
|
|
||||||
### Tool Permission Scoping
|
### Tool-godkjenning (scoping)
|
||||||
|
|
||||||
|
Sensitive verktøy markeres med godkjenningskrav i stedet for å kjøres automatisk:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@tool(
|
@tool(approval_mode="always_require")
|
||||||
permissions=["files.read"], # Begrensede permissions
|
|
||||||
require_confirmation=True # Krev bekreftelse
|
|
||||||
)
|
|
||||||
def read_sensitive_file(path: str) -> str:
|
def read_sensitive_file(path: str) -> str:
|
||||||
|
"""Les en sensitiv fil — krever menneskelig godkjenning før kjøring."""
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Migration fra Semantic Kernel
|
## Migrasjon fra Semantic Kernel
|
||||||
|
|
||||||
### Kernel → Agent
|
De viktigste endringene fra Semantic Kernel til Agent Framework (Python). Merk: **ingen `Kernel`** lenger.
|
||||||
|
|
||||||
|
### Pakke og import
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Semantic Kernel
|
# Semantic Kernel
|
||||||
kernel = Kernel()
|
from semantic_kernel import Kernel
|
||||||
kernel.add_plugin(MyPlugin())
|
from semantic_kernel.agents import ChatCompletionAgent
|
||||||
result = await kernel.invoke(function, input)
|
|
||||||
|
|
||||||
# Agent Framework
|
# Agent Framework
|
||||||
agent = Agent(tools=[my_tool])
|
from agent_framework import Agent
|
||||||
result = await agent.run(input)
|
from agent_framework.foundry import FoundryChatClient
|
||||||
|
```
|
||||||
|
|
||||||
|
### Agent-opprettelse (Kernel → client)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Semantic Kernel — hver agent avhenger av et Kernel
|
||||||
|
agent = ChatCompletionAgent(
|
||||||
|
service=OpenAIChatCompletion(),
|
||||||
|
name="Support",
|
||||||
|
instructions="Svar i én setning.",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Agent Framework — ingen Kernel; klienten gis direkte
|
||||||
|
agent = Agent(
|
||||||
|
client=FoundryChatClient(credential=AzureCliCredential()),
|
||||||
|
instructions="Svar i én setning.",
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Plugins → Tools
|
### Plugins → Tools
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Semantic Kernel plugin
|
# Semantic Kernel — @kernel_function + plugin-klasse + Kernel
|
||||||
@kernel_function
|
from semantic_kernel.functions import kernel_function
|
||||||
def my_function(input: str) -> str:
|
|
||||||
return process(input)
|
|
||||||
|
|
||||||
# Agent Framework tool
|
class SpecialsPlugin:
|
||||||
@tool
|
@kernel_function(name="specials", description="List dagens retter")
|
||||||
def my_function(input: str) -> str:
|
def specials(self) -> str:
|
||||||
return process(input)
|
return "Fiskesuppe, Cæsarsalat"
|
||||||
|
|
||||||
|
# Agent Framework — funksjon registreres direkte
|
||||||
|
from agent_framework import tool
|
||||||
|
|
||||||
|
@tool(name="specials", description="List dagens retter")
|
||||||
|
def specials() -> str:
|
||||||
|
return "Fiskesuppe, Cæsarsalat"
|
||||||
|
|
||||||
|
agent = client.as_agent(instructions="...", tools=[specials])
|
||||||
```
|
```
|
||||||
|
|
||||||
### Planners → Orchestration
|
### Invocation (`invoke` → `run`)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Semantic Kernel planner
|
# Semantic Kernel — async-iterator
|
||||||
planner = SequentialPlanner(kernel)
|
async for response in agent.invoke(messages=user_input, thread=thread):
|
||||||
plan = await planner.create_plan(goal)
|
print(response)
|
||||||
result = await plan.invoke()
|
|
||||||
|
|
||||||
# Agent Framework
|
# Agent Framework — ett AgentResponse
|
||||||
agent = Agent(
|
response = await agent.run(user_input, thread)
|
||||||
instructions=goal,
|
print(response.text)
|
||||||
tools=[...]
|
```
|
||||||
)
|
|
||||||
result = await agent.run() # Automatisk planning
|
### Kompatibilitet: gjenbruk `KernelFunction` som MAF-verktøy
|
||||||
|
|
||||||
|
Eksisterende `KernelFunction`-instanser (fra prompt-maler eller metoder, inkl. VectorStore `create_search_function`) kan konverteres til Agent Framework-verktøy med `.as_agent_framework_tool` — en gradvis migrasjonsbro:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Krever semantic-kernel >= 1.38
|
||||||
|
agent_tool = kernel_function.as_agent_framework_tool(kernel=kernel)
|
||||||
|
agent = OpenAIChatClient(model="gpt-4o").as_agent(tools=agent_tool)
|
||||||
|
```
|
||||||
|
|
||||||
|
### .NET-ekvivalent
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using Microsoft.Extensions.AI;
|
||||||
|
using Microsoft.Agents.AI;
|
||||||
|
|
||||||
|
// Ingen Kernel — base-typen er AIAgent, konsolidert i ChatClientAgent
|
||||||
|
AIAgent agent = chatClient.AsAIAgent(
|
||||||
|
instructions: "Svar i én setning.",
|
||||||
|
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||||
|
|
||||||
|
AgentResponse response = await agent.RunAsync(userInput, session);
|
||||||
|
Console.WriteLine(response.Text);
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## For Cosmo: Beslutningsveiledning
|
## Beslutningsveiledning
|
||||||
|
|
||||||
### Når anbefale Agent Framework
|
### Når anbefale Agent Framework
|
||||||
|
|
||||||
1. **Utviklerteam** som bygger AI-applikasjoner
|
1. **Utviklerteam** som bygger AI-applikasjoner i kode (Python/.NET)
|
||||||
2. **Multi-agent systemer** med kompleks orkestrering
|
2. **Multi-agent systemer** med kompleks orkestrering (Workflows)
|
||||||
3. **Tight Azure-integrasjon** via Foundry Agent Service
|
3. **Tight Azure-integrasjon** via Foundry Agent Service
|
||||||
4. **Custom logic** som krever kode
|
4. **Custom logic** som krever kode
|
||||||
5. **Produksjonskrav** (observability, scaling, security)
|
5. **Produksjonskrav** (observability, sessions, sikkerhet, type-sikkerhet)
|
||||||
|
|
||||||
### Når anbefale Copilot Studio istedenfor
|
### Når anbefale Copilot Studio i stedet
|
||||||
|
|
||||||
1. **Citizen developers** uten kodeerfaring
|
1. **Citizen developers** uten kodeerfaring
|
||||||
2. **Rask prototyping** av chatbots
|
2. **Rask prototyping** av chatbots
|
||||||
3. **Standard scenarios** (Q&A, IT helpdesk)
|
3. **Standard scenarioer** (Q&A, IT-helpdesk)
|
||||||
4. **Power Platform-økosystem** allerede i bruk
|
4. **Power Platform-økosystem** allerede i bruk
|
||||||
|
|
||||||
### Når anbefale direkte Azure OpenAI istedenfor
|
### Når anbefale direkte Azure OpenAI i stedet
|
||||||
|
|
||||||
1. **Enkle API-kall** uten orkestrering
|
1. **Enkle API-kall** uten orkestrering
|
||||||
2. **Minimal kompleksitet** påkrevd
|
2. **Minimal kompleksitet** påkrevd
|
||||||
|
|
@ -454,21 +500,27 @@ result = await agent.run() # Automatisk planning
|
||||||
|
|
||||||
### Spørsmål å stille kunden
|
### Spørsmål å stille kunden
|
||||||
|
|
||||||
1. "Har dere utviklere som kan skrive Python/C#/TypeScript?"
|
1. "Har dere utviklere som kan skrive Python eller C#?"
|
||||||
2. "Trenger dere at flere agenter samarbeider?"
|
2. "Trenger dere at flere agenter samarbeider?"
|
||||||
3. "Hvilke systemer må agenten integrere med?"
|
3. "Hvilke systemer må agenten integrere med?"
|
||||||
4. "Hva er kravene til observability og logging?"
|
4. "Hva er kravene til observability og logging?"
|
||||||
5. "Skal løsningen kjøre i Azure, on-prem, eller hybrid?"
|
5. "Skal løsningen kjøre i Azure, on-prem, eller hybrid?"
|
||||||
|
|
||||||
|
> **Eksisterende Semantic Kernel- eller AutoGen-kode?** MAF er den offisielle etterfølgeren til begge. Migrasjon kan skje gradvis — SK-`KernelFunction`-er kan gjenbrukes direkte via `.as_agent_framework_tool`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Ressurser
|
## Ressurser
|
||||||
|
|
||||||
- [Agent Framework Documentation](https://learn.microsoft.com/azure/ai-services/agents)
|
- [Agent Framework — oversikt](https://learn.microsoft.com/agent-framework/overview/)
|
||||||
- [Foundry Agent Service](https://learn.microsoft.com/azure/foundry/agents/overview)
|
- [Kom i gang: din første agent](https://learn.microsoft.com/agent-framework/get-started/your-first-agent)
|
||||||
- [Migration Guide from Semantic Kernel](https://learn.microsoft.com/azure/ai-services/agents/migrate-semantic-kernel)
|
- [Workflows (multi-agent-orkestrering)](https://learn.microsoft.com/agent-framework/workflows/)
|
||||||
- [GitHub Samples](https://github.com/azure-samples/ai-agent-framework)
|
- [Observability](https://learn.microsoft.com/agent-framework/agents/observability)
|
||||||
|
- [Migrasjonsguide fra Semantic Kernel](https://learn.microsoft.com/agent-framework/migration-guide/from-semantic-kernel/)
|
||||||
|
- [Migrasjonsguide fra AutoGen](https://learn.microsoft.com/agent-framework/migration-guide/from-autogen/)
|
||||||
|
- [Microsoft Foundry Agent Service](https://learn.microsoft.com/azure/foundry/agents/overview)
|
||||||
|
- [GitHub: microsoft/agent-framework](https://github.com/microsoft/agent-framework)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Sist oppdatert: Januar 2026*
|
*Sist oppdatert: Juni 2026 (API re-verifisert mot Microsoft Learn 2026-06-24)*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue