managarten/docs/reports/gemini-deep-research.md
Till JS b1b9bbc269
Some checks are pending
CD Mac Mini / Detect Changes (push) Waiting to run
CD Mac Mini / Deploy (push) Blocked by required conditions
CI / Detect Changes (push) Waiting to run
CI / Validate (push) Waiting to run
CI / Build mana-search (push) Blocked by required conditions
CI / Build mana-sync (push) Blocked by required conditions
CI / Build mana-api-gateway (push) Blocked by required conditions
CI / Build mana-crawler (push) Blocked by required conditions
Docker Validate / Validate Dockerfiles (push) Waiting to run
Docker Validate / Build calendar-web (push) Blocked by required conditions
Docker Validate / Build quotes-web (push) Blocked by required conditions
Docker Validate / Build todo-backend (push) Blocked by required conditions
Docker Validate / Build todo-web (push) Blocked by required conditions
Docker Validate / Build mana-auth (push) Blocked by required conditions
Docker Validate / Build mana-sync (push) Blocked by required conditions
Docker Validate / Build mana-media (push) Blocked by required conditions
Mirror to Forgejo / Push to Forgejo (push) Waiting to run
chore: rename repo mana-monorepo → managarten
Phase-3-Rename des ehemaligen Multi-App-Monorepos zum eigenständigen
Produkt-Repo. Verein heißt mana e.V., Plattform-Domain bleibt mana.how,
apps/mana/ bleibt unverändert — nur der Repo-Container kriegt den
neuen Namen "managarten" (Garten der mana-Apps).

