Document Notion Agent (2026) concepts and a FlowDeck Agent design that orchestrates tool calls through existing FastAPI routers, plus a chat UI screenshot.
703 lines
34 KiB
Markdown
703 lines
34 KiB
Markdown
# 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).
|