---
name: langflow-basics
description: >
  Use when: explaining Langflow concepts, installing Langflow, configuring flows, understanding
  nodes/edges/executions, or integrating Langflow with VorstersNV stack (Ollama/FastAPI/PostgreSQL).
  Triggers: "wat is Langflow", "Langflow installeren", "Langflow nodes uitleg", "flow execution",
  "Langflow vs agent_runner", "Langflow architectuur", "visual workflow", "low-code AI"
allowed-tools: [view, grep, glob]
context: fork
---

# SKILL: Langflow Basics

Reference knowledge voor **Langflow visual AI workflow builder** in het VorstersNV platform.

---

## Wat is Langflow?

**Langflow** is een open-source **low-code** tool voor het bouwen van LLM-applicaties via drag-and-drop.
Het is vergelijkbaar met n8n maar specifiek ontworpen voor **AI workflows** (LLMs, vector databases, agents).

**Kernfunctionaliteit**:
- ✅ Visual flow editor (nodes + edges)
- ✅ Native Ollama support (lokale LLMs)
- ✅ Python backend (FastAPI-based)
- ✅ PostgreSQL voor flows opslag
- ✅ REST API voor flow executions
- ✅ Component marketplace (herbruikbare nodes)

**VorstersNV context**: Langflow stelt klanten in staat om hun eigen AI-agents te bouwen **zonder code**,
terwijl VorstersNV bestaande `agents/*.yml` blijft gebruiken voor productie workloads.

---

## Architectuur in VorstersNV Stack

```
┌──────────────────────────────────────────────────────────────────┐
│  VorstersNV Portal (Next.js :3000)                                │
│    ├─ AI Studio tab → iframe naar Langflow UI (:7860)            │
│    └─ Flow executions via FastAPI /api/langflow/execute          │
├──────────────────────────────────────────────────────────────────┤
│  Langflow Service (Docker :7860)                                  │
│    ├─ Flow Designer UI (React)                                    │
│    ├─ Execution Engine (Python/FastAPI)                           │
│    └─ Flow Storage (PostgreSQL langflow schema)                   │
├──────────────────────────────────────────────────────────────────┤
│  Shared Resources                                                 │
│    ├─ Ollama :11434 (mistral, llama3.2) ← gebruikt door beide    │
│    ├─ PostgreSQL :5432 (vorstersNV DB + langflow schema)          │
│    └─ FastAPI :8000 (custom endpoints)                            │
└──────────────────────────────────────────────────────────────────┘
```

**Geen conflict**: `agent_runner.py` en Langflow **delen** Ollama — Ollama is stateless en kan
concurrent gebruikt worden.

---

## Core Concepten

### 1. Nodes (Bouwstenen)

Een **node** is een functie/transformatie in de flow. Elke node heeft:
- **Inputs** (linker kant, groene dots)
- **Outputs** (rechter kant, blauwe dots)
- **Configuratie** (parameters zoals model, temperature, prompt)

**Veel gebruikte node types**:

| Node Type | Icon | Doel | Configuratie |
|-----------|------|------|-------------|
| **LLM (Ollama)** | 🤖 | Roept Ollama model aan | `model`, `temperature`, `base_url` |
| **Prompt** | 📝 | Template voor LLM input | Jinja2-style: `{variable}` |
| **Python Code** | 🐍 | Custom logic | Python function met `return` |
| **Text Input** | ⌨️ | User input capture | Validatie regex/length |
| **Vector Store** | 🗄️ | Embeddings opslag | PostgreSQL pgvector |
| **Chain** | 🔗 | Sequentie van nodes | Linear flow |
| **Agent** | 🎯 | LangChain agent | Reasoning + tool use |
| **Output** | 📤 | Eindresultaat | Format: text/JSON/markdown |

### 2. Edges (Verbindingen)

Een **edge** is een lijn tussen twee nodes die data doorgeeft.

**Voorbeeld**:
```
[User Input] ───(question)───> [Prompt Template]
                                      ↓
                                (formatted_prompt)
                                      ↓
                               [Ollama LLM]
                                      ↓
                                  (answer)
                                      ↓
                               [Text Output]
```