Geändert:
- package.json#name + #description
- README.md (Titel + erster Absatz)
- TROUBLESHOOTING.md
- alle Mac-Mini-Skripte (Pfade ~/projects/mana-monorepo → ~/projects/managarten)
- COMPOSE_PROJECT_NAME-default in scripts/mac-mini/status.sh
- .github/workflows/cd-macmini.yml + mirror-to-forgejo.yml
- apps/docs (astro.config.mjs + content)
- .claude/settings.local.json (Bash-Permission-Pfade)
- alle docs/*.md Pfad-Referenzen
- launchd plists, .env.macmini.example, infrastructure/

Forgejo-Repo + GitHub-Repo bereits via API umbenannt. Lokales
Verzeichnis-Rename + Mac-Mini-Cutover folgen separat.
2026-05-09 01:16:02 +02:00

451 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Gemini 3.1 Pro Deep Research & Deep Research Max
**Datum:** 2026-04-22
**Anlass:** Googles Launch am 2026-04-21 — zwei autonome Research-Agenten auf Basis von Gemini 3.1 Pro, verfügbar als Public Preview über die Gemini API.
**Status:** Schritt 1 + 2 geliefert und **deployt auf Mac-Mini** (2026-04-22 18:21 MESZ). `MANA_AI_DEEP_RESEARCH_ENABLED=false` — Feature ist dark, Infra bereit. Schritt 3 (MCP-Server) geplant, nicht implementiert.
## TL;DR
Google hat zwei neue Research-Agenten veröffentlicht, die bei uns direkt in die Provider-Landschaft von `mana-research` passen und die Phase-3b-Lücke (`openai-deep-research` als einziger async Agent) auf natürliche Weise ergänzen. Besonderheit: **beide Agenten sprechen Model Context Protocol (MCP)**, wodurch sie potenziell an *unsere* Daten andocken könnten — was in Kombination mit dem existierenden AI-Mission-Key-Grant-System (RSA-wrapped MDK, audit-logged) ein strategisch interessanter Vektor ist.
Schritt 1 (async Provider) und Schritt 2 (`mana-ai` Cross-Tick-Pre-Research) sind geliefert und hinter einem Opt-in-Flag (`MANA_AI_DEEP_RESEARCH_ENABLED=true`) aktivierbar. Schritt 3 (MCP-Server für unsere verschlüsselten Kontextdaten) ist spezifiziert, aber Security-Review erforderlich vor Rollout.
## 1. Die Modelle im Detail
### 1.1 Varianten und Positionierung
| | **Deep Research** | **Deep Research Max** |
|---|---|---|
| **Model-ID** | `deep-research-preview-04-2026` | `deep-research-max-preview-04-2026` |
| **Zielbild** | Interaktiv, niedrige Latenz, eingebettet in User-Surfaces | Asynchron, nächtliche Cron-Jobs, maximale Tiefe |
| **Typ. Laufzeit** | Minutenbereich (eingebaut in Chat-UIs) | Bis zu 60 min (typ. ~20 min) |
| **Typ. Volumen** | ~80 Suchen, ~250k Input-Tokens, ~60k Output | ~160 Suchen, ~900k Input-Tokens, ~80k Output |
| **Preis (geschätzt)** | $1.003.00 pro Task | $3.007.00 pro Task |
| **DeepSearchQA** | — | 93.3 % (von 66.1 % im Dez 2025) |
| **Humanity's Last Exam** | — | 54.6 % (von 46.4 %) |
Beide laufen ausschließlich **async** (`background=true` ist Pflicht, `store=true` erforderlich). Es gibt keinen synchronen Request-Response-Modus wie bei `gemini-grounding`.
### 1.2 API-Shape — submit
```
POST https://generativelanguage.googleapis.com/v1beta/interactions
x-goog-api-key: <GOOGLE_GENAI_API_KEY>
Content-Type: application/json
{
"agent": "deep-research-preview-04-2026",
"input": "query",
"background": true,
"store": true,
"agent_config": {
"type": "deep-research",
"thinking_summaries": "auto", // Live-Gedanken streamen
"visualization": "auto", // Charts/Infographics inline
"collaborative_planning": false
},
"tools": [
{ "type": "google_search" },
{ "type": "url_context" },
{ "type": "code_execution" },
{ "type": "file_search" },
{
"type": "mcp_server",
"name": "mana-kontext",
"url": "https://mcp.mana.how/...",
"headers": { "Authorization": "Bearer …" },
"allowed_tools": ["search_notes", "search_journal"]
}
]
}
→ 200
{
"id": "v1_Chd...",
"status": "in_progress",
"role": "agent",
"created": "...",
"agent": "deep-research-preview-04-2026"
}
```
### 1.3 API-Shape — poll (completed)
Die tatsächlich beobachtete Response-Shape (Smoke-Test am 2026-04-22) weicht von der OpenAI-Responses-API deutlich ab. Wir hatten initial OpenAI-Style (`output: [{type:'message', content:[...]}]`) erwartet — die echte Shape sieht so aus:
```
GET https://generativelanguage.googleapis.com/v1beta/interactions/{id}
→ 200
{
"id": "v1_Chd...",
"status": "completed",
"outputs": [ // Plural! Flaches Array.
{ "type": "thought",
"signature": "...",
"summary": [ // Thought-Summaries als Liste
{ "type": "text", "text": "..." }
]
},
{}, // Gelegentlich leer → ignorieren
{ "type": "text",
"text": "# Hono and Bun...",
"annotations": [
{ "type": "url_citation",
"url": "https://...",
"start_index": 268,
"end_index": 283
}
]
},
{ "type": "image",
"mime_type": "image/png",
"data": "<base64>" // Charts/Infographics
},
{ "type": "text", "text": "**Sources:** ..." }
],
"usage": {
"total_tokens": 145268,
"total_input_tokens": 93025,
"total_output_tokens": 7770,
"total_cached_tokens": 16384, // Prompt-Cache
"total_tool_use_tokens": 28371,
"total_thought_tokens": 16102,
"input_tokens_by_modality": [...],
"output_tokens_by_modality": [...]
},
"role": "agent",
"object": "interaction",
"agent": "deep-research-preview-04-2026"
}
```
Wichtig für den Parser:
- **`outputs` (nicht `output`)** ist ein flaches Array mit `type: 'thought' | 'text' | 'image' | null`
- `text` items haben `annotations[]` mit `type: 'url_citation'`, `url`, `start_index`/`end_index`**kein `title`-Feld**, wir ziehen den Hostname aus der URL
- `image` items tragen base64-codierte Bilder (PNG) als `data` mit `mime_type`
- `thought` items sind die live-gestreamten Reasoning-Summaries — wenn wir nur den finalen Report brauchen, skip
- `usage` nutzt `total_input_tokens` / `total_output_tokens` (nicht `input_tokens` / `output_tokens`)
### 1.4 Was die Agenten können
- **Autonom planen** und iterativ nachsuchen, bis sie eine Antwort haben
- **Google Search + URL Context + Code Execution + File Search** parallel oder einzeln; Web-Zugriff lässt sich auch komplett deaktivieren (Pure-MCP-Mode)
- **MCP-Server** als Brücke zu proprietären Datenquellen — Enterprise-Partner sind FactSet, S&P Global, PitchBook
- **Native Visualisierung**: Charts und Infographics inline als HTML oder Nano-Banana
- **Thought-Summaries** als Live-Stream — brauchbar für "Agent denkt gerade…"-UIs
- **Keine** Structured Outputs, **keine** custom Function-Calls (dafür gibt es MCP)
## 2. Einordnung in unsere Landschaft
### 2.1 `mana-research` (port 3068)
Phase 3a liefert vier **synchrone** Agents (`perplexity-sonar`, `gemini-grounding`, `openai-responses`, `claude-web-search`). Phase 3b war ursprünglich nur für `openai-deep-research` (1000 credits) vorgesehen; mit Schritt 1 kommen die beiden Gemini-Async-Provider dazu und verdoppeln die Abdeckung des Max-Tiers.
### 2.2 `mana-ai` (port 3067)
v0.6 hatte den RSS-basierten `NewsResearchClient` und den **Pre-Planning-Research-Step** geshipped. Mit Schritt 2 (v0.7) kommt daneben ein zweiter Pfad: wenn eine Mission explizit nach deep research fragt und der Service die entsprechende ENV-Flag gesetzt hat, wird statt RSS eine async Gemini Deep Research Max Task submittet und über Ticks hinweg gepollt.
## 3. Integrationsplan — Status
| Schritt | Status | Datum | Details |
|---|---|---|---|
| 1 — Gemini als async Provider in mana-research | ✅ Geliefert | 2026-04-22 | §3.1 |
| 2 — Cross-Tick Deep-Research in mana-ai | ✅ Geliefert | 2026-04-22 | §3.2 |
| 3 — MCP-Server für unsere Daten | ⏳ Spezifiziert | — | §3.3 |
### 3.1 Schritt 1 — `gemini-deep-research[-max]` als async Provider — ✅ GELIEFERT
Zwei neue Provider-IDs neben `openai-deep-research` in `mana-research`:
**Geänderte/neue Dateien:**
- `packages/shared-research/src/ids.ts``AGENT_PROVIDER_IDS` erweitert um `gemini-deep-research` + `gemini-deep-research-max`
- `services/mana-research/src/providers/agent/gemini-deep-research.ts` — neuer Provider, submit/poll-Split tier-parametrisiert (`standard`/`max`). Parser nutzt die echte Response-Shape aus §1.3.
- `services/mana-research/src/routes/research.ts``/async` POST + `/async/:id` GET dispatchen via `dispatchAsync(providerId, config)`. Default: `openai-deep-research` (backward compatible).
- `services/mana-research/src/routes/internal-research.ts`**neu** — service-to-service Pendant unter `/api/v1/internal/research/async`, gated durch `X-Service-Key` + `X-User-Id` Header für Credit-Accounting.
- `src/lib/pricing.ts` — 300 / 1500 credits (Standard / Max)
- `src/executor/env-map.ts` + `src/router/auto-route.ts` — beide neue IDs auf `googleGenai`, explizit **nicht** in `AGENT_DEFAULT_ORDER` (sync-Auto-Route überspringt sie; nur `/async` erreichbar)
- `src/routes/providers.ts` — Health-keyMap ergänzt
- `src/index.ts` — internal route gemountet unter `/api/v1/internal/research/*`
- `services/mana-research/API_KEYS.md` + `CLAUDE.md` — dokumentiert
**Use (user-facing):**
```
POST /api/v1/research/async
{ "query": "…", "provider": "gemini-deep-research-max" }
→ { taskId, status: "queued", providerId, costCredits: 1500 }
GET /api/v1/research/async/:taskId
```
**Use (service-to-service):**
```
POST /api/v1/internal/research/async
X-Service-Key: <MANA_SERVICE_KEY>
X-User-Id: <userId>
{ "query": "…", "provider": "gemini-deep-research-max" }
```
**Verifiziert** mit echtem `GOOGLE_GENAI_API_KEY` am 2026-04-22: submit + poll über Googles Preview-API → HTTP 200 in beiden Richtungen, completed Response korrekt geparst.
### 3.2 Schritt 2 — `mana-ai` v0.7 Cross-Tick Deep Research — ✅ GELIEFERT
**Problem:** Max-Tasks laufen bis 60 min. Der mana-ai Tick-Loop läuft alle 60 s. Wir brauchen Cross-Tick-State, um genau einen pending Research-Job pro Mission zu tracken und über mehrere Ticks zu pollen, ohne neu zu submitten.
**Geänderte/neue Dateien:**
- `services/mana-ai/src/clients/mana-research.ts`**neu** — HTTP-Client für die internen Async-Endpoints. Graceful-null bei Fehler, damit eine kaputte mana-research den Tick nicht crasht.
- `services/mana-ai/src/db/migrate.ts` — neue Tabelle `mana_ai.mission_research_jobs (user_id, mission_id, task_id, provider_id, submitted_at, last_polled_at)` mit PK `(user_id, mission_id)`. Ein Row = es läuft ein Job.
- `services/mana-ai/src/db/research-jobs.ts`**neu**`get/insert/touch/delete`. Nach `completed`/`failed`: DELETE.
- `services/mana-ai/src/cron/tick.ts`:
- neuer `handleDeepResearch(m, sql, config)` mit State-Machine:
- Wenn pending Job existiert → poll
- `queued`/`running``'pending'` (skip tick)
- `failed`/`cancelled` → delete, fall through zu shallow
- `completed` → delete + return ResolvedInput
- Kein Job aber `DEEP_RESEARCH_TRIGGER` + `config.deepResearchEnabled` → submit + insert → `'pending'`
- `planOneMission` Rückgabetyp auf Discriminated Union erweitert: `{outcome:'planned'|'skipped'|'failed'}` statt `T | null`, damit skipped-wegen-pending-research nicht als parse-failure gezählt wird
- Shallow RSS-Pfad läuft nur noch, wenn deep weder ein Ergebnis geliefert hat, noch pending ist
- `services/mana-ai/src/config.ts``manaResearchUrl` + `deepResearchEnabled` (`MANA_AI_DEEP_RESEARCH_ENABLED`)
- `services/mana-ai/src/metrics.ts` — vier neue Counter: `mana_ai_research_jobs_submitted_total{provider}`, `_completed_total{provider}`, `_failed_total{provider}`, `_pending_skips_total`
- `services/mana-ai/package.json``@mana/shared-research` als workspace-dep + `type-check` script
- `docker-compose.macmini.yml` — mana-ai bekommt `MANA_RESEARCH_URL`, `MANA_AI_DEEP_RESEARCH_ENABLED` (default `false`), `depends_on: mana-research`
**Opt-in-Trigger (streng enger als shallow):**
```
DEEP_RESEARCH_TRIGGER = /\b(deep research|tiefe recherche|umfassende recherche|hintergrundrecherche|deep dive)\b/i
```
Zusätzlich per ENV gegated. In Prod default off; ein expliziter Flip erlaubt Rollout nur an uns selbst / Founder-Tier zuerst.
**Flow:**
```
tick N-1: Mission X, objective: "deep research zu Thema Y"
├ RESEARCH_TRIGGER matched UND DEEP_RESEARCH_TRIGGER matched
├ config.deepResearchEnabled = true
├ client.submit(userId, "deep research zu…", "gemini-deep-research-max")
│ → { taskId, status: "queued", costCredits: 1500 }
├ INSERT INTO mana_ai.mission_research_jobs (task_id, …)
└ skip planner this tick
tick N, N+1, … während Google den Task ausarbeitet (~20 min):
├ SELECT * FROM mana_ai.mission_research_jobs WHERE (user_id, mission_id) = …
├ client.poll(userId, taskId) → { status: "running" }
├ touchPendingResearchJob() bumpt last_polled_at
└ skip planner this tick
tick N+k: Max ist fertig
├ client.poll(userId, taskId) → { status: "completed", result: { answer: {...} } }
├ DELETE FROM mana_ai.mission_research_jobs WHERE …
├ resolvedInputs.push({id:"__web-research__", content: formatDeepResearchContext(...)})
└ Planner läuft mit Deep-Research-Kontext als Input
```
**Graceful Degradation:** Wenn `mana-research` down oder der Gemini-Submit 500t, fällt die Mission auf den Shallow-RSS-Pfad zurück. Wenn ein bereits submittierter Job nicht mehr gepollt werden kann, rotiert der Row ab über `touchPendingResearchJob`, bis manuelle Intervention oder ein späterer poll Erfolg hat.
### 3.3 Schritt 3 — MCP-Server für verschlüsselte Kontextdaten — ⏳ SPEZIFIZIERT
**Warum der Aufwand:** Der Grund, warum dieses Feature gerade *für uns* strategisch ist: wir haben ein Zero-Knowledge-Crypto-Setup mit per-mission Key-Grants (RSA-OAEP-2048 wrapped MDK, HKDF-Scope-Binding, audit-logged). Das MCP-Pattern kreuzt exakt unsere Stärke (lokale, verschlüsselte Daten) mit Googles Stärke (Deep-Research-Synthese). Positioning: **"Deep Research, das deine Kontextdaten kennt — ohne sie in Google's Trainings-Pipeline zu schicken"**.
#### 3.3.1 Architektur
```
┌──────────────────┐ ┌──────────────────┐
│ Gemini DR Max │◀──────│ mana-mcp-server │ (Cloudflare-tunneled,
│ (bei Google) │ MCP │ (neu, port 3069)│ öffentlich erreichbar)
└──────────────────┘ └──────┬───────────┘
│ Bearer <mcp-token>
│ (Mission-ID, TTL-clamped)
┌──────────────────┐
│ mana-auth │ verifiziert token,
│ │ lädt Mission-Grant,
│ /api/v1/mcp- │ unwrappt MDK
│ token/verify │
└──────┬───────────┘
┌──────────────────┐ ┌─────────────────┐
│ Encrypted-Data │──────▶│ mana_sync DB │
│ Resolver │ │ (+ RLS) │
│ (re-use of │ └─────────────────┘
│ mana-ai's │
│ encrypted.ts) │
└──────────────────┘
```
Der neue Service `mana-mcp` übernimmt die Rolle des MCP-Servers für Gemini. Er:
1. **hört auf eingehende MCP-Requests** von Google (z. B. `tools/call` mit `search_notes`), authentifiziert per **Bearer-Token pro Mission**. Der Token ist kein JWT, sondern eine opaque ID, die in mana-auth auf `{missionId, userId, allowedTools, expiresAt}` aufgelöst wird — analog zum existierenden Mission-Key-Grant.
2. **verifiziert das Token** gegen mana-auth's neue `/api/v1/mcp-token/verify` Route (returned `{userId, missionId, mdk-wrapped, allowedTools}` oder 401).
3. **unwrappt den Mission-Grant** (MDK) via den existierenden `crypto/unwrap-grant.ts`-Code aus mana-ai — wird in ein geteiltes Paket `@mana/mission-grant` gehoben.
4. **liest und entschlüsselt** die relevanten Records aus `mana_sync` via den existierenden `encrypted.ts` Resolver-Pattern (ebenfalls ins gleiche Paket heben).
5. **antwortet in MCP-Shape** mit Titel + Body + URL pro gefundenem Record.
#### 3.3.2 Tool-Set (Minimal)
Start mit drei readonly Tools, alle audit-logged nach `mana_ai.decrypt_audit`:
| Tool | Signatur | Was es macht |
|---|---|---|
| `search_notes` | `(query: string, limit?: number)` | Volltext über entschlüsselte Notizen |
| `search_journal` | `(date_range?: {from,to}, query?: string, limit?: number)` | Journal-Einträge nach Datum + Query |
| `search_kontext` | `(scope: string)` | Kontext-Felder aus dem Interview (bereits strukturiert) |
Alle drei sind scoped auf die Mission — sie sehen nur Records, die der Mission-Grant in der Allowlist hat. Schreibende Tools bewusst nicht.
#### 3.3.3 Token-Lifecycle
1. **Mission-Erstellung (Webapp):** Wenn eine Mission für Deep-Research-Max konfiguriert wird, erzeugt die Webapp zusätzlich zum existierenden Key-Grant einen **MCP-Token** via `POST /api/v1/me/ai-mission-mcp-token` auf mana-auth. Der Endpoint:
- erzeugt eine opaque Bearer-ID (crypto random, 32 bytes)
- speichert sie in `mana_auth.mcp_tokens` mit `{tokenHash, userId, missionId, allowedTools, expiresAt}`
- TTL-clamped [1h, 7d] — kürzer als Key-Grants, weil das Token exakt einen Research-Run abdeckt
2. **Submit (mana-ai):** Beim Submit der Max-Task wird der MCP-Token als `headers.Authorization` in den `tools.mcp_server`-Block eingebaut, passend zum Request-Shape aus §1.2.
3. **MCP-Call (mana-mcp):** Jeder eingehende Request wird via mana-auth verifiziert. Bei `expires`/unbekanntem Token → 401. Bei OK → Resolver-Aufruf + audit-row.
4. **Teardown:** Nach Poll-Result `completed`/`failed` markiert mana-ai den Token als verbraucht (mana-auth DELETE). Auch expirte Tokens werden über einen Cron entfernt.
#### 3.3.4 Was wir neu bauen müssen
| Komponente | Umfang |
|---|---|
| `services/mana-mcp/` | Neuer Bun/Hono-Service, ~500 LOC. MCP-Protokoll (JSON-RPC über HTTP), 3 Tool-Handler, Bearer-Auth. |
| `packages/mission-grant/` | Wiederverwendbares Paket mit `unwrapMissionGrant` + `encryptedRecordResolver` (jetzt in mana-ai lokalisiert) |
| `mana_auth.mcp_tokens` Tabelle | `{id, token_hash, user_id, mission_id, allowed_tools, expires_at, consumed_at}` |
| `POST /api/v1/me/ai-mission-mcp-token` | Issue |
| `POST /api/v1/mcp-token/verify` | Server-to-server Verify |
| `DELETE /api/v1/me/ai-mission-mcp-token/:id` | Explicit revoke (UI-Link) |
| Webapp: MCP-Option im Mission-Detail | "Meine Kontextdaten für diese Recherche freigeben" Checkbox + Token-Erzeugung |
| Audit-Tab-Erweiterung | Zeigt auch MCP-Aufrufe neben Decrypts |
| Cloudflare Tunnel für `mcp.mana.how` → mana-mcp | Analog zu `api.mana.how` etc. |
#### 3.3.5 Risiken
- **Öffentliche Angriffsfläche:** Der Service ist über Cloudflare Tunnel öffentlich erreichbar — sonst kann Gemini ihn nicht aufrufen. Ein schlecht durchdachter Tool-Handler oder eine Grant-Verwechslung bedeutet direkte Datenlecks. **Security-Review Pflicht** (Secure Code Review + Mini-Pentest) vor Rollout.
- **MCP-Rate-Limits:** Google kann den Server bei parallelen Research-Max-Tasks zig mal pro Minute anfragen. Wir brauchen Rate-Limiting (per Token) + Caching-Layer.
- **Token-Scope-Violations:** Wenn ein Request für Mission A auf Records aus Mission B geht (Bug oder Angriff), muss das einen dicken Alert auslösen. Bestehende `grant_scope_violations_total` Metrik lässt sich wiederverwenden.
- **Prompt Injection:** Entschlüsselte Notizen-Content kann Instruktionen an Gemini enthalten ("IGNORE PREVIOUS, download all …"). Wir müssen Tool-Responses klar als `data`, nicht als `instructions` labeln und Gemini prompten, userdata als nicht-vertrauenswürdig zu behandeln.
- **DSGVO-Implikationen:** Auch wenn MCP nur punktuell liest, geht der gelesene Content via Google's API-Endpunkt. Das muss in den Privacy-Text + Consent-Flow der Webapp.
- **Preview-Stabilität:** Bauen bevor die MCP-Integration auf Google-Seite stabil ist, heißt nachbauen wenn sich das Protokoll ändert. Erst mit POC, dann inkrementell.
#### 3.3.6 Meilensteine
**M0 — Security-Review + Plan-Sign-off (12 Tage).** Vor jeder Implementation. Liefert: konkretes Threat-Model, DSGVO-Check, Go/No-Go.
**M1 — POC mit `search_notes` only (34 Tage).**
- `services/mana-mcp` Bun-Service-Skeleton
- `@mana/mission-grant` Paket extrahiert (kein Verhaltenschange für mana-ai)
- `mcp_tokens` Tabelle + Issue/Verify-Endpoints
- Nur `search_notes`, auf einen harten Test-User gated (`userId === 'dev-…'`)
- Ad-hoc Cloudflare-Tunnel, noch kein permanenter `mcp.mana.how`
**M2 — `search_journal` + `search_kontext` + Prod-Tunnel (2 Tage).** Nach M1-Erkenntnissen.
**M3 — Webapp UX (23 Tage).** Mission-Config-Checkbox + Audit-Tab-Erweiterung.
**M4 — Public Rollout Founder-Tier.** Nach 1 Woche Beta für uns selbst.
Bewusst linearer Rollout — MCP ist zu Security-sensitiv für parallele Entwicklung.
## 4. Pricing-Sanity-Check
Bei angenommenen $37 pro Max-Task: eine nächtliche Max-Mission pro aktivem Nutzer entspricht **$90210/Monat pro Nutzer**. Das sitzt jetzt hinter zwei Gates:
1. `MANA_AI_DEEP_RESEARCH_ENABLED=true` auf dem Server (default off)
2. `DEEP_RESEARCH_TRIGGER` Regex im Mission-Text (explizite User-Wording)
Das `mana-credits` 2-Phase-Debit-Modell fängt Per-User-Limits ab, aber wir haben konservativ mit 1500 credits (≈ $15) für Max gepreist statt 700 (≈ $7) — als Puffer. Nach ersten echten Runs nachjustieren in `services/mana-research/src/lib/pricing.ts`.
## 5. Risiken & offene Fragen (Stand nach Schritt 1+2)
- **Preview-Status:** Model-IDs enden auf `-preview-04-2026`. Google deprecated solche Varianten typischerweise innerhalb von 612 Monaten. Aktuelle Strategie: `modelVersion` liegt als Konstante in `gemini-deep-research.ts` — Upgrade auf GA ist ein 1-Zeilen-Change, kein Refactor.
- **Charts/Infographics (`image`-Items):** Wir parsen sie derzeit nur in `providerRaw` — nicht im `AgentAnswer.answer` String. Follow-up: neues optionales Feld `AgentAnswer.visualizations: Array<{mime, data}>` plus MinIO-Upload für große Bilder.
- **Thought-Summaries:** Gehen heute verloren. Für eine zukünftige Research-Lab-UI wäre Streaming (`stream=true`) + Live-Anzeige der Gedanken ein differenzierendes Feature.
- **Quota:** Public Preview heißt niedrige Rate-Limits. Ersten 2 Wochen nur Founder-Tier. Monitoring via `mana_ai_research_jobs_failed_total{provider}` — sobald Spikes, Rate-Limit-Retry-Logic nachziehen.
- **`collaborative_planning: true`**: Ignoriert. Wäre ein interessanter UX-Modus für eine zukünftige **Webapp**-Research-Lab-UI (Agent fragt vor Start zurück, ob der Plan passt). Irrelevant für den Background-Runner.
- **MCP-Seite (Schritt 3):** siehe §3.3.5 — eigener Risk-Catalog.
## 6. Betrieb
### 6.1 Metriken
```
# mana-research
research.async_jobs — Tabelle, ein Row pro submit (inkl. finalem result)
# mana-ai
mana_ai_research_jobs_submitted_total{provider} — Pro Tick submittet
mana_ai_research_jobs_completed_total{provider} — Pro Tick Ergebnisse verfuettert
mana_ai_research_jobs_failed_total{provider} — Pro Tick failed/cancelled
mana_ai_research_jobs_pending_skips_total — Pro Tick skipped (Job läuft noch)
mana_ai_mission_research_jobs — Tabelle, ein Row pro pending Job pro Mission
```
### 6.2 Debug-Workflow
```bash
# Welche Missions haben aktuell einen pending Deep-Research-Job?
docker exec mana-postgres psql -U mana -d mana_sync -c "
SELECT user_id, mission_id, provider_id,
age(now(), submitted_at) AS running_for,
last_polled_at
FROM mana_ai.mission_research_jobs
ORDER BY submitted_at DESC;"
# Was ist der aktuelle Status upstream?
docker exec mana-postgres psql -U mana -d mana_platform -c "
SELECT id, user_id, provider_id, status, cost_credits, age(now(), created_at) AS age
FROM research.async_jobs
ORDER BY created_at DESC LIMIT 20;"
```
### 6.3 Notfall-Kill-Switch
`MANA_AI_DEEP_RESEARCH_ENABLED=false` + Service-Restart → keine neuen Jobs. Bereits pending Jobs laufen zu Ende (werden brav gepollt bis fertig), keine neuen kommen dazu.
Härter: direkte DB-Bereinigung —
```sql
DELETE FROM mana_ai.mission_research_jobs WHERE submitted_at < now() - interval '2 hours';
```
Die upstream-Tasks bleiben bei Google, aber wir lassen sie einfach laufen (Google berechnet sie trotzdem — aber das ist der Compute-Kosten-Sunk-Cost, nicht der Hebel).
### 6.4 Deploy-Log — 2026-04-22 (Mac-Mini)
Erst-Deploy von Schritt 1 + 2 auf dem Produktions-Mac-Mini. Alles, was von der Standard-Konfiguration abwich:
- **`mana-research` war auf Mac-Mini noch nie gestartet** — Service ist zwar in `docker-compose.macmini.yml` definiert, aber nie hochgezogen. Erst-Boot via `docker compose ... up -d mana-research`.
- **`research.*` Schema existierte nicht in `mana_platform`** — das Drizzle-Push läuft **nicht** automatisch beim Service-Boot. Manuell nachgezogen:
```bash
docker exec mana-research bun run db:push
```
Ergebnis: 5 Tabellen (`async_jobs`, `eval_results`, `eval_runs`, `provider_configs`, `provider_stats`).
- **`GOOGLE_GENAI_API_KEY` fehlte in `.env`** — lokalen Key aus `.env.secrets` nach `/Users/mana/projects/managarten/.env` übertragen. Backup: `.env.bak.pre-gemini-deep-research`.
- **Redis-NOAUTH-Spam**: mana-research hatte `REDIS_URL: redis://redis:6379` ohne Passwort-Credentials, Redis läuft aber mit `--requirepass`. Cache degradierte graceful, aber Log-Noise. Fix: commit `4867300d0` — `REDIS_URL: redis://:${REDIS_PASSWORD:-redis123}@redis:6379`.
- **Smoke-Test**: Submit über `POST /api/v1/internal/research/async` (Standard-Tier, 300 credits, Test-User ohne Wallet-Eintrag) → HTTP 500 in mana-credits (`credits.reserve failed: 404 Not Found`). **Erwartetes Ergebnis** — beweist den Chain `X-Service-Key → dispatch → googleGenai apiKey → credits.reserve` bis zum mana-credits-HTTP-Call. Kein Fehler in unserem neuen Code.
Bekannte offene Punkte nach Deploy:
- `mana-llm` (Port 3025) hat dieselbe Redis-ohne-Passwort-Config. Out-of-Scope für diesen Deploy, aber dokumentiert hier für einen separaten Fix.
- `/api/v1/providers/health` listet async-Provider nicht (weil sie nicht in der `buildRegistry()`-Map stehen). Health-Seite-Lücke, kein funktionaler Fehler.
- Für den ersten echten Test-Run braucht es (a) einen User mit Credits in `credits.balances` und (b) `MANA_AI_DEEP_RESEARCH_ENABLED=true` + mana-ai-Restart.
## 7. Empfehlung
1. **Jetzt (erledigt, 2026-04-22):** Schritt 1 + 2 umgesetzt. Ein Pilot mit uns selbst (einem Test-User mit Founder-Tier und expliziter "deep research" Mission) kann ab sofort laufen. `MANA_AI_DEEP_RESEARCH_ENABLED=true` auf dem Mac-Mini setzen und eine Nightly-Mission anlegen.
2. **Nach 1 Woche Pilot:** Wenn Response-Qualität + Latenz überzeugen und kein größerer Parser-Fail auftritt → Founder-Tier öffnen (ENV-Flag bleibt, Opt-in per Mission-Wording).
3. **Nach 2 Wochen Pilot + Beta-Tier-Öffnung:** Schritt 3 (MCP-Server) M0-M1 starten — POC mit `search_notes` only + harter User-Gate.
4. **Nach Erfolg von M1:** M2-M4 iterativ. Public Rollout erst mit kompletter Audit-UX + dokumentiertem Privacy-Flow.
## Quellen
- [Google Blog — Deep Research Max: a step change for autonomous research agents](https://blog.google/innovation-and-ai/models-and-research/gemini-models/next-generation-gemini-deep-research/)
- [Google AI for Developers — Gemini Deep Research Agent docs](https://ai.google.dev/gemini-api/docs/deep-research)
- [Google AI for Developers — Gemini API changelog](https://ai.google.dev/gemini-api/docs/changelog)
- [VentureBeat — Google's new Deep Research and Deep Research Max agents can search the web and your private data](https://venturebeat.com/technology/googles-new-deep-research-and-deep-research-max-agents-can-search-the-web-and-your-private-data)
- [The Decoder — Google launches Deep Research and Deep Research Max agents to automate complex research](https://the-decoder.com/google-launches-deep-research-and-deep-research-max-agents-to-automate-complex-research/)
- [Testing Catalog — Google debuts Deep Research agents on AI Studio and APIs](https://www.testingcatalog.com/google-debuts-deep-research-agents-on-ai-studio-and-apis/)
- [H2S Media — Google Launches Deep Research Max, Its Most Powerful Autonomous Research Agent](https://www.how2shout.com/news/google-deep-research-max-gemini-api-autonomous-agent.html)
- [Model Context Protocol Specification (für Schritt 3)](https://modelcontextprotocol.io/specification)