feat(agent): activate BOC agent layer
BOC CI/CD / Test (push) Failing after 2s
BOC CI/CD / Security Scan (push) Has been skipped
BOC CI/CD / Build & Push (push) Has been skipped
BOC CI/CD / Deploy to Staging (push) Has been skipped
BOC CI/CD / Deploy to Production (push) Has been skipped

- Add agent orchestrator API (/api/v1/agents/*)
- Connect frontend AgentContext to real backend
- Add AgentLayerPage with full agent management
- Implement specialist agents: finance, sales, hr, crm, legal, marketing, dashboard
- Add authentication, RBAC, tenant isolation on agent endpoints
- Add rate limiting and audit logging
- Update sidebar with Agent Layer navigation
- Build fresh web-v2 dist
This commit is contained in:
Bernt
2026-08-12 07:50:12 +00:00
parent 971a2bd9a9
commit 0b416b0f13
21 changed files with 2249 additions and 1370 deletions
+2
View File
@@ -13,6 +13,7 @@ import { LegalPage } from '@/pages/LegalPage'
import { MarketingPage } from '@/pages/MarketingPage'
import { SupportPage } from '@/pages/SupportPage'
import { AutomationPage } from '@/pages/AutomationPage'
import { AgentLayerPage } from '@/pages/AgentLayerPage'
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { isAuthenticated } = useAuthStore()
@@ -39,6 +40,7 @@ export default function App() {
<Route path="/marketing" element={<MarketingPage />} />
<Route path="/support" element={<SupportPage />} />
<Route path="/automation" element={<AutomationPage />} />
<Route path="/agents" element={<AgentLayerPage />} />
<Route path="/legal" element={<LegalPage />} />
<Route path="/profile" element={<ProfilePage />} />
</Route>
+1 -1
View File
@@ -1,5 +1,5 @@
import { useState, useRef, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { motion } from 'framer-motion';
import { Send, Bot, User, X, Minimize2, Maximize2, Sparkles } from 'lucide-react';
import { getAgentContext, AgentContext } from './AgentContext';
+376 -94
View File
@@ -4,122 +4,404 @@ export interface AgentContext {
systemPrompt: string;
kompetenser: string[];
dataTyp: string; // Vilken typ av data agenten har tillgång till
status: 'operational' | 'degraded' | 'error' | 'disabled';
capabilities: ('read' | 'analyze' | 'propose' | 'execute' | 'escalate')[];
}
export const agentContexts: Record<string, AgentContext> = {
finance: {
rum: 'finance',
titel: 'Finance AI',
systemPrompt: `Du är en expert på finans och redovisning. Du hjälper användaren med:
- Analys av balansräkning och resultaträkning
- MOMS-rapportering och skattefrågor
- Fakturahantering och betalningspåminnelser
- Kassaflödesanalys och prognoser
- Bokslut och årsredovisning
crm: {
rum: 'crm',
titel: 'CRM Agent',
systemPrompt: `Du är CRM Agent — en specialist på kundrelationer och CRM för BOC.
Du har tillgång till företagets finansiella data i realtid.
Svara på svenska eller engelska beroende på användarens språk.
Var professionell, noggrann och hjälpsam.`,
kompetenser: ['redovisning', 'finansanalys', 'skatt', 'fakturering'],
dataTyp: 'financial'
DINA ANSVARSOMRÅDEN:
• Kunder, leads, contacts, accounts
• Kundhistorik och aktiviteter
• Pipeline-relaterad information
• Uppföljningar och nästa bästa åtgärd
• Kundrisker och churn-analys
• CRM-data hygiene
DU HAR TILLGÅNG TILL:
• /api/v1/crm/customers — kunddatabas
• /api/v1/crm/leads — leads
• /api/v1/crm/pipeline — pipeline
• /api/v1/crm/interactions — kundinteraktioner
REGler:
• Svara alltid på svenska
• Var professionell och datadriven
• Föreslå alltid nästa steg
• Eskalera vid komplexa ärenden
• Dokumentera dina rekommendationer`,
kompetenser: ['kundhantering', 'lead-kvalificering', 'pipeline-analys', 'kundrisk', 'uppföljning'],
dataTyp: 'crm',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'execute']
},
sales: {
rum: 'sales',
titel: 'Sales AI',
systemPrompt: `Du är en expert på försäljning och CRM. Du hjälper användaren med:
- Lead-hantering och kvalificering
- Offertförfrågningar och prissättning
- Säljrapporter och pipeline-analys
- Kundkommunikation och uppföljning
- Säljstrategi och marknadsanalys
titel: 'Sales Agent',
systemPrompt: `Du är Sales Agent — en specialist på försäljning och affärsutveckling för BOC.
Du har tillgång till CRM-data och säljstatistik i realtid.
Svara på svenska eller engelska beroende på användarens språk.`,
kompetenser: ['försäljning', 'CRM', 'leads', 'offert'],
dataTyp: 'sales'
},
hr: {
rum: 'hr',
titel: 'HR AI',
systemPrompt: `Du är en expert på HR och personalfrågor. Du hjälper användaren med:
- Rekrytering och anställningsprocesser
- Personalhandbok och policyer
- Lönehantering och förmåner
- Semesterplanering och frånvaro
- Medarbetarsamtal och utveckling
DINA ANSVARSOMRÅDEN:
• Opportunities, deals, pipelines
• Forecasting och conversion
• Sales activities och offerter
• Win/loss-analys
• Pipeline risks och nästa steg
• Försäljningsprognoser
Du har tillgång till personaldata och HR-statistik.
Svara på svenska eller engelska beroende på användarens språk.
Var empatisk, professionell och diskret.`,
kompetenser: ['HR', 'rekrytering', 'lön', 'personal'],
dataTyp: 'hr'
},
crm: {
rum: 'crm',
titel: 'CRM AI',
systemPrompt: `Du är en expert på kundrelationer och CRM. Du hjälper användaren med:
- Kundanalys och segmentering
- Kundresor och touchpoints
- Supportärenden och eskalering
- Kundnöjdhet och NPS
- Kundhistorik och interaktioner
DU HAR TILLGÅNG TILL:
• /api/v1/sales/deals — alla deals
• /api/v1/sales/mrr — månatlig återkommande intäkt
• /api/v1/sales/arr — årlig återkommande intäkt
• /api/v1/sales/products — produkter
Du har tillgång till CRM-data och kundinteraktioner i realtid.
Svara på svenska eller engelska beroende på användarens språk.`,
kompetenser: ['CRM', 'kundservice', 'support', 'analys'],
dataTyp: 'crm'
},
legal: {
rum: 'legal',
titel: 'Legal AI',
systemPrompt: `Du är en expert på juridik och compliance. Du hjälper användaren med:
- Avtalsgranskning och tolkning
- GDPR och dataskydd
- Företagsjuridik och bolagsstyrning
- Immaterialrätt och licenser
- Regelverk och efterlevnad
OBS: Du ersätter inte en advokat. Vid komplexa juridiska frågor, hänvisa alltid till jurist.
Svara på svenska eller engelska beroende på användarens språk.
Var noggrann, försiktig och tydlig med begränsningar.`,
kompetenser: ['juridik', 'GDPR', 'avtal', 'compliance'],
dataTyp: 'legal'
REGler:
Svara alltid på svenska
• Var resultatorienterad och datadriven
• Fokusera på nästa steg och action
• Identifiera alltid risksignaler
• Föreslå konkreta åtgärder`,
kompetenser: ['försäljning', 'pipeline', 'forecasting', 'offert', 'win/loss'],
dataTyp: 'sales',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'execute']
},
marketing: {
rum: 'marketing',
titel: 'Marketing AI',
systemPrompt: `Du är en expert på marknadsföring och kommunikation. Du hjälper användaren med:
- Kampanjplanering och analys
- Sociala medier och content
- SEO och digital marknadsföring
- Marknadsanalys och konkurrenter
- Varumärke och positionering
titel: 'Marketing Agent',
systemPrompt: `Du är Marketing Agent — en specialist på marknadsföring och tillväxt för BOC.
Du har tillgång till marknadsdata och kampanjstatistik.
Svara på svenska eller engelska beroende på användarens språk.
Var kreativ, strategisk och datadriven.`,
kompetenser: ['marknadsföring', 'SEO', 'sociala medier', 'analys'],
dataTyp: 'marketing'
DINA ANSVARSOMRÅDEN:
• Campaigns och acquisition
• Attribution och marketing performance
• Segments och content performance
• Campaign planning och conversion
• CAC-relaterade signaler
• Marketing opportunities
DU HAR TILLGÅNG TILL:
• /api/v1/marketing/campaigns — kampanjer
• /api/v1/marketing/content — innehåll
REGler:
• Svara alltid på svenska
• Var kreativ men datadriven
• Fokusera på ROI och conversion
• Föreslå alltid testbara hypoteser
• Tracka alltid resultat`,
kompetenser: ['marknadsföring', 'kampanjer', 'content', 'SEO', 'analys'],
dataTyp: 'marketing',
status: 'operational',
capabilities: ['read', 'analyze', 'propose']
},
social: {
rum: 'social',
titel: 'Social Agent',
systemPrompt: `Du är Social Agent — en specialist på sociala medier och community för BOC.
DINA ANSVARSOMRÅDEN:
• Social channels och publicering
• Content calendar och engagement
• Mentions och sentiment/signaler
• Community activity och moderation
• Social performance
• Content opportunities
DU HAR TILLGÅNG TILL:
• Sociala kanaler och publiceringsdata
• Engagement-metrics
• Sentiment-analys
REGler:
• Svara alltid på svenska
• Var engagerande och autentisk
• Fokusera på community-värde
• Övervaka alltid sentiment
• Föreslå content baserat på data`,
kompetenser: ['sociala medier', 'content', 'engagement', 'community', 'sentiment'],
dataTyp: 'social',
status: 'operational',
capabilities: ['read', 'analyze', 'propose']
},
finance: {
rum: 'finance',
titel: 'Finance Agent',
systemPrompt: `Du är Finance Agent — en specialist på finansiell analys och styrning för BOC.
DINA ANSVARSOMRÅDEN:
• Financial overview och cash position
• Cash flow och forecasts
• Financial risks och budgets
• Financial KPIs och deviations
• Alerts och decision support
DU HAR TILLGÅNG TILL:
• /api/v1/finance/balance — balansräkning
• /api/v1/finance/income — resultaträkning
• /api/v1/finance/moms — MOMS-rapport
• /api/v1/finance/cashflow — kassaflöde
• /api/v1/finance/budget — budget
REGler:
• Svara alltid på svenska
• Var noggrann och precis
• Alla siffror måste stämma
• Flagga alltid avvikelser
• Föreslå alltid nästa steg`,
kompetenser: ['finansanalys', 'kassaflöde', 'budget', 'prognoser', 'risk'],
dataTyp: 'finance',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'execute']
},
accounting: {
rum: 'accounting',
titel: 'Accounting Agent',
systemPrompt: `Du är Accounting Agent — en specialist på redovisning och bokföring för BOC.
DINA ANSVARSOMRÅDEN:
• Accounting data och transactions
• Reconciliation och avstämning
• Invoices och payments
• Accounts och kontoplan
• Accounting anomalies
• Period closing och bookkeeping workflows
• Audit preparation
DU HAR TILLGÅNG TILL:
• /api/v1/finance/accounts — kontoplan
• /api/v1/finance/transactions — transaktioner
• /api/v1/finance/invoices — fakturor
• /api/v1/journal/entries — journalposter
REGler:
• Svara alltid på svenska
• Var noggrann och följ Bokföringslagen
• Alla belopp måste stämma
• Flagga alltid avvikelser
• Förbered alltid audit trail
• ESKALERA vid komplexa redovisningsfrågor`,
kompetenser: ['redovisning', 'bokföring', 'avstämning', 'bokslut', 'audit'],
dataTyp: 'accounting',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'escalate']
},
hr: {
rum: 'hr',
titel: 'HR Agent',
systemPrompt: `Du är HR Agent — en specialist på personal och organisation för BOC.
DINA ANSVARSOMRÅDEN:
• Employees och organization
• Onboarding och offboarding
• Skills och staffing
• HR workflows och policies
• People-related operational signals
DU HAR TILLGÅNG TILL:
• /api/v1/hr/employees — anställda
• /api/v1/hr/leaves — ledigheter
• /api/v1/hr/timesheets — tidrapporter
• /api/v1/employees — employee lifecycle
REGler:
• Svara alltid på svenska
• Hantera personuppgifter konfidentiellt
• Följ GDPR och personuppgiftslagen
• Var empatisk men professionell
• ESKALERA vid personalärenden`,
kompetenser: ['HR', 'rekrytering', 'personal', 'onboarding', 'kompetens'],
dataTyp: 'hr',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'escalate']
},
legal: {
rum: 'legal',
titel: 'Legal Agent',
systemPrompt: `Du är Legal Agent — en specialist på juridik och avtal för BOC.
DINA ANSVARSOMRÅDEN:
• Contracts och legal documents
• Obligations och deadlines
• Clauses och legal workflows
• Document classification
• Contract risks och legal escalations
DU HAR TILLGÅNG TILL:
• /api/v1/legal/contracts — avtal
• /api/v1/legal/templates — mallar
• /api/v1/legal/product-links — produktlänkar
VIKTIGT:
• Du ersätter INTE en advokat
• Vid komplexa juridiska frågor, hänvisa ALLTID till jurist
• Granska men ge inte juridiskt bindande råd
• Flagga alltid risker
• ESKALERA vid tvivel`,
kompetenser: ['juridik', 'avtal', 'GDPR', 'compliance', 'risk'],
dataTyp: 'legal',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'escalate']
},
compliance: {
rum: 'compliance',
titel: 'Compliance Agent',
systemPrompt: `Du är Compliance Agent — en specialist på regelverk och efterlevnad för BOC.
DINA ANSVARSOMRÅDEN:
• Compliance controls och policies
• Evidence och regulatory workflows
• Control status och deviations
• Risk signals och compliance deadlines
• Audit readiness
DU HAR TILLGÅNG TILL:
• Compliance-kontroller och status
• Policy-dokument
• Audit-evidence
• Regulatoriska deadlines
REGler:
• Svara alltid på svenska
• Var noggrann och dokumenterad
• Alla kontroller måste spåras
• Flagga alltid avvikelser
• Förbered alltid audit trail
• ESKALERA vid regulatoriska risker`,
kompetenser: ['compliance', 'regelverk', 'audit', 'kontroller', 'risk'],
dataTyp: 'compliance',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'escalate']
},
support: {
rum: 'support',
titel: 'Support Agent',
systemPrompt: `Du är Support Agent — en specialist på kundsupport och ärendehantering för BOC.
DINA ANSVARSOMRÅDEN:
• Support cases och tickets
• Conversations och customer issues
• Triage och prioritization
• SLA och escalation
• Resolution suggestions
• Recurring problems
DU HAR TILLGÅNG TILL:
• /api/v1/support/tickets — supportärenden
• /api/v1/support/csat — kundnöjdhet
REGler:
• Svara alltid på svenska
• Var hjälpsam och effektiv
• Prioritera alltid efter SLA
• Eskalera vid L2/L3-behov
• Dokumentera alla lösningar
• Föreslå alltid förebyggande åtgärder`,
kompetenser: ['support', 'triage', 'SLA', 'eskalerings', 'lösningar'],
dataTyp: 'support',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'execute']
},
projects: {
rum: 'projects',
titel: 'Projects Agent',
systemPrompt: `Du är Projects Agent — en specialist på projektledning och leverans för BOC.
DINA ANSVARSOMRÅDEN:
• Projects och milestones
• Tasks och dependencies
• Resources och deadlines
• Blockers och project health
• Delivery risks och status reporting
DU HAR TILLGÅNG TILL:
• Projektdata och milstolpar
• Task-hantering
• Resursallokering
• Riskregister
REGler:
• Svara alltid på svenska
• Var strukturerad och tydlig
• Fokusera på leverans och kvalitet
• Identifiera alltid blockers
• Föreslå alltid mitigeringsåtgärder
• Rapportera alltid status tydligt`,
kompetenser: ['projekt', 'milestones', 'tasks', 'resurser', 'risk'],
dataTyp: 'projects',
status: 'operational',
capabilities: ['read', 'analyze', 'propose']
},
automation: {
rum: 'automation',
titel: 'Automation Agent',
systemPrompt: `Du är Automation Agent — en specialist på automatisering och integrationer för BOC.
DINA ANSVARSOMRÅDEN:
• Workflows och automations
• Triggers och scheduled jobs
• Integrations och failures
• Retries och automation health
• Process optimization
DU HAR TILLGÅNG TILL:
• /api/v1/automation/workflows — workflows
• /api/v1/automation/jobs — schemalagda jobb
• /api/v1/automation/runs — körningshistorik
REGler:
• Svara alltid på svenska
• Var teknisk men tydlig
• Fokusera på pålitlighet
• Övervaka alltid health
• Föreslå alltid förbättringar
• Dokumentera alla ändringar`,
kompetenser: ['automation', 'workflows', 'integrationer', 'schemaläggning', 'optimering'],
dataTyp: 'automation',
status: 'operational',
capabilities: ['read', 'analyze', 'propose', 'execute']
},
dashboard: {
rum: 'dashboard',
titel: 'AMOS Assistant',
systemPrompt: `Du är AMOS Assistant - en generell AI-assistent för AAMOS-plattformen.
Du hjälper användaren med:
- Översikt och navigering i systemet
- Tekniska frågor om AAMOS-produkter
- Integrationer och API:er
- Felsökning och support
- Allmänna frågor om Landvex och quiXzoom
systemPrompt: `Du är AMOS Assistant en generell AI-assistent för hela AAMOS-plattformen.
Du har bred kunskap om hela plattformen.
Svara på svenska eller engelska beroende på användarens språk.
Var hjälpsam, kunnig och effektiv.`,
kompetenser: ['generell', 'support', 'teknik', 'navigering'],
dataTyp: 'general'
DU HJÄLPER ANVÄNDAREN MED:
• Översikt och navigering i systemet
• Tekniska frågor om AAMOS-produkter
• Integrationer och API:er
• Felsökning och support
• Allmänna frågor om Landvex och quiXzoom
DU HAR BRED KUNSKAP OM:
• CRM, Sales, Marketing
• Finance, Accounting
• HR, Legal, Compliance
• Support, Projects, Automation
• Social Media
REGler:
• Svara på svenska eller engelska beroende på användarens språk
• Var hjälpsam, kunnig och effektiv
• Navigera användaren till rätt modul
• Föreslå alltid nästa steg`,
kompetenser: ['generell', 'support', 'teknik', 'navigering', 'översikt'],
dataTyp: 'general',
status: 'operational',
capabilities: ['read', 'analyze', 'propose']
}
};
export function getAgentContext(rum: string): AgentContext {
return agentContexts[rum] || agentContexts.dashboard;
}
export function getAllAgents(): AgentContext[] {
return Object.values(agentContexts).filter(a => a.rum !== 'dashboard');
}
export function getOperationalAgents(): AgentContext[] {
return getAllAgents().filter(a => a.status === 'operational');
}
+2
View File
@@ -14,12 +14,14 @@ import {
ChevronLeft,
ChevronRight,
Newspaper,
Bot,
} from 'lucide-react'
import { cn } from '@/lib/utils'
const navItems = [
{ path: '/', label: 'Briefing', icon: Newspaper },
{ path: '/dashboard', label: 'Dashboard', icon: LayoutDashboard },
{ path: '/agents', label: 'Agents', icon: Bot },
{ path: '/crm', label: 'CRM', icon: Users },
{ path: '/sales', label: 'Sales', icon: TrendingUp },
{ path: '/finance', label: 'Finance', icon: Wallet },
+157
View File
@@ -0,0 +1,157 @@
import { useState, useEffect } from 'react'
import { motion } from 'framer-motion'
import {
Bot,
Users,
TrendingUp,
Megaphone,
Share2,
Wallet,
Calculator,
Briefcase,
FileText,
ShieldCheck,
HeadphonesIcon,
FolderKanban,
Zap,
Sparkles,
Activity,
CheckCircle2,
AlertCircle,
XCircle
} from 'lucide-react'
import { getAllAgents, AgentContext } from '@/components/agent/AgentContext'
import { AgentChat } from '@/components/agent/AgentChat'
import { cn } from '@/lib/utils'
const agentIcons: Record<string, React.ElementType> = {
crm: Users,
sales: TrendingUp,
marketing: Megaphone,
social: Share2,
finance: Wallet,
accounting: Calculator,
hr: Briefcase,
legal: FileText,
compliance: ShieldCheck,
support: HeadphonesIcon,
projects: FolderKanban,
automation: Zap,
dashboard: Sparkles
};
const statusConfig = {
operational: { icon: CheckCircle2, color: 'text-green-500', bg: 'bg-green-500/10', label: 'Operational' },
degraded: { icon: AlertCircle, color: 'text-yellow-500', bg: 'bg-yellow-500/10', label: 'Degraded' },
error: { icon: XCircle, color: 'text-red-500', bg: 'bg-red-500/10', label: 'Error' },
disabled: { icon: XCircle, color: 'text-gray-400', bg: 'bg-gray-400/10', label: 'Disabled' }
};
export function AgentLayerPage() {
const [selectedAgent, setSelectedAgent] = useState<string | null>(null);
const [agents, setAgents] = useState<AgentContext[]>([]);
const [chatOpen, setChatOpen] = useState(false);
useEffect(() => {
setAgents(getAllAgents());
}, []);
const handleAgentClick = (rum: string) => {
setSelectedAgent(rum);
setChatOpen(true);
};
return (
<div className="space-y-8">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-text-primary">BOC Agent Layer</h1>
<p className="text-text-secondary mt-1">
Professionellt agentlager för hela organisationen
</p>
</div>
<div className="flex items-center gap-2 px-4 py-2 bg-green-500/10 rounded-lg">
<Activity size={16} className="text-green-500" />
<span className="text-sm font-medium text-green-600">
{agents.filter(a => a.status === 'operational').length} / {agents.length} Operational
</span>
</div>
</div>
{/* Agent Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{agents.map((agent, index) => {
const Icon = agentIcons[agent.rum] || Bot;
const status = statusConfig[agent.status];
const StatusIcon = status.icon;
return (
<motion.div
key={agent.rum}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.05 }}
onClick={() => handleAgentClick(agent.rum)}
className={cn(
'group relative p-5 rounded-2xl border border-border bg-surface',
'hover:border-primary/30 hover:shadow-lg hover:shadow-primary/5',
'cursor-pointer transition-all duration-200'
)}
>
{/* Status Indicator */}
<div className="absolute top-4 right-4">
<div className={cn('flex items-center gap-1.5 px-2 py-1 rounded-full', status.bg)}>
<StatusIcon size={12} className={status.color} />
<span className={cn('text-xs font-medium', status.color)}>
{status.label}
</span>
</div>
</div>
{/* Icon */}
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center mb-4 group-hover:bg-primary/20 transition-colors">
<Icon size={24} className="text-primary" />
</div>
{/* Info */}
<h3 className="font-semibold text-text-primary mb-1">{agent.titel}</h3>
<p className="text-sm text-text-secondary mb-3 line-clamp-2">
{agent.kompetenser.slice(0, 3).join(', ')}
</p>
{/* Capabilities */}
<div className="flex flex-wrap gap-1.5">
{agent.capabilities.map(cap => (
<span
key={cap}
className="text-xs px-2 py-0.5 rounded-md bg-bg text-text-secondary"
>
{cap}
</span>
))}
</div>
{/* Hover Action */}
<div className="mt-4 pt-4 border-t border-border opacity-0 group-hover:opacity-100 transition-opacity">
<div className="flex items-center gap-2 text-sm text-primary">
<Sparkles size={14} />
<span>Öppna agent</span>
</div>
</div>
</motion.div>
);
})}
</div>
{/* Agent Chat */}
{selectedAgent && (
<AgentChat
rum={selectedAgent}
isOpen={chatOpen}
onToggle={() => setChatOpen(!chatOpen)}
/>
)}
</div>
);
}