Skip to content

Step 3 — Output: AI-Enhanced Digest & DM Delivery

This final step completes the POC loop with intelligence. It proves the full AI pipeline by generating per-item summaries using the Symfony AI Bundle and delivering a formatted digest via Slack DM. Each knowledge item is condensed into 2–3 sentences followed by a direct link to its Notion page.

TIP

The AI provider stack introduced here is the same stack the MVP uses for all AI operations (summaries, content cleaning, etc.). Building it now saves significant rework later.

User Story

Story 3.1 — AI-Powered Digest

As a user, I want to generate a digest of recent knowledge for a list and receive a beautifully formatted DM where each item is summarized in 2–3 sentences with a link to its Notion page.

Example Output (Slack DM):

📊 Digest — LIJST: Design & UX
2 nieuwe items in de afgelopen 7 dagen

━━━━━━━━━━━━━━━━━━━━━━

📝 Accessibility Best Practices 2026
Nieuwe WCAG 3.0 richtlijnen benadrukken contrast-
en leesbaarheid. De focus verschuift van compliance
naar bruikbare inclusiviteit.
🔗 Bekijk in Notion

━━━━━━━━━━━━━━━━━━━━━━

📝 Dark Mode Design Patterns
Donkere achtergronden verbeteren de leesbaarheid op
OLED-schermen en verminderen batterijverbruik. Goede
implementatie vereist aangepaste kleurenpaletten.
🔗 Bekijk in Notion

━━━━━━━━━━━━━━━━━━━━━━

Architecture Flow

This flow introduces the AI Provider Layer into the generation pipeline:


The AI Provider Stack

The POC introduces the full Symfony AI provider stack. This is the same stack the MVP extends — no throwaway code.

Key Design Decisions

DecisionRationale
AiProviderInterfaceProvider-agnostic contract. MVP can swap OpenAI for Anthropic without touching business logic.
SymfonyAiProviderUses symfony/ai-bundle PlatformInterface directly. No custom gateway or auth override — clean standard integration.
Mock mode supportSymfonyAiProvider has a $mockMode flag. When true, returns deterministic text without calling OpenAI. Essential for testing.
Agent selectionTemperature-based agent routing (creative/balanced/precise). POC uses balanced for digest summaries.

Backend Files (9)

AI Provider Infrastructure (5 files)

These are the foundation for all future AI operations in the MVP (content cleaning, full summaries, prompt templates, etc.).

#FileLayerPurpose~LOC
1Service/Ai/AiProviderInterface.phpContractgenerateCompletion(prompt, options): AiResponse, getName(), getModel(), estimateCost(), getMaxTokens()59
2Service/Ai/SymfonyAi/SymfonyAiProvider.phpImplementationImplements interface via Symfony AI PlatformInterface. Agent selection (creative/balanced/precise), cost calculation, mock mode. No custom gateway/auth override.180
3Service/Ai/AiResponse.phpDTOImmutable result: content, promptTokens, completionTokens, cost, model, metadata43
4DTO/Ai/AiOptionsDto.phpDTOtemperature, maxTokens, topP, frequencyPenalty, presencePenalty, seed, model, timeout50
5DTO/Ai/AiMetadataDto.phpDTOdurationMs, finishReason, provider, systemFingerprint, mock, extra30

Digest Domain (4 files)

#FileLayerPurpose~LOC
6Service/Digest/DigestAiSummaryGenerator.phpDomain ServicegenerateItemSummary(Knowledge): string — builds a prompt from the knowledge content and calls AiProviderInterface. Hardcoded Dutch prompt template (POC only). Fallback: returns truncated content if AI fails.100
7Service/Digest/DigestQueryService.phpQuery ServicefindKnowledgeForDigest(categoryId, dateRange): Knowledge[], parseDateRange(string): DateRangeDto. Extends BaseQueryService.80
8Service/Digest/DigestOrchestrator.phpOrchestratorgenerateDigest(categoryId, dateRange) — queries items via DigestQueryService, generates per-item AI summaries via DigestAiSummaryGenerator, builds response with Notion URLs from Knowledge::notionId. Extends BaseOrchestrator.130
9Controller/DigestController.phpPresentationPOST /api/digests/generate — accepts categoryId + dateRange, delegates to orchestrator.50

IMPORTANT

Simplified for POC: The DigestAiSummaryGenerator uses a hardcoded prompt template, not PromptTemplate entities or PromptBuilderService. Those are MVP features.

POC Prompt Template (Hardcoded)

The generator uses this embedded prompt — no database-backed templates needed:

Vat het volgende kennisitem samen in 2-3 beknopte zinnen in het Nederlands.
Focus op de kernboodschap en praktische relevantie.

Titel: {{title}}
Inhoud: {{content}}

Samenvatting:

Slack Files (3)

#FileResponsibilities~LOC
1views/modals/digest/generateDigest.tsModal UI: Category dropdown, Days numeric input.60
2services/digest.tsgenerateDigest(categoryId, dateRange) — POST /api/digests/generate.40
3handlers/knowledge/itemActions.tshandleGenerateDigest() — extract modal values, call backend, build Block Kit DM with: Header → per-item AI summary + Notion linkstatistics footer. This handler IS the delivery mechanism.150

Block Kit DM Structure

The Slack handler builds these blocks from the backend response:

┌─────────────────────────────────────────┐
│  📊 Digest — {categoryName}             │  ← Header block
│  {itemCount} items · afgelopen {days}d  │  ← Section block
├─────────────────────────────────────────┤
│  ─────────────────────────────────      │  ← Divider
│                                         │
│  📝 *{item.title}*                      │  ← Section block
│  {item.aiSummary}                       │  ← 2-3 sentences from AI
│  🔗 <{notionUrl}|Bekijk in Notion>      │  ← Notion link
│  _Tags: {tags}_                         │  ← Context block
│                                         │
│  ─────────────────────────────────      │  ← Divider
│  ... repeat for each item ...           │
└─────────────────────────────────────────┘

Updating Existing Code

The following files from Step 1 are updated:

  • app.ts: Register the digest view submission callback
  • views/home/dynamicHomeTab.ts: Add "Digest Maken" button to the Quick Actions row

Notion URL Construction

Each knowledge item has a notionId field (populated when synced to Notion). The Notion URL is constructed as:

https://notion.so/{notionId with dashes removed}

If notionId is null (item not yet synced), the link is omitted and only the AI summary is shown.


Verification Checklist

  • [ ] Click "Digest Maken" on the App Home
  • [ ] Select a list and set timeframe (e.g., 7 days)
  • [ ] Receive a DM from the bot
  • [ ] Each item in the DM has a 2–3 sentence AI-generated summary (not raw content)
  • [ ] Each item with a notionId includes a clickable Notion link
  • [ ] If no items exist for the period → polite "Geen items gevonden" message
  • [ ] If AI fails (API key missing / mock mode) → fallback shows truncated raw content instead

Step 3 LOC Summary

ComponentFiles~LOC
AI Provider stack5362
Digest services2210
Digest controller150
Slack modal/service2100
Slack handler1150
Total12~872

NOTE

Step 3 is larger than originally planned (~460 LOC → ~872 LOC) due to the AI provider stack. This is intentional — the 5 AI files are MVP foundational infrastructure, not throwaway POC code.