Mécanisme (src/server/services/inter-kin.ts) :
- Deux modes :
request(enqueue → déclenche un tour LLM chez la cible, attend reply) etinform(insert direct en DB, pas de tour LLM) reply()renvoie une réponse au sender original via la queue- Rate limiting in-memory par paire sender→target (configurable, par minute)
- Chain depth tracking pour éviter les boucles infinies (max configurable)
listAvailableKins()retourne tous les Kins (flat list, pas de groupement)
Limites actuelles :
- Pas de notion de groupe : chaque Kin voit tous les autres, flat. Pas de "canal privé" entre Kins.
- Pas de contexte partagé : quand un Kin envoie un message à un autre, le destinataire n'a aucune visibilité sur la conversation d'origine.
- Pas de routage intelligent : le Hub actuel (
hub_kin_iddansappSettings) est un simple flag qui enrichit le prompt du Kin désigné, mais c'est un singleton global — un seul Hub pour toute la plateforme. - Pas de mémoire/knowledge partagée : chaque Kin a ses propres memories et knowledge sources (liées par
kinId).
Table kins : flat, pas de relation parent/enfant ni de groupement. Chaque Kin a :
id,slug,name,role,character,expertise,model,providerIdtoolConfig(JSON deny/allow list)workspacePath(filesystem isolé)
Relations : messages, memories, knowledge sources, crons, tasks, channels, miniApps — tout indexé par kinId.
- Sidebar (
AppSidebar.tsx) : tabs Kins / Tasks / Crons / MiniApps. KinList avec drag-and-drop (dnd-kit), search, hub badge. - KinCard : affiche nom, rôle, avatar, badge Hub, état queue.
- Navigation :
react-router-dom, sélection par slug (/kin/:slug). - Pas de notion de section/groupe dans la sidebar actuellement.
EPIC — Feature transversale touchant DB, backend (services, tools, routes, engine, prompt), frontend (sidebar, navigation, nouveau UI), et logique LLM.
Via l'UI :
- Bouton "Create Team" dans la sidebar (ou page Settings > Teams)
- Form : nom, description, icône/couleur, sélection du Hub Kin (parmi les Kins existants ou création d'un nouveau)
- Le Hub Kin est obligatoire — c'est le point d'entrée de la team
Via un Kin (tool) :
- Un Kin avec les droits peut créer une team via
create_team(name, description, hubKinId)
- Un Kin peut appartenir à 0 ou 1 team (pour éviter les conflits de contexte) — OU à plusieurs teams (plus flexible, mais complexifie la mémoire partagée)
- Recommandation : un Kin peut être dans plusieurs teams mais n'a qu'un rôle par team. La mémoire partagée est scopée par team.
- Assignation via UI (drag-and-drop ou multiselect dans les settings de la team)
- Le Hub Kin est automatiquement membre de sa team
Le Hub Kin d'une team reçoit un prompt enrichi :
- Annuaire détaillé des membres de la team (avec expertise, rôle dans la team)
- Instructions de routage spécifiques à la team
- Accès à la mémoire partagée de la team
- Accès à la knowledge base partagée de la team
Routage :
- Pas de logique custom côté backend — tout passe par le prompt du Hub
- Le Hub utilise les tools inter-Kin existants (
send_message,spawn_kin) pour déléguer - Différence avec le Hub global : le Hub de team a un scope réduit (ses membres) et un contexte enrichi (mémoire/knowledge de team)
Relation avec le Hub global :
- Le Hub global existant peut coexister. Il peut router vers des teams entières (en parlant au Hub de team) ou vers des Kins individuels.
- Un Kin peut être Hub global ET Hub d'une team.
Chat de Team :
- L'utilisateur peut "parler à la team" → le message arrive au Hub Kin de la team
- Dans la sidebar, la team apparaît comme un groupe cliquable. Cliquer dessus ouvre le chat du Hub.
- Le Hub route, délègue, et synthétise les réponses.
Chat individuel :
- L'utilisateur peut toujours parler directement à n'importe quel Kin membre
- La vue individuelle reste inchangée
Vue Team (optionnel, phase 2+) :
- Dashboard de la team : activité récente, état des membres, mémoire partagée
- Timeline des échanges intra-team
Mémoire partagée de team :
- Nouvelle scope de mémoire : en plus des memories
kinId-scoped, on ajoute des memoriesteamId-scoped - Tout Kin membre de la team peut lire et écrire dans la mémoire de team
- Le Hub a accès en priorité
- Tool :
team_memorize(content, category),team_recall(query)
Knowledge Base partagée :
- Les knowledge sources peuvent être attachées à une team (pas seulement à un Kin)
- Les chunks sont indexés par
teamIden plus dekinId - Lors du retrieval, un Kin membre cherche dans sa KB perso + la KB de team
- Créer une team : admin only (via UI) ou Kin avec opt-in tool
- Assigner un Kin : admin only (le Kin ne s'auto-assigne pas)
- Hub : désigné par l'admin, un seul par team
- Mémoire team : tous les membres lisent/écrivent
- Knowledge team : tous les membres lisent, admin gère les sources
-- Teams
CREATE TABLE teams (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
slug TEXT UNIQUE,
description TEXT,
icon TEXT, -- emoji ou Lucide icon
color TEXT, -- hex color pour la sidebar
hub_kin_id TEXT NOT NULL REFERENCES kins(id),
created_by TEXT REFERENCES user(id),
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
-- Team membership (many-to-many)
CREATE TABLE team_members (
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
kin_id TEXT NOT NULL REFERENCES kins(id) ON DELETE CASCADE,
role TEXT NOT NULL DEFAULT 'member', -- 'hub' | 'member'
joined_at INTEGER NOT NULL,
PRIMARY KEY (team_id, kin_id)
);
CREATE INDEX idx_team_members_kin ON team_members(kin_id);
-- Team-scoped memories
CREATE TABLE team_memories (
id TEXT PRIMARY KEY,
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
author_kin_id TEXT NOT NULL REFERENCES kins(id),
content TEXT NOT NULL,
embedding BLOB,
category TEXT NOT NULL, -- same as memories: fact/preference/decision/knowledge
subject TEXT,
importance REAL,
retrieval_count INTEGER NOT NULL DEFAULT 0,
last_retrieved_at INTEGER,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE INDEX idx_team_memories_team ON team_memories(team_id);
CREATE INDEX idx_team_memories_team_cat ON team_memories(team_id, category);
-- Team-scoped knowledge sources
CREATE TABLE team_knowledge_sources (
id TEXT PRIMARY KEY,
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
-- same columns as knowledge_sources minus kinId
name TEXT NOT NULL,
type TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
error_message TEXT,
original_filename TEXT,
mime_type TEXT,
stored_path TEXT,
source_url TEXT,
raw_content TEXT,
chunk_count INTEGER NOT NULL DEFAULT 0,
token_count INTEGER NOT NULL DEFAULT 0,
metadata TEXT,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE TABLE team_knowledge_chunks (
id TEXT PRIMARY KEY,
source_id TEXT NOT NULL REFERENCES team_knowledge_sources(id) ON DELETE CASCADE,
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
content TEXT NOT NULL,
embedding BLOB,
position INTEGER NOT NULL,
token_count INTEGER NOT NULL,
metadata TEXT,
created_at INTEGER NOT NULL
);
CREATE INDEX idx_team_kchunks_team ON team_knowledge_chunks(team_id);Drizzle schema : ajouter dans schema.ts les tables correspondantes avec les mêmes patterns que l'existant.
Services :
-
src/server/services/teams.ts— CRUD teams, gestion membrescreateTeam(name, slug, description, hubKinId, createdBy)updateTeam(id, updates)deleteTeam(id)addTeamMember(teamId, kinId)removeTeamMember(teamId, kinId)getTeam(id)/getTeamBySlug(slug)getTeamsForKin(kinId)— retourne les teams dont ce Kin est membregetTeamMembers(teamId)— avec détails KinisKinInTeam(kinId, teamId)
-
src/server/services/team-memory.ts— memories scopées team- Même interface que
memory.tsmais avecteamIdau lieu dekinId teamMemorize(teamId, authorKinId, content, category, subject)getRelevantTeamMemories(teamId, query)— hybrid search
- Même interface que
-
src/server/services/team-knowledge.ts— knowledge scopée team- Même interface que
knowledge.tsmais avecteamId
- Même interface que
Routes :
src/server/routes/teams.ts:GET /api/teams— list all teamsPOST /api/teams— create teamGET /api/teams/:id— get team details + membersPUT /api/teams/:id— update teamDELETE /api/teams/:id— delete teamPOST /api/teams/:id/members— add memberDELETE /api/teams/:id/members/:kinId— remove memberGET /api/teams/:id/memories— list team memoriesGET /api/teams/:id/knowledge— list team knowledge sources
Tools (Kin-side) :
src/server/tools/team-tools.ts:team_memorize— sauvegarder dans la mémoire de teamteam_recall— chercher dans la mémoire de teamlist_team_members— voir les membres de sa teamget_team_info— info sur la team courante
Modifications à l'existant :
-
inter-kin.ts:listAvailableKins()enrichi avec info team membership- Priorité intra-team : rate limits plus souples pour les messages intra-team
-
kin-engine.ts:- Dans
processNextMessage(), détecter si le Kin est Hub de team → enrichir le prompt - Lors du retrieval de memories, ajouter les team memories
- Lors du retrieval de knowledge, ajouter les team knowledge chunks
- Dans
-
prompt-builder.ts:- Nouveau paramètre
teamContextdansPromptParams - Nouveau block dans le system prompt : "## Team context" avec membres, mémoire, instructions
- Pour le Hub de team : instructions de routage spécifiques (similaires au Hub global mais scopées)
- Nouveau paramètre
-
app-settings.ts:- Le Hub global coexiste avec les Hub de teams — pas de changement nécessaire
Sidebar :
sidebar/
├── KinList.tsx (modifié — affiche les teams comme sections)
├── TeamSection.tsx (nouveau — groupe de Kins avec header team)
├── TeamCreateDialog.tsx (nouveau)
├── TeamSettingsDialog.tsx (nouveau)
Concept sidebar :
- Les Kins non-assignés apparaissent en haut (comme aujourd'hui)
- Chaque team apparaît comme une section collapsible avec icône/couleur
- Le Hub Kin a un badge "Hub" dans sa section team
- Cliquer sur le header de team ouvre le chat du Hub
- Les Kins membres apparaissent indentés sous la team
Pages / routes :
/team/:slug→ ouvre le chat du Hub de la team (réutilise la page chat existante)- Pas besoin d'une page "team dashboard" en phase 1
Settings :
- Nouvelle section dans les Settings : "Teams" — CRUD teams, drag-and-drop membres
- Additive only : nouvelles tables, pas de modification des tables existantes
- Le Hub global (
hub_kin_id) reste : aucun breaking change - Les Kins sans team fonctionnent exactement comme avant
- Les tools team sont opt-in (
defaultDisabled: true) — activés quand un Kin est ajouté à une team - Migration Drizzle : un seul fichier de migration ajoutant les nouvelles tables
Scope : Schema DB, migration, service CRUD teams, routes API, tests.
- Ajouter les tables
teams,team_membersdans le schema Drizzle - Créer
src/server/services/teams.ts(CRUD complet) - Créer
src/server/routes/teams.ts(API REST) - Tests unitaires
- Complexité : Medium
- Dépendances : aucune
Scope : Affichage des teams dans la sidebar, navigation, dialogs create/edit.
- Modifier
KinList.tsxpour grouper par team - Créer
TeamSection.tsx,TeamCreateDialog.tsx - Route
/team/:slugqui pointe vers le Hub - Settings page section Teams
- Complexité : Medium-Large
- Dépendances : Phase 1
Scope : Le Hub de team reçoit un prompt enrichi avec les membres et instructions de routage.
- Modifier
kin-engine.ts: détecter team membership, fetch team data - Modifier
prompt-builder.ts: nouveau block "Team context" - Modifier
inter-kin.ts: enrichirlistAvailableKins()avec team info - Le Hub de team fonctionne comme un coordinateur scopé
- Complexité : Medium
- Dépendances : Phase 1
Scope : Team memories avec tools pour les Kins membres.
- Ajouter table
team_memoriesau schema - Créer
src/server/services/team-memory.ts - Créer tools
team_memorize,team_recall - Modifier
kin-engine.ts: inclure team memories dans le retrieval - Complexité : Medium
- Dépendances : Phase 1, 3
Scope : Knowledge sources scopées team.
- Ajouter tables
team_knowledge_sources,team_knowledge_chunks - Créer
src/server/services/team-knowledge.ts - Modifier le retrieval dans
kin-engine.tspour inclure team knowledge - UI : section knowledge dans les settings de team
- Complexité : Medium-Large
- Dépendances : Phase 1, 4
Scope : Rate limits intra-team, tests E2E, edge cases, documentation.
- Rate limits différenciés intra-team vs inter-team
- Tests E2E du flow complet
- Gestion des edge cases (suppression team, suppression Kin membre, etc.)
- Documentation utilisateur
- Complexité : Medium
- Dépendances : toutes les phases précédentes
-
Complexité du prompt : Le system prompt est déjà long. Ajouter un block team context + team memories + team knowledge augmente significativement le token count. Il faudra être strict sur la taille des injections.
-
Ambiguïté Hub global vs Hub de team : Si un Kin est Hub global ET Hub d'une team, les instructions peuvent se chevaucher. Solution : le Hub de team a un scope explicite ("tu es Hub de la team X, voici tes membres"), distinct du Hub global.
-
Mémoire partagée vs privée : Un Kin pourrait vouloir mémoriser quelque chose en privé vs en team. Il faut que les tools soient clairs (
memorize= privé,team_memorize= team). -
Performance : Le retrieval de memories/knowledge est déjà un hot path. Ajouter un second pool (team) double le coût. Solution : queries parallèles, limite de résultats combinés.
-
Multi-team : Si un Kin est dans 2 teams, il reçoit le contexte des 2 teams dans son prompt. Ça peut devenir lourd. Solution : ne charger le contexte team que quand le message vient d'un membre de cette team (ou du Hub).
Oui. L'architecture existante est propre et extensible. Le pattern Hub existe déjà (même s'il est global), l'inter-Kin fonctionne, les memories/knowledge sont bien abstraites. La feature Teams est une extension naturelle, pas une refonte.
6 crons de 2h = ~12h de travail effectif, découpés en 6 phases indépendamment livrables.
- Phase 1 (DB + CRUD) : 2h
- Phase 2 (Frontend) : 2h
- Phase 3 (Hub prompt) : 2h
- Phase 4 (Team memory) : 2h
- Phase 5 (Team knowledge) : 2h
- Phase 6 (Polish) : 2h
Oui, recommandé. Un cron dédié kinbot-teams (2h, Sonnet ou Opus) par phase, exécuté séquentiellement. Chaque phase est autonome et testable. Le cron peut s'appuyer sur ce document comme spec.
Phases 1→3 sont le MVP : teams visibles, Hub fonctionnel, routage intra-team. Livrable en 3 crons (6h). Phases 4→6 sont des enrichissements : mémoire partagée, knowledge, polish. Livrable en 3 crons supplémentaires.
Le MVP (phases 1-3) apporte déjà 80% de la valeur : l'utilisateur peut créer des teams, voir les groupements dans la sidebar, et parler à un Hub qui connaît ses membres.