# Agent Routing and Task Specialization **Last updated:** 2026-02 **Status:** GA **Category:** Agent Orchestration & Automation **Type:** reference --- ## Innhold - [Introduksjon](#introduksjon) - [Kjernekomponenter](#kjernekomponenter) - [Intent Classification Routing](#intent-classification-routing) - [Agent Capability Matching](#agent-capability-matching) - [Semantic Kernel Handoff Pattern](#semantic-kernel-handoff-pattern) - [Load Balancing Strategies](#load-balancing-strategies) - [Fallback Routing](#fallback-routing) - [Specialization Hierarchies](#specialization-hierarchies) - [Norsk offentlig sektor](#norsk-offentlig-sektor) - [Beslutningsrammeverk](#beslutningsrammeverk) - [For Cosmo](#for-cosmo) ## Introduksjon Intelligent routing mellom spesialiserte agenter er en av de mest kritiske arkitekturbeslutningene i multi-agent-systemer. Istedenfor å bygge en "god nok til alt"-agent, deler man ansvarsområder mellom spesialiserte agenter som hver mestrer sitt domene. En router-agent eller orkestrator analyserer innkommende forespørsler og dirigerer dem til riktig spesialist basert på intent-klassifisering, kontekstuell matching og kapabilitets-deklarasjoner. Microsoft Agent Framework og Semantic Kernel tilbyr flere routing-mekanismer gjennom orkestreringsmønstrene Handoff, Group Chat og Magentic. Handoff-mønsteret er spesielt designet for agent-til-agent delegering, der en agent kan overføre en samtale til en mer kvalifisert agent basert på brukerens behov. Group Chat bruker en manager-agent til å dirigere samtaler, mens Magentic bruker en planbasert tilnærming med dynamisk oppgavefordeling. For komplekse enterprise-scenarier er routing-strategien avgjørende for brukeropplevelse, kostnadseffektivitet og systemets evne til å skalere. Feil routing betyr enten at brukeren møter en agent som ikke kan svare godt nok, eller at en dyr premium-modell brukes på enkle oppgaver. Riktig routing balanserer kvalitet, kostnad og responstid. ## Kjernekomponenter | Komponent | Formål | Teknologi | |-----------|--------|-----------| | Intent Classifier | Klassifiser brukerens hensikt | Azure AI Language, LLM-basert klassifisering | | Capability Registry | Registrer agent-kapabiliteter | Agent manifest, Semantic Kernel plugins | | Router Agent | Dirigér forespørsler til rett agent | Handoff orchestration, custom routing logic | | Load Balancer | Fordel last mellom agentinstanser | Azure APIM, Azure Load Balancer | | Fallback Handler | Håndtér situasjoner der ingen agent matcher | Default agent, human escalation | | Skill Matcher | Match oppgave-krav til agent-ferdigheter | Semantic matching, capability scoring | ## Intent Classification Routing ### LLM-basert intent-klassifisering ```python from semantic_kernel import Kernel from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion # Router-agent som klassifiserer intent og velger spesialist ROUTER_PROMPT = """ Du er en routing-agent. Analyser brukerens forespørsel og klassifiser den. Tilgjengelige agenter: 1. HR-Agent: Spørsmål om ansettelse, ferie, lønn, personalhåndbok 2. IT-Support-Agent: Tekniske problemer, tilganger, programvare 3. Økonomi-Agent: Faktura, budsjett, reiseregning, innkjøp 4. Juridisk-Agent: Kontrakter, personvern, compliance, anskaffelser 5. General-Agent: Alt annet Svar med JSON: { "intent": "", "target_agent": "", "confidence": <0.0-1.0>, "reasoning": "" } Brukerforespørsel: {{$query}} """ async def route_query(kernel: Kernel, query: str) -> dict: result = await kernel.invoke_prompt( ROUTER_PROMPT, input_vars={"query": query} ) routing = json.loads(str(result)) # Fallback hvis confidence er lav if routing["confidence"] < 0.6: routing["target_agent"] = "General-Agent" routing["needs_clarification"] = True return routing ``` ### Azure AI Language for intent-klassifisering ```python # CLU (Conversational Language Understanding) for deterministisk routing from azure.ai.language.conversations import ConversationAnalysisClient from azure.core.credentials import AzureKeyCredential client = ConversationAnalysisClient( endpoint=os.environ["LANGUAGE_ENDPOINT"], credential=AzureKeyCredential(os.environ["LANGUAGE_KEY"]) ) def classify_intent(query: str) -> dict: result = client.analyze_conversation( task={ "kind": "Conversation", "analysisInput": { "conversationItem": { "id": "1", "participantId": "user", "text": query } }, "parameters": { "projectName": "agent-routing", "deploymentName": "production" } } ) prediction = result["result"]["prediction"] return { "intent": prediction["topIntent"], "confidence": prediction["intents"][0]["confidenceScore"], "entities": prediction.get("entities", []) } ``` ## Agent Capability Matching ### Capability Registry Pattern ```csharp // Definer agent-kapabiliteter som et registrer public class AgentCapabilityRegistry { private readonly List _capabilities = new(); public void Register(AgentCapability capability) { _capabilities.Add(capability); } public AgentCapability FindBestMatch( string intent, Dictionary context) { return _capabilities .Where(c => c.CanHandle(intent)) .OrderByDescending(c => c.CalculateScore(intent, context)) .FirstOrDefault(); } } public class AgentCapability { public string AgentName { get; set; } public string[] SupportedIntents { get; set; } public string[] RequiredEntities { get; set; } public string[] SupportedLanguages { get; set; } public int MaxComplexity { get; set; } // 1-5 public decimal CostPerRequest { get; set; } public bool CanHandle(string intent) => SupportedIntents.Any(i => intent.Contains(i, StringComparison.OrdinalIgnoreCase)); public double CalculateScore( string intent, Dictionary context) { double score = 0; // Eksakt intent-match gir høy score if (SupportedIntents.Contains(intent)) score += 10; // Språkmatch if (SupportedLanguages.Contains(context.GetValueOrDefault("lang", "no"))) score += 5; // Lavere kostnad gir bonus (for like-kapable agenter) score += (1.0 / (double)(CostPerRequest + 0.01)); return score; } } // Registrering var registry = new AgentCapabilityRegistry(); registry.Register(new AgentCapability { AgentName = "HR-Specialist", SupportedIntents = new[] { "ferie", "lønn", "ansettelse", "permisjon" }, RequiredEntities = new[] { "ansatt-id" }, SupportedLanguages = new[] { "no", "en" }, MaxComplexity = 3, CostPerRequest = 0.02m }); ``` ## Semantic Kernel Handoff Pattern Handoff-mønsteret i Semantic Kernel er designet for agent-til-agent delegering: ```python from semantic_kernel.agents import ChatCompletionAgent, HandoffOrchestration from semantic_kernel.agents.orchestration.handoffs import HandoffBuilder # Definer spesialiserte agenter triage_agent = ChatCompletionAgent( name="Triage", instructions=""" Du er en triage-agent. Analyser brukerens forespørsel og overfør til riktig spesialist: - HR-spørsmål → transfer_to_hr - IT-problemer → transfer_to_it_support - Økonomi → transfer_to_finance """, kernel=kernel ) hr_agent = ChatCompletionAgent( name="HR-Specialist", instructions="Du er en HR-ekspert. Svar på HR-relaterte spørsmål.", kernel=kernel ) it_agent = ChatCompletionAgent( name="IT-Support", instructions="Du er IT-support. Hjelp med tekniske problemer.", kernel=kernel ) # Konfigurer handoff-regler handoffs = ( HandoffBuilder() .add(source=triage_agent, target=hr_agent, description="HR-spørsmål") .add(source=triage_agent, target=it_agent, description="IT-problemer") .add(source=hr_agent, target=triage_agent, description="Ikke HR-relatert") .add(source=it_agent, target=triage_agent, description="Ikke IT-relatert") .build() ) # Opprett orkestrering orchestration = HandoffOrchestration( members=[triage_agent, hr_agent, it_agent], handoffs=handoffs ) # Kjør result = await orchestration.invoke( task="Hvordan søker jeg om foreldrepermisjon?", runtime=runtime ) ``` ## Load Balancing Strategies ### Multi-instans agent routing via APIM ```xml ``` ## Fallback Routing ### Graceful degradation ved routing-feil ```python class FallbackRouter: """Router med multi-level fallback""" def __init__(self, agents: dict, default_agent: str): self.agents = agents self.default = default_agent self.escalation_threshold = 2 # Maks antall re-routes async def route(self, query: str, context: dict) -> AgentResponse: attempts = 0 current_agent = self._classify_and_select(query) while attempts < self.escalation_threshold: try: response = await self.agents[current_agent].invoke(query) # Sjekk om agenten selv indikerer at den ikke kan svare if response.confidence < 0.4: attempts += 1 current_agent = self._get_fallback(current_agent) continue return response except AgentUnavailableError: attempts += 1 current_agent = self._get_fallback(current_agent) # Ultimat fallback: default agent eller menneskelig eskalering return await self.agents[self.default].invoke(query) def _get_fallback(self, current: str) -> str: fallback_chain = { "HR-Specialist": "General-Agent", "IT-Support": "General-Agent", "Økonomi-Agent": "General-Agent", "General-Agent": "Human-Escalation" } return fallback_chain.get(current, self.default) ``` ## Specialization Hierarchies ### Tre-nivå spesialiseringshierarki ``` ┌──────────────┐ │ Triage │ L0: Intent classification │ Router │ └──────┬───────┘ │ ┌──────────────┼──────────────┐ │ │ │ ┌───────▼──────┐ ┌────▼────┐ ┌──────▼───────┐ │ HR Domain │ │ IT │ │ Finance │ L1: Domain │ Agent │ │ Agent │ │ Agent │ └───────┬──────┘ └────┬────┘ └──────┬───────┘ │ │ │ ┌───────▼──────┐ │ ┌──────▼───────┐ │ Rekruttering │ │ │ Faktura │ L2: Specialist │ Onboarding │ │ │ Budsjett │ │ Permisjon │ │ │ Innkjøp │ └──────────────┘ │ └──────────────┘ │ ┌──────▼───────┐ │ Nettverks- │ L2: Specialist │ Applikasjons-│ │ Tilgangs- │ └──────────────┘ ``` ## Norsk offentlig sektor ### Routing-hensyn for offentlig sektor | Aspekt | Krav | Implementering | |--------|------|----------------| | Sakstype-basert routing | Ulike sakstyper krever ulik behandling | Map sakstyper til agent-spesialister | | Sikkerhetsnivå | Gradert informasjon krever spesielle agenter | Rout gradert info til isolerte agenter | | Språk | Bokmål, nynorsk, samisk | Språkdeteksjon i router + dedikerte agenter | | Arkivering | Alle agent-interaksjoner skal journalføres | Logging av routing-beslutninger | | Innsynsrett | Borgere har rett til innsyn i saksbehandling | Dokumentér hvilken agent som behandlet saken | ### Eksempel: Norsk kommune agent-routing ```python KOMMUNE_AGENT_MAP = { "byggesak": { "agent": "byggesak-agent", "model": "gpt-4o", # Kompleks regulering "knowledge": ["plan-og-bygningsloven", "kommuneplan"], "requires_human_review": True }, "barnehageplass": { "agent": "barnehage-agent", "model": "gpt-4o-mini", # Enklere forespørsler "knowledge": ["barnehageloven", "lokale-vedtekter"], "requires_human_review": False }, "sosialtjenester": { "agent": "sosial-agent", "model": "gpt-4o", # Sensitive opplysninger "knowledge": ["sosialtjenesteloven", "NAV-retningslinjer"], "requires_human_review": True, "data_classification": "fortrolig" } } ``` ## Beslutningsrammeverk | Scenario | Anbefaling | Begrunnelse | |----------|------------|-------------| | < 5 agenttyper, lavt volum | Enkel LLM-basert router | Lav kompleksitet, rask å implementere | | 5-20 agenttyper, middels volum | CLU + capability registry | Deterministisk + skalerbar | | > 20 agenttyper, høyt volum | APIM-basert routing + hierarkisk | Ytelse + kostnadseffektivitet | | Sensitive domener med compliance | Handoff med human-in-the-loop | Sikkerhet + etterprøvbarhet | | Dynamisk agentøkosystem | Capability advertisement + discovery | Agenter kan registreres/fjernes uten kodeendring | ## For Cosmo - **Handoff-mønsteret** i Semantic Kernel er den mest naturlige routing-mekanismen for multi-agent-systemer -- triage-agenten klassifiserer og delegerer, spesialistene behandler. - **Kombiner LLM-basert og deterministisk routing** for best resultat: Bruk CLU for kjente intenter med høy volum, LLM for edge cases og nye scenarier. - **Capability Registry** er nøkkelen til skalerbar arkitektur -- nye agenter registrerer sine kapabiliteter, og routeren oppdager dem automatisk uten kodeendringer. - **Fallback er like viktig som routing** -- design alltid en graceful degradation-kjede fra spesialist via generalist til menneskelig eskalering. - **For norsk offentlig sektor**: Map sakstyper til agenter, respekter sikkerhetsnivåer i routing, og sørg for at alle routing-beslutninger logges for etterprøvbarhet.