Add Notion Agent and FlowDeck integration docs
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped

Document Notion Agent (2026) concepts and a FlowDeck Agent design
that orchestrates tool calls through existing FastAPI routers, plus
a chat UI screenshot.
This commit is contained in:
2026-07-20 14:38:42 -04:00
parent 0ea447ee6f
commit b0d222b81a
3 changed files with 1166 additions and 0 deletions
+702
View File
@@ -0,0 +1,702 @@
# FlowDeck Agent — Intégration & Fonctionnement
> **Version:** 1.0 · **Date:** 2026-07-20 · **Auteur:** Hermes-Deepin
> **Cible:** Agent IA natif pour FlowDeck, inspiré de Notion Agent (2026)
> **Prérequis:** FlowDeck v4.0.x · FastAPI · SQLite · Gitea/GitHub
---
## Table des matières
1. [Vision & Objectifs](#1-vision--objectifs)
2. [Concept : de l'IA qui répond à l'IA qui réalise](#2-concept)
3. [Positionnement dans l'architecture FlowDeck](#3-positionnement)
4. [Placement dans l'interface (sidebar 🤖 Agents)](#4-placement-interface)
5. [Boucle d'exécution de l'agent](#5-boucle-dexécution)
6. [Sources de contexte FlowDeck](#6-sources-de-contexte)
7. [Modèle de données (nouvelles tables)](#7-modèle-de-données)
8. [Routes & API Agent](#8-routes--api)
9. [Le service AgentEngine](#9-service-agentengine)
10. [Système d'outils (Tools)](#10-système-doutils)
11. [Permissions & sécurité](#11-permissions--sécurité)
12. [Custom Agents & déclencheurs](#12-custom-agents)
13. [Skills réutilisables](#13-skills)
14. [Cas d'usage FlowDeck](#14-cas-dusage)
15. [Plan de migration](#15-plan-de-migration)
16. [Limitations](#16-limitations)
---
## 1. Vision & Objectifs
FlowDeck Agent transforme FlowDeck d'un clone Notion **passif** (où l'utilisateur crée manuellement collections, pages, propriétés) en un espace de travail **agentique** où une IA peut :
- Comprendre un objectif exprimé en langage naturel
- Lire le contexte du workspace (collections, pages, propriétés, issues Gitea)
- Planifier une suite d'actions
- **Exécuter** ces actions via l'API interne (créer collections, pages, propriétés, vues, sync Gitea)
- Retourner un résultat consolidé
L'agent réutilise l'infrastructure existante : **il n'appelle pas directement la DB**, il passe par les mêmes routers FastAPI (`/db/*`, `/board/api/*`) que l'utilisateur, garantissant cohérence, validation et respect du `PermissionManager`.
Cette fonctionnalité concrétise la ligne `v5.0.0 — AI Assistants` de la roadmap, en s'inspirant directement du modèle Notion Agent.
---
## 2. Concept : de l'IA qui répond à l'IA qui réalise {#2-concept}
Assistant classique :
Utilisateur → Prompt → Réponse texte
FlowDeck Agent :
Utilisateur → Objectif → Planification → Collecte contexte → Actions API → Résultat
| Notion AI | FlowDeck Agent |
|-----------|----------------|
| Répond, résume, réécrit | Planifie, recherche, **agit** |
| Bloc de texte | Crée collections, pages, propriétés, vues |
| Sans état | Historique de conversation + snapshots |
| Aucune action DB | Modifie le workspace via routers FastAPI |
---
## 3. Positionnement dans l'architecture FlowDeck {#3-positionnement}
L'agent s'insère comme un **nouveau service** et un **nouveau router**, sans modifier le cœur existant.
```
┌──────────────────────────────────────────────────────────────────┐
│ CLIENT (Browser) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ agent_panel.html — Panneau conversation (Alpine.js) │ │
│ │ agent_message.html — Fragment message (HTMX streaming) │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────┬───────────────────────────────────────┘
│ HTTP (SSE stream / JSON)
┌──────────────────────────▼───────────────────────────────────────┐
│ FASTAPI (Python 3.11+) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ROUTERS │ │
│ │ ├─ agent.py ← NOUVEAU /api/agent/* │ │
│ │ └─ (existants: board.py, api.py, collections.py, ...) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ SERVICES │ │
│ │ ├─ AgentEngine ← NOUVEAU (orchestrateur) │ │
│ │ ├─ ToolRegistry ← NOUVEAU (outils actionnables) │ │
│ │ ├─ LLMClient ← NOUVEAU (GPT/Claude/Gemini/local) │ │
│ │ ├─ ContextBuilder ← NOUVEAU (collecte workspace) │ │
│ │ ├─ SearchEngine (réutilisé — FTS5) │ │
│ │ ├─ PermissionManager (réutilisé — ACL) │ │
│ │ └─ GiteaClient (réutilisé — API Gitea) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ DATA LAYER — SQLite │ │
│ │ ├─ agents ← NOUVEAU │ │
│ │ ├─ agent_conversations ← NOUVEAU │ │
│ │ ├─ agent_messages ← NOUVEAU │ │
│ │ ├─ agent_actions ← NOUVEAU (journal audit) │ │
│ │ ├─ agent_skills ← NOUVEAU │ │
│ │ └─ (tables existantes: collections, pages, ...) │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────┬───────────────────────────────────────┘
│ HTTPS
┌──────────────────┴──────────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────────────┐
│ GITEA API REST │ │ PROVIDER LLM │
│ (contexte issues)│ │ OpenAI / Anthropic / │
│ │ │ Gemini / Ollama local │
└──────────────────┘ └──────────────────────────┘
```
**Principe clé — Tool-calling en boucle fermée :**
Le `LLMClient` ne touche jamais la base. Il émet des *intentions d'outil* (function calls). L'`AgentEngine` les traduit en appels HTTP internes vers les routers existants, exécutés avec la session et les permissions de l'utilisateur.
---
## 4. Placement dans l'interface (sidebar 🤖 Agents) {#4-placement-interface}
Le sidebar FlowDeck contient déjà une entrée **🤖 Agents** (voir ARCHITECTURE §5.2). Elle devient le point d'entrée de l'agent.
```
┌────────────┬─────────────────────────────────────────────────┐
│ SIDEBAR │ CONTENU PRINCIPAL │
│ │ │
│ 🕒 Recents │ ┌─ Page / Collection courante ──────────────┐ │
│ ⭐ Favoris │ │ │ │
│ 🤖 Agents ◄┼── clic ouvre le panneau agent (droite) │ │
│ 👥 Shared │ └────────────────────────────────────────────┘ │
│ │ ┌────────────┐ │
│ │ │ 🤖 Agent │ │
│ │ ├────────────┤ │
│ │ │ Historique │ │
│ │ │ Réponses │ │
│ │ │ ───────── │ │
│ │ │ @Sources │ │
│ │ │ 📎 Fichier │ │
│ │ │ [Modèle ▾] │ │
│ │ │ [Saisie... ]│ │
│ │ └────────────┘ │
└────────────┴─────────────────────────────────────────────────┘
```
Deux modes d'accès, comme Notion Agent :
- **Icône flottante** (coin inférieur droit) — accès global rapide
- **Section 🤖 Agents** du sidebar — liste des agents (personnel + custom)
L'affichage de la section 🤖 Agents est déjà prévu dans les 3 scénarios de compte (A/B/C) — voir ARCHITECTURE §6.5.4 : **toujours visible**.
---
## 5. Boucle d'exécution de l'agent {#5-boucle-dexécution}
Adaptation du modèle Notion (Compréhension → Contexte → Raisonnement → Action) à l'architecture FlowDeck :
```
Utilisateur formule un objectif
│
▼
┌─────────────────────────────────────────────┐
│ 1. COMPRÉHENSION (AgentEngine) │
│ Parse objectif + instructions custom │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 2. COLLECTE CONTEXTE (ContextBuilder) │
│ - Page/collection courante (cookie ws) │
│ - @mentions explicites │
│ - SearchEngine FTS5 (pages pertinentes) │
│ - Issues Gitea liées (GiteaClient) │
│ - Fichiers joints │
│ ⚠ filtré par PermissionManager │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 3. RAISONNEMENT (LLMClient + ToolRegistry) │
│ LLM reçoit: objectif + contexte + schéma │
│ des outils disponibles (function calling) │
│ → émet un plan / une intention d'outil │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 4. ACTION (AgentEngine → routers FastAPI) │
│ Exécute l'appel outil → route interne │
│ POST /db → create_collection │
│ POST /db/{id}/properties → add_property │
│ POST /db/{id}/pages → create_page │
│ Journalise dans agent_actions │
└──────────────────┬──────────────────────────┘
▼
Résultat outil réinjecté dans le LLM
│
┌────────┴────────┐
│ Objectif atteint?│
└────┬────────┬────┘
non │ │ oui
│ ▼
(retour étape 3) ┌─────────────────────────────┐
│ 5. RÉSULTAT consolidé + lien │
│ vers les objets créés │
└─────────────────────────────┘
```
Cette boucle **ReAct** (Reason + Act) se répète jusqu'à `max_iterations` (défaut : 12) ou atteinte de l'objectif.
---
## 6. Sources de contexte FlowDeck {#6-sources-de-contexte}
Correspondance avec les sources Notion Agent, adaptées aux entités FlowDeck :
| Source Notion | Équivalent FlowDeck | Mécanisme |
|---------------|---------------------|-----------|
| Pages, sous-pages | `pages`, `collection_pages` (parent_id) | `SearchEngine` FTS5 + lecture directe |
| Bases de données | `collections` + `collection_properties` | Lecture schéma `schema_json` |
| Wikis / docs internes | Blocs éditeur (`content_json`) | Parsing blocs |
| Jira | **Issues Gitea/GitHub** | `GiteaClient` (issues, labels, milestones) |
| Slack / Drive | Fichiers uploadés (`/api/files/`) | Lecture `files` property |
| Fichiers joints | Upload local-workspace | PDF/MD parsing |
| `@Projet Alpha` | `@collection` / `@page` / `@repo` | Résolution de mention |
**Résolution des mentions** — L'utilisateur peut cibler :
@collection:Roadmap → force le contexte sur une collection
@page:123 → une page précise
@repo:bruno/flowdeck → issues d'un repo Gitea
@ws → workspace courant complet
Le `ContextBuilder` respecte strictement le `PermissionManager` : l'agent ne voit **que** ce que l'utilisateur peut voir (même token, mêmes ACL — voir ARCHITECTURE §6.2).
---
## 7. Modèle de données (nouvelles tables) {#7-modèle-de-données}
```sql
-- Définition d'un agent (personnel ou custom)
CREATE TABLE agents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
workspace_id INTEGER REFERENCES workspaces(id),
name TEXT NOT NULL DEFAULT 'FlowDeck Agent',
icon TEXT DEFAULT '🤖',
agent_type TEXT NOT NULL DEFAULT 'personal',
-- 'personal' | 'custom'
description TEXT DEFAULT '',
-- Instructions personnalisées (ton, format, règles métier)
system_instructions TEXT DEFAULT '',
-- Modèle IA par défaut
model TEXT DEFAULT 'claude-opus-4-8',
-- gpt-* | claude-* | gemini-* | ollama:*
-- Périmètre custom agent : collections/repos autorisés
scope_json TEXT NOT NULL DEFAULT '{}',
-- {collections:[3,7], repos:["bruno/flowdeck"], tools:["create_page"]}
-- Déclencheurs (custom agents)
trigger_json TEXT NOT NULL DEFAULT '{}',
-- {type:"schedule", cron:"0 9 * * 1"} | {type:"webhook", event:"issue.opened"}
is_active BOOLEAN NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by INTEGER REFERENCES users(id),
UNIQUE(workspace_id, name)
);
-- Conversations (fils de discussion, comme Notion history)
CREATE TABLE agent_conversations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_id INTEGER NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id),
title TEXT DEFAULT 'New conversation',
-- Contexte de départ (page/collection ouverte à l'invocation)
context_json TEXT NOT NULL DEFAULT '{}',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Messages d'une conversation
CREATE TABLE agent_messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
conversation_id INTEGER NOT NULL REFERENCES agent_conversations(id) ON DELETE CASCADE,
role TEXT NOT NULL,
-- 'user' | 'assistant' | 'tool' | 'system'
content TEXT NOT NULL DEFAULT '',
-- Pour role='tool' : nom de l'outil + payload + résultat
tool_calls_json TEXT DEFAULT '[]',
model TEXT,
tokens_used INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Journal d'audit : CHAQUE action modifiant le workspace
CREATE TABLE agent_actions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
conversation_id INTEGER NOT NULL REFERENCES agent_conversations(id) ON DELETE CASCADE,
tool_name TEXT NOT NULL,
-- create_collection | create_page | add_property | ...
target_type TEXT,
-- collection | page | property | view | issue
target_id TEXT,
payload_json TEXT NOT NULL DEFAULT '{}',
result_json TEXT NOT NULL DEFAULT '{}',
status TEXT NOT NULL DEFAULT 'success',
-- success | error | reverted
-- Snapshot avant modification → permet le rollback
undo_snapshot_json TEXT DEFAULT '{}',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
executed_by INTEGER REFERENCES users(id)
);
-- Skills réutilisables (mini-prompts)
CREATE TABLE agent_skills (
id INTEGER PRIMARY KEY AUTOINCREMENT,
workspace_id INTEGER REFERENCES workspaces(id),
name TEXT NOT NULL,
-- "Génération de PRD", "Analyse SWOT", "Préparation sprint"
description TEXT DEFAULT '',
prompt_template TEXT NOT NULL,
-- Outils que la skill peut invoquer
allowed_tools_json TEXT NOT NULL DEFAULT '[]',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by INTEGER REFERENCES users(id),
UNIQUE(workspace_id, name)
);
CREATE INDEX idx_agent_conv_user ON agent_conversations(user_id, updated_at);
CREATE INDEX idx_agent_msg_conv ON agent_messages(conversation_id, created_at);
CREATE INDEX idx_agent_action_conv ON agent_actions(conversation_id);
Intégration au diagramme de relations existant
users ──1:N──► agent_conversations ──1:N──► agent_messages
│ │
│ └──1:N──► agent_actions ──► (collections/pages/...)
│
workspaces ──1:N──► agents ──1:N──► agent_conversations
│
└──1:N──► agent_skills
```
## 8. Routes & API Agent {#8-routes--api}
Nouveau router agent.py, préfixe /api/agent.
# Agents (définitions)
```
GET /api/agent → Liste agents du workspace
POST /api/agent → Créer custom agent
GET /api/agent/{agent_id} → Détail agent
PUT /api/agent/{agent_id} → Update (instructions, scope, model)
DELETE /api/agent/{agent_id} → Supprimer custom agent
```
# Conversations
```
GET /api/agent/conversations → Historique des conversations
POST /api/agent/conversations → Nouvelle conversation
GET /api/agent/conversations/{id} → Messages d'une conversation
DELETE /api/agent/conversations/{id} → Supprimer conversation
```
# Exécution (cœur)
```
POST /api/agent/conversations/{id}/run → Envoyer un objectif (SSE stream)
body: {message, model?, mentions?, files?, skill_id?}
→ stream: reasoning → tool_call → tool_result → ... → final
```
# Actions & audit
```
GET /api/agent/conversations/{id}/actions → Journal des actions
POST /api/agent/actions/{action_id}/undo → Annuler une action (rollback)
```
# Skills
```
GET /api/agent/skills → Liste skills
POST /api/agent/skills → Créer skill
POST /api/agent/skills/{id}/apply → Appliquer une skill
```
# Custom agents — déclencheurs
```
POST /api/agent/{agent_id}/trigger → Déclenchement manuel
```
# (déclenchement auto via scheduler interne + webhooks.py)
Streaming — La route /run renvoie un flux Server-Sent Events (SSE) pour afficher en temps réel le raisonnement et chaque action, à la manière de l'interface conversationnelle Notion. Le frontend (Alpine.js) consomme le flux et met à jour agent_panel.html.
-------------------------
## 9. Le service AgentEngine {#9-service-agentengine}
Orchestrateur central. Pseudo-implémentation :
```
class AgentEngine:
"""Orchestrateur ReAct pour FlowDeck Agent."""
def __init__(self, db, user, request):
self.db = db
self.user = user
self.request = request # pour réutiliser session/cookies
self.llm = LLMClient()
self.tools = ToolRegistry(db, user, request)
self.ctx = ContextBuilder(db, user)
self.perms = PermissionManager(db, user)
async def run(self, conversation_id, objective, *, model=None,
mentions=None, files=None, skill_id=None):
agent = self._load_agent(conversation_id)
model = model or agent.model
# 1. COMPRÉHENSION + instructions custom + skill
system = self._build_system_prompt(agent, skill_id)
# 2. COLLECTE CONTEXTE (respecte permissions)
context = await self.ctx.build(
workspace=self._active_workspace(),
mentions=mentions,
files=files,
)
messages = [
{"role": "system", "content": system},
{"role": "user", "content": f"{objective}\n\n# Contexte\n{context}"},
]
# 3-4. BOUCLE RAISONNEMENT ↔ ACTION
for _ in range(MAX_ITERATIONS): # défaut 12
response = await self.llm.complete(
model=model,
messages=messages,
tools=self.tools.schema(scope=agent.scope), # function calling
stream=True,
)
yield {"type": "reasoning", "content": response.text}
if not response.tool_calls:
yield {"type": "final", "content": response.text}
break
for call in response.tool_calls:
# Vérif permission AVANT exécution
self.perms.assert_can(call.tool, call.args)
result = await self.tools.execute(call.tool, call.args)
# Journal d'audit + snapshot rollback
self._log_action(conversation_id, call, result)
yield {"type": "action",
"tool": call.tool,
"target": result.get("target"),
"status": result["status"]}
messages.append({"role": "tool",
"name": call.tool,
"content": result})
```
Points clés :
- stream=True → SSE vers le frontend
- Chaque tool_call passe par PermissionManager.assert_can() avant exécution
- Chaque action modifiant la DB écrit un agent_actions avec undo_snapshot_json → rollback possible
- La boucle réutilise le même token Gitea que l'utilisateur (via user_tokens)
-------------------------
10. Système d'outils (Tools) {#10-système-doutils}
Les outils sont des wrappers autour des routers FastAPI existants — l'agent ne réinvente rien.
| Outil | Route interne appelée | Ce que ça fait |
|-------|----------------------|----------------|
| `search_workspace` | `SearchEngine` (FTS5) | Recherche full-text pages/collections |
| `read_collection` | `GET /db/{id}` | Lit schéma + pages d'une collection |
| `read_page` | `GET /db/{c}/pages/{p}` | Lit une page + propriétés + blocs |
| `create_collection` | `POST /db` | Crée une database |
| `add_property` | `POST /db/{id}/properties` | Ajoute une propriété typée |
| `create_view` | `POST /db/{id}/views` | Crée une vue (table/board/calendar…) |
| `create_page` | `POST /db/{id}/pages` | Crée une page + valeurs propriétés |
| `update_page` | `PUT /db/{c}/pages/{p}` | Modifie propriétés/contenu |
| `write_blocks` | `POST /board/api/pages/{id}/blocks` | Écrit du contenu (éditeur de blocs) |
| `add_relation` | `POST /db/{id}/properties` (type relation) | Lie deux collections |
| `create_sub_item` | `POST /db/{c}/pages/{p}/sub-items` | Crée un sub-item |
| `add_dependency` | `POST /db/{c}/pages/{p}/dependencies` | Ajoute blocks/blocked_by |
| `sync_gitea` | `POST /board/api/sync/{o}/{r}` | Synchronise issues ↔ collection |
| `read_gitea_issues` | `GiteaClient` | Lit issues/labels/milestones |
| `create_gitea_issue` | `POST /api/issues/{o}/{r}` | Crée une issue Gitea |
| `apply_template` | `POST /db/{id}/templates/{t}/apply` | Applique un template |
Schéma d'un outil (function calling) exposé au LLM :
```
{
"name": "create_page",
"description": "Crée une page dans une collection FlowDeck avec ses valeurs de propriétés.",
"parameters": {
"type": "object",
"properties": {
"collection_id": {"type": "integer"},
"title": {"type": "string"},
"property_values": {
"type": "object",
"description": "Map property_id → valeur (respecte le type)"
}
},
"required": ["collection_id", "title"]
}
}
```
Filtrage par scope — Pour un custom agent, ToolRegistry.schema(scope=...) ne renvoie que les outils autorisés dans agents.scope_json.tools, et limite les cibles aux collections/repos de scope_json.
-------------------------
## 11. Permissions & sécurité {#11-permissions--sécurité}
L'agent agit avec les permissions de l'utilisateur, jamais au-delà (principe Notion Agent : « mêmes permissions que l'utilisateur »).
```
┌───────────────────────────────────────────────────────────┐
│ GARDE-FOUS AGENT │
│ │
│ 1. Identité → session utilisateur + user_tokens │
│ 2. ACL → PermissionManager.assert_can() par outil│
│ 3. Scope custom → scope_json limite collections/repos │
│ 4. Database lock → collection is_locked ⇒ outils write KO │
│ 5. Audit → agent_actions journalise TOUT │
│ 6. Rollback → undo_snapshot_json par action │
│ 7. Rate limiting → RateLimiter (middleware existant) │
│ 8. Confirmation → actions destructives ⇒ approbation UI │
└───────────────────────────────────────────────────────────┘
```
Mode approbation — Configurable par agent :
- auto : l'agent exécute directement (création de contenu)
- confirm : actions destructives (delete_page, sync massif) demandent une confirmation dans le panneau avant exécution
Cohérent avec le modèle de rôles workspace (owner/admin/editor/commenter/viewer, ARCHITECTURE §6.2) : un agent lancé par un viewer ne peut que lire.
-------------------------
## 12. Custom Agents & déclencheurs {#12-custom-agents}
Comme Notion (Custom Agents 2026), FlowDeck distingue :
| Type | Portée | Exemple |
|------|--------|---------|
| **Personal Agent** | Généraliste, tout le workspace visible | Assistant quotidien |
| **Custom Agent** | Spécialisé, scope restreint, déclencheurs | Agent Reporting, Agent Support |
Déclencheurs (agents.trigger_json) :
```
type: "manual" → bouton dans l'UI
type: "schedule" → cron interne (ex: "0 9 * * 1" = lundi 9h)
type: "webhook" → branché sur webhooks.py (issue.opened, issue.closed…)
```
Exemples de custom agents FlowDeck :
- Agent Reporting — chaque lundi, scanne toutes les collections, produit une page « Rapport hebdo » avec KPI
- Agent Gitea Triage — à issue.opened, classe l'issue dans la bonne collection et remplit ses propriétés
- Agent Sprint — prépare une collection sprint depuis les issues du milestone courant
Le scheduler s'appuie sur le lifespan FastAPI (main.py) et les webhooks réutilisent le router webhooks.py existant.
-------------------------
## 13. Skills réutilisables {#13-skills}
Une skill est un mini-prompt paramétrable + liste d'outils autorisés (table agent_skills).
```
Skill "Préparation de sprint"
├─ prompt_template:
│ "Analyse les issues ouvertes du repo {repo}, crée une collection
│ sprint '{sprint_name}', ajoute les propriétés Status/Priority/Assignee,
│ importe chaque issue comme page, groupe en vue Board."
├─ allowed_tools: [read_gitea_issues, create_collection,
│ add_property, create_page, create_view]
└─ Invocation: POST /api/agent/skills/{id}/apply
```
Autres skills livrées par défaut : Analyse SWOT, Génération de compte-rendu, Génération de PRD, Synthèse GitHub/Gitea.
-------------------------
## 14. Cas d'usage FlowDeck {#14-cas-dusage}
Gestion de produit
> « Crée une roadmap Q3 à partir des issues du repo bruno/flowdeck »
```
L'agent : read_gitea_issues → create_collection("Roadmap Q3") → add_property(Status, Priority, DueDate) → create_page × N → create_view(timeline).
Développement logiciel
```
> « Analyse les bugs des 6 derniers mois et crée un plan d'amélioration »
```
sync_gitea → search_workspace → analyse LLM → create_collection("Plan qualité") → create_page (causes, actions) → add_dependency.
Direction
```
> « Génère les OKR du prochain trimestre depuis nos objectifs actuels »
```
read_collection(Objectifs) → raisonnement → create_collection("OKR Q4") → create_page × N.
Multi-étapes (comme Notion)
```
> « Résume les notes de réunion du trimestre et crée les tâches de suivi »
```
search_workspace(meetings) → synthèse → write_blocks (page résumé) → create_page × N (tâches) dans la collection Tasks.
```
-------------------------
## 15. Plan de migration {#15-plan-de-migration}
Phase 1 — Fondations DB & Service
1. Créer tables agents, agent_conversations, agent_messages,
agent_actions, agent_skills
2. Implémenter LLMClient (abstraction multi-provider)
3. Implémenter ContextBuilder (réutilise SearchEngine)
Phase 2 — Tool-calling
1. ToolRegistry : wrappers read-only d'abord (search, read_*)
2. Ajouter outils write (create_collection, create_page, ...)
3. Brancher PermissionManager.assert_can() sur chaque outil
4. Journal agent_actions + snapshots rollback
Phase 3 — Interface
1. agent_panel.html (Alpine.js) branché sur section 🤖 Agents
2. Streaming SSE (/run)
3. Icône flottante coin inférieur droit
4. Affichage temps réel reasoning + actions
Phase 4 — Personnalisation
1. Instructions custom par agent
2. Skills (table + /apply)
3. Sélecteur de modèle (GPT/Claude/Gemini/Ollama)
Phase 5 — Custom Agents
1. Scope + trigger_json
2. Scheduler (lifespan FastAPI)
3. Déclencheurs webhook (via webhooks.py)
4. Mode approbation (auto/confirm)
-------------------------
## 16. Limitations {#16-limitations}
Alignées sur les limites connues de Notion Agent, adaptées à FlowDeck. L'agent ne peut pas :
- Modifier les paramètres du workspace (/workspace/{id}/settings)
- Gérer les membres / rôles (workspace_members)
- Gérer l'authentification ou les intégrations OAuth (connexion/déconnexion Gitea/GitHub)
- Publier ou partager publiquement une page sans confirmation utilisateur (/api/pages/{id}/publish, /share)
- Modifier une collection verrouillée (is_locked = 1)
- Agir au-delà des permissions de l'utilisateur qui l'invoque
- Supprimer définitivement (hard delete) sans mode confirm
-------------------------
Résumé
FlowDeck Agent porte le modèle Notion Agent dans FlowDeck en réutilisant l'infrastructure existante :
- Un service AgentEngine orchestrant une boucle ReAct (raisonnement ↔ action)
- Des outils qui sont de simples wrappers des routers FastAPI existants (/db/*, /board/api/*, Gitea)
- Un contexte collecté via SearchEngine + GiteaClient, filtré par PermissionManager
- Un audit complet (agent_actions) avec rollback
- Custom Agents, skills et déclencheurs pour l'automatisation
Le passage de « l'IA qui répond » à « l'IA qui réalise le travail » se fait sans réécrire FlowDeck : l'agent agit comme un utilisateur privilégié mais contraint, à travers les mêmes portes que l'interface humaine.
J'ai créé le document `Flowdeck_Agent_integration.md`. Points saillants de l'intégration proposée :
- **Réutilisation maximale** : l'agent n'accède jamais directement à SQLite — il appelle les routers FastAPI existants (`/db/*`, `/board/api/*`, `GiteaClient`), ce qui garantit validation, cohérence et respect du `PermissionManager`.
- **Boucle ReAct** : Compréhension → Contexte → Raisonnement → Action, calquée sur le fonctionnement de Notion Agent mais mappée sur vos entités (`collections`, `collection_pages`, issues Gitea).
- **5 nouvelles tables** seulement (`agents`, `agent_conversations`, `agent_messages`, `agent_actions`, `agent_skills`), plus un router `agent.py` et 4 services.
- **Sécurité** : audit complet avec `undo_snapshot_json` pour rollback, respect des rôles workspace, mode `confirm` pour les actions destructives.
- **Custom Agents + Skills + déclencheurs** (cron via `lifespan`, webhooks via votre `webhooks.py` existant).