Data flow: `question` → `formatted_prompt` → `answer`.

### 3. Flows

Een **flow** is een volledige workflow (nodes + edges + configuratie).

**Flow lifecycle**:
1. **Design** — bouw in Langflow UI
2. **Save** — opgeslagen in PostgreSQL `langflow.flows` tabel (JSON)
3. **Execute** — run via UI of API call
4. **Log** — execution details in `langflow.executions` tabel

**Flow JSON voorbeeld** (simplified):
```json
{
  "name": "FAQ Bot",
  "nodes": [
    {"id": "1", "type": "TextInput", "data": {"label": "Vraag"}},
    {"id": "2", "type": "OllamaLLM", "data": {"model": "mistral"}},
    {"id": "3", "type": "TextOutput"}
  ],
  "edges": [
    {"source": "1", "target": "2", "sourceHandle": "output", "targetHandle": "input"},
    {"source": "2", "target": "3", "sourceHandle": "output", "targetHandle": "input"}
  ]
}
```

### 4. Executions

Een **execution** is één run van een flow met specifieke inputs.

**Voorbeeld**:
```
Flow: "FAQ Bot"
Execution 1: input={"vraag": "Wat zijn jullie openingstijden?"} → output="Ma-Vr 9-17u"
Execution 2: input={"vraag": "Leveren jullie in België?"} → output="Ja, gratis vanaf €50"
```

Elke execution wordt gelogd met:
- `started_at`, `completed_at` (timestamps)
- `status` (`success`, `failed`, `running`)
- `inputs`, `outputs` (JSON)

---

## Ollama Integratie

### Configuratie Ollama Node

**In Langflow UI**:
1. Drag "Ollama LLM" node naar canvas
2. Configureer:
   - **Base URL**: `http://host.docker.internal:11434` (Docker Desktop) of `http://172.17.0.1:11434` (Linux)
   - **Model**: `mistral` of `llama3.2` (beschikbare modellen in VorstersNV)
   - **Temperature**: `0.4` (standaard), `0.1` (deterministisch), `0.8` (creatief)
   - **Max Tokens**: `4096` (maximaal voor mistral)

**Test connectie**:
```bash
# Vanuit Langflow container
docker exec vorstersNV-langflow curl http://host.docker.internal:11434/api/tags
# Moet modellen tonen: mistral, llama3.2
```

### Model Selectie

| Use Case | Model | Reden |
|----------|-------|-------|
| Code analyse | `mistral` | Beter op logica + structured output |
| Lange documenten | `mistral` | 4096 token context |
| Snelle responses | `llama3.2` | Kleiner model (3.2B vs 7.2B) |
| NL/FR content | `mistral` | Betere meertaligheid |

**Kosten**: Ollama is **gratis** (lokaal), maar GPU-tijd is beperkt op laptop → queue executions.

---

## VorstersNV vs Langflow: Wanneer Wat Gebruiken?

| Scenario | Tool | Reden |
|----------|------|-------|
| **Klant wil zelf agent bouwen** | Langflow | No-code UI, self-service |
| **Productie batch processing** | `agent_runner.py` | Sneller, geen UI overhead |
| **Prototype testen** | Langflow | Visueel debuggen, snel itereren |
| **Complexe state machine (>20 steps)** | `agent_runner.py` | YAML is overzichtelijker dan 20+ nodes |
| **Demo voor prospect** | Langflow | Visueel overtuigend |
| **CI/CD geautomatiseerd** | `agent_runner.py` | Headless execution |

**Beste practice**: Start in Langflow (rapid prototyping), converteer naar YAML als het production-ready is.

---

## Installatie & Setup

### Lokaal (Docker Compose)

```yaml
# docker-compose.yml toevoeging
services:
  langflow:
    image: langflowai/langflow:1.0.0  # pin versie!
    container_name: vorstersNV-langflow
    ports:
      - "7860:7860"
    environment:
      - LANGFLOW_DATABASE_URL=postgresql://vorstersNV:${DB_PASSWORD}@database:5432/vorstersNV
      - LANGFLOW_OLLAMA_URL=http://host.docker.internal:11434
      - LANGFLOW_LOG_LEVEL=INFO
    depends_on:
      database:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7860/health"]
      interval: 30s
      timeout: 10s
      retries: 3
```

