feat: Implement AI Router for Dynamic Agent Selection (#15227)

Adds intelligent routing system that automatically selects the best
agent for user queries based on conversation context.

### Changes:
- Added `routerModel` column to workspace table for configurable router
LLM selection
- Implemented `RouterService` with conversation history analysis and
agent matching logic
- Created router settings UI in AI Settings page with model dropdown
- Removed agent-specific thread associations - threads are now
agent-agnostic
- Added real-time routing status notification in chat UI with shimmer
effect
- Removed automatic default assistant agent creation
- Renamed GraphQL operations from agent-specific to generic (e.g.,
`agentChatThreads` → `chatThreads`)

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Abdul Rahman
2025-10-22 18:32:41 +05:30
committed by GitHub
parent 1c27206b41
commit 32558673c6
102 changed files with 2262 additions and 1912 deletions
@@ -1,14 +1,10 @@
import {
type ReasoningUIPart,
type ToolUIPart,
type UIMessagePart,
type UITool,
} from 'ai';
import { type ReasoningUIPart, type ToolUIPart } from 'ai';
import { type ExtendedUIMessagePart } from 'twenty-shared/ai';
import { type AgentChatMessagePart } from '~/generated/graphql';
export const mapDBPartToUIMessagePart = (
part: AgentChatMessagePart,
): UIMessagePart<never, Record<string, UITool>> => {
): ExtendedUIMessagePart => {
switch (part.type) {
case 'text':
return {
@@ -49,6 +45,14 @@ export const mapDBPartToUIMessagePart = (
return {
type: 'step-start',
};
case 'data-routing-status':
return {
type: part.type,
data: {
text: part.textContent!,
state: part.state!,
},
};
default:
{
if (part.type.includes('tool-') === true) {