**Start**:
```bash
docker compose up -d langflow
```

**Eerste keer setup**:
```bash
# Maak admin user
docker exec -it vorstersNV-langflow langflow superuser \
  --username admin@vorstersnv.be \
  --password <sterk-wachtwoord>
```

**Toegang**: http://localhost:7860

---

## API Usage (Vanuit FastAPI)

### Flow Execution via API

```python
# api/routers/langflow.py (voorbeeld)
from fastapi import APIRouter
import httpx

router = APIRouter(prefix="/langflow", tags=["Langflow"])

@router.post("/execute/{flow_id}")
async def execute_flow(flow_id: str, inputs: dict):
    """Voer een Langflow flow uit en return resultaat"""
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"http://langflow:7860/api/v1/run/{flow_id}",
            json={"inputs": inputs},
            timeout=30.0
        )
    return response.json()
```

**Voorbeeld call**:
```bash
curl -X POST http://localhost:8000/api/langflow/execute/abc-123 \
  -H "Content-Type: application/json" \
  -d '{"inputs": {"vraag": "Wat zijn de openingstijden?"}}'
```

**Response**:
```json
{
  "result": {
    "answer": "Onze openingstijden zijn ma-vr 9:00-17:00."
  },
  "session_id": "def-456"
}
```

---

## Best Practices

### 1. Flow Naming Convention

```
<klant>_<use-case>_<versie>

Voorbeelden:
- acme_faq_bot_v1
- shop_btw_validator_v2
- demo_contract_analyse_v1
```

### 2. Prompt Engineering in Flows

**Anti-pattern**:
```
Prompt: "Beantwoord de vraag"
```

**Best practice**:
```
Prompt: """
Je bent een vriendelijke klantenservice medewerker voor {bedrijf_naam}.
Beantwoord in {taal} (NL of FR).
Gebruik formele toon bij klachten, informele toon bij vragen.

Context:
{kennisbank_docs}

Klantvraag:
{vraag}

Antwoord (max 200 woorden):
"""
```

### 3. Error Handling

Voeg altijd een "Error Handler" node toe:

```
[LLM Node] → [Check Output Valid?]
                  ├─ Yes → [Success Output]
                  └─ No  → [Error Output: "Sorry, kon geen antwoord genereren"]
```

### 4. Logging

Enable execution logging:
```python
# In Python Code node
import logging
logger = logging.getLogger("langflow")

logger.info(f"Processing input: {input_data}")
# ... processing
logger.info(f"Generated output: {output_data}")
```

Logs verschijnen in `docker logs vorstersNV-langflow`.

---

## Troubleshooting

### "Ollama model not found"

**Symptoom**: Error `Model 'mistral' not found`.

**Diagnose**:
```bash
# Check beschikbare modellen
ollama list
```

**Oplossing**:
```bash
# Download model
ollama pull mistral
```

### "Flow execution timeout"

**Symptoom**: Execution blijft hangen op "running".

**Diagnose**:
```sql
SELECT * FROM langflow.executions WHERE status = 'running' AND started_at < NOW() - INTERVAL '5 minutes';
```

**Oplossing**:
- Check Ollama logs: `docker logs ollama`
- Check Langflow logs: `docker logs vorstersNV-langflow`
- Kill stuck execution manueel in DB

### "Database connection failed"

**Symptoom**: Langflow kan niet starten.

**Diagnose**:
```bash
docker logs vorstersNV-langflow | grep -i "database"
```

**Oplossing**:
- Check PostgreSQL draait: `docker ps | grep database`
- Check `LANGFLOW_DATABASE_URL` env var correct is
- Check database exists: `psql -U vorstersNV -d vorstersNV -c "\dn"` (moet `langflow` schema tonen)

---

## Resources

- Langflow docs: https://docs.langflow.org/
- Langflow GitHub: https://github.com/langflow-ai/langflow
- VorstersNV implementatieplan: `documentatie/architectuur/langflow-integratie-plan.md`
- Agent conversie guide: `.claude/agents/langflow-flow-designer.md`
