Zum Inhalt springen
EN DE

Challenge 9.4: Research Workflow

Wie baust Du ein End-to-End AI-System das selbststaendig recherchiert, zusammenfasst und einen qualitaetsgesicherten Bericht erstellt — und dabei Guardrails, Model Routing und alle bisher gelernten Konzepte nutzt?

Overview: Topic als Input, Agent Loop, Break Conditions, Workflow, Context Engineering, Guardrails, Model Router als Prozesse in Gruppe, Report als Output

Drei Phasen: Research (Agent Loop mit Tools und Break Conditions), Processing (Workflow mit Context Engineering) und Quality (Guardrails und Model Router). Konzepte aus 8 verschiedenen Levels kommen zusammen.

Ohne Orchestrierung: Einzelne Bausteine die nicht zusammenspielen. Du hast Guardrails, aber sie sind nicht in die Pipeline integriert. Du hast einen Model Router, aber er wird nicht genutzt. Du hast Workflows, aber ohne Qualitaetssicherung. Das Ergebnis: ein fragiles System das in Production versagt.

Mit Orchestrierung: Eine durchgaengige Pipeline in der jede Phase auf die vorherige aufbaut. Research sammelt Daten mit Safeguards. Processing strukturiert die Ergebnisse mit Context Engineering. Quality sichert Guardrails und optimiert Kosten mit Model Routing. Das Ergebnis: ein Production-Ready System.

Diese Pipeline verbindet Konzepte aus dem gesamten Lernpfad. Hier ist die Übersicht, welches Level wo zum Einsatz kommt:

PhaseKonzeptLevelFunktion
ResearchTool Calling3.1search-Tool für Datensammlung
ResearchCustom Loop8.3Agent entscheidet selbst wann genug recherchiert ist
ResearchBreak Conditions8.4Max Iterations, Timeout, Cost Guard
ProcessingWorkflow8.1Sequentielle Steps: Zusammenfassen, Strukturieren
ProcessingContext Engineering5.xXML-strukturierte Prompts für praezise Outputs
ProcessingStructured Output1.5Zod Schema für typisierte Metadaten
QualityGuardrails9.1Input/Output-Validierung
QualityModel Router9.2Optimales Modell pro Phase
QualityUsage Tracking2.2Token-Kosten über die gesamte Pipeline

Die Research-Phase ist ein Custom Agent Loop mit Tools — das Muster aus Level 8.3 und 8.4:

import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { google } from '@ai-sdk/google';
import { z } from 'zod';
// search-Tool — simuliert Websuche (in Production: echte API)
const searchTool = tool({
description: 'Suche nach Informationen zu einem Thema',
parameters: z.object({
query: z.string().describe('Der Suchbegriff'),
}),
execute: async ({ query }) => {
console.log(` Suche: "${query}"`);
// In Production: Web Search API, Datenbank, etc.
return `Ergebnisse für "${query}": [Hier würden echte Suchergebnisse stehen]`;
},
});
async function researchPhase(topic: string) {
const LIMITS = { maxIterations: 5, timeoutMs: 30_000, maxTokens: 5_000 };
let totalTokens = 0;
let iterations = 0;
let breakReason = 'complete';
let researchResult = 'Keine Ergebnisse gefunden.';
const messages: any[] = [ // ← any[] weil AI SDK Messages verschiedene Content-Typen haben
{
role: 'user',
content: `Recherchiere gruendlich zum Thema: ${topic}.
Nutze das search-Tool um Informationen zu sammeln.
Wenn Du genug Informationen hast, fasse die Ergebnisse zusammen.`,
},
];
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), LIMITS.timeoutMs);
try {
while (true) {
// Break Condition: Max Iterations
if (iterations >= LIMITS.maxIterations) {
breakReason = 'max-iterations';
break;
}
// Break Condition: Cost Guard
if (totalTokens >= LIMITS.maxTokens) {
breakReason = 'cost-limit';
break;
}
iterations++;
const result = await generateText({
model: google('gemini-2.5-flash'), // ← Guenstiges Modell für Research
tools: { search: searchTool },
messages,
abortSignal: controller.signal,
});
totalTokens += result.usage.totalTokens;
messages.push(...result.response.messages);
// Break Condition: LLM ist fertig (kein Tool Call mehr)
if (result.finishReason === 'stop') {
// result.text der letzten Iteration enthaelt den finalen Text —
// sicherer als lastAssistant.content, das bei Tool-Calls ein Array ist
researchResult = result.text || 'Keine Ergebnisse gefunden.';
break;
}
}
} catch (error) {
if (error.name === 'AbortError') {
breakReason = 'timeout';
} else {
throw error;
}
} finally {
clearTimeout(timeout);
}
console.log(`Research: ${iterations} Iterationen, ${totalTokens} Tokens, Grund: ${breakReason}`);
return { result: researchResult, iterations, totalTokens, breakReason };
}

Drei Break Conditions schuetzen den Loop: Max Iterations (5), Timeout (30s), Cost Guard (5.000 Tokens). Das search-Tool wird vom LLM autonom genutzt — es entscheidet, welche Suchbegriffe es verwendet. Wenn das LLM finishReason: 'stop' zurueckgibt, hat es genug recherchiert.

Die Processing-Phase nutzt den Workflow-Pattern aus Level 8.1 mit Context Engineering aus Level 5:

import { generateText, Output } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
const ReportSchema = z.object({
title: z.string(),
summary: z.string(),
keyFindings: z.array(z.string()).min(3).max(7),
conclusion: z.string(),
});
async function processingPhase(researchResult: string, topic: string) {
// Step 1: Zusammenfassen (Context Engineering — XML-strukturierter Prompt)
const summary = await generateText({
model: anthropic('claude-sonnet-4-5-20250514'),
system: `<role>Du bist ein Research-Analyst.</role>
<task>Fasse die Recherche-Ergebnisse in 5-7 Kernaussagen zusammen.</task>
<rules>
- Jede Aussage in maximal 2 Saetzen
- Nur Fakten, keine Spekulationen
- Wenn Informationen fehlen, sage es explizit
</rules>`,
prompt: `<topic>${topic}</topic>\n<research>\n${researchResult}\n</research>`,
});
console.log(`Zusammenfassung: ${summary.usage.totalTokens} Tokens`);
// Step 2: Strukturieren (Structured Output — Zod Schema)
const structured = await generateText({
model: anthropic('claude-sonnet-4-5-20250514'),
system: `Erstelle einen strukturierten Report aus der folgenden Zusammenfassung.`,
prompt: summary.text,
output: Output.object({ schema: ReportSchema }),
});
console.log(`Strukturierung: ${structured.usage.totalTokens} Tokens`);
return {
report: structured.output,
totalTokens: summary.usage.totalTokens + structured.usage.totalTokens,
};
}

Zwei sequentielle Steps: Erst zusammenfassen mit XML-strukturiertem Prompt (Context Engineering aus Level 5), dann in ein typisiertes Schema umwandeln (Structured Output aus Level 1.5). Jeder Step hat seinen eigenen System Prompt mit klarer Rolle.

Die Quality-Phase wendet Guardrails aus Challenge 9.1 und Model Routing aus Challenge 9.2 an:

import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
type Guardrail = (text: string) => { ok: boolean; reason?: string };
// Output-Guardrails
const notEmpty: Guardrail = (text) =>
text.length > 0 ? { ok: true } : { ok: false, reason: 'Output is empty' };
const maxLength: Guardrail = (text) =>
text.length <= 15_000 ? { ok: true } : { ok: false, reason: `Too long: ${text.length}` };
const noHallucination: Guardrail = (text) => {
const markers = ['ich bin nicht sicher', 'ich weiss nicht', 'keine informationen'];
const hasUncertainty = markers.some(m => text.toLowerCase().includes(m));
if (hasUncertainty) {
console.warn('Warnung: Output enthaelt Unsicherheits-Marker');
}
return { ok: true }; // Warnen, nicht blocken
};
function runGuardrails(text: string, guardrails: Guardrail[]): void {
for (const guard of guardrails) {
const result = guard(text);
if (!result.ok) throw new Error(`Quality check failed: ${result.reason}`);
}
}
// Vollstaendige Pipeline
async function researchPipeline(topic: string) {
console.log(`\n=== Research Pipeline: "${topic}" ===\n`);
const pipelineStart = Date.now();
// Phase 1: Research
console.log('[Phase 1: Research]');
const research = await researchPhase(topic);
// Phase 2: Processing
console.log('\n[Phase 2: Processing]');
const processing = await processingPhase(research.result, topic);
// Phase 3: Quality
console.log('\n[Phase 3: Quality]');
const report = processing.report;
const reportText = `${report.title}\n\n${report.summary}\n\n${report.keyFindings.join('\n')}\n\n${report.conclusion}`;
runGuardrails(reportText, [notEmpty, maxLength, noHallucination]);
console.log('Alle Quality-Checks bestanden.');
// Statistiken
const totalTokens = research.totalTokens + processing.totalTokens;
const durationMs = Date.now() - pipelineStart;
console.log(`\n=== Pipeline abgeschlossen ===`);
console.log(`Dauer: ${durationMs}ms`);
console.log(`Tokens gesamt: ${totalTokens}`);
console.log(`Research-Iterationen: ${research.iterations}`);
console.log(`Abbruchgrund: ${research.breakReason}`);
return { report, totalTokens, durationMs, breakReason: research.breakReason };
}
// Ausfuehren
const result = await researchPipeline('Edge Computing Trends 2026');
console.log('\n--- Report ---');
console.log(`Titel: ${result.report.title}`);
console.log(`Zusammenfassung: ${result.report.summary}`);
console.log(`Kernaussagen:`);
for (const finding of result.report.keyFindings) {
console.log(` - ${finding}`);
}
console.log(`Fazit: ${result.report.conclusion}`);

Die Quality-Phase ist die letzte Verteidigungslinie. Guardrails prüfen den finalen Output auf Laenge, Inhalt und Qualität. Die gesamte Pipeline trackt Tokens und Dauer — wichtig für Production Monitoring.

Aufgabe: Baue eine Mini Research Pipeline: Suche, Zusammenfassung, Formatierung mit Guardrails.

Erstelle research-pipeline.ts und fuehre aus mit npx tsx research-pipeline.ts.

import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
const model = anthropic('claude-sonnet-4-5-20250514');
// TODO 1: Definiere ein search-Tool (simuliert, gibt festen Text zurück)
// TODO 2: Baue Phase 1 — Research
// - generateText mit search-Tool
// - Maximal 3 Iterationen
// TODO 3: Baue Phase 2 — Summarize
// - generateText das die Recherche in 3 Kernaussagen zusammenfasst
// TODO 4: Baue Phase 3 — Format + Guardrails
// - Formatiere als kurzen Report
// - Pruefe: nicht leer, max 5.000 Zeichen
// TODO 5: Logge Token-Verbrauch pro Phase und gesamt

Checkliste:

  • search-Tool definiert und genutzt
  • Research-Phase mit Iterations-Limit
  • Zusammenfassung nutzt Research-Output als Input
  • Output-Guardrails prüfen den finalen Report
  • Token-Verbrauch wird pro Phase und gesamt geloggt
Lösung anzeigen
import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
const model = anthropic('claude-sonnet-4-5-20250514');
// search-Tool (simuliert)
const searchTool = tool({
description: 'Suche nach Informationen',
parameters: z.object({ query: z.string() }),
execute: async ({ query }) => {
console.log(` Suche: "${query}"`);
return `Suchergebnisse für "${query}": AI wird in der Medizin für Diagnostik, Medikamentenentwicklung und personalisierte Therapie eingesetzt. Aktuelle Studien zeigen 30% schnellere Diagnosen durch AI-Unterstuetzung.`;
},
});
async function miniResearchPipeline(topic: string) {
let totalTokens = 0;
console.log(`\n=== Mini Research Pipeline: "${topic}" ===\n`);
// Phase 1: Research (max 3 Iterationen)
console.log('[Phase 1: Research]');
const messages: any[] = [ // ← any[] weil AI SDK Messages verschiedene Content-Typen haben
{ role: 'user', content: `Recherchiere zum Thema: ${topic}. Nutze das search-Tool.` },
];
let iterations = 0;
while (iterations < 3) {
iterations++;
const result = await generateText({
model,
tools: { search: searchTool },
messages,
});
totalTokens += result.usage.totalTokens;
messages.push(...result.response.messages);
if (result.finishReason === 'stop') break;
}
const researchText = messages
.filter(m => m.role === 'assistant' && typeof m.content === 'string')
.map(m => m.content)
.join('\n');
console.log(` ${iterations} Iterationen, ${totalTokens} Tokens\n`);
// Phase 2: Summarize
console.log('[Phase 2: Summarize]');
const summary = await generateText({
model,
system: 'Fasse die Informationen in exakt 3 Kernaussagen zusammen. Jede in einem Satz.',
prompt: researchText,
});
totalTokens += summary.usage.totalTokens;
console.log(` ${summary.usage.totalTokens} Tokens\n`);
// Phase 3: Format + Guardrails
console.log('[Phase 3: Format + Quality]');
const report = await generateText({
model,
system: 'Formatiere als kurzen Report mit Titel, Kernaussagen und Fazit.',
prompt: summary.text,
});
totalTokens += report.usage.totalTokens;
// Guardrails
if (report.text.length === 0) throw new Error('Report ist leer');
if (report.text.length > 5_000) throw new Error('Report zu lang');
console.log(' Quality-Checks bestanden.');
console.log(`\n=== Fertig. Gesamt: ${totalTokens} Tokens ===\n`);
console.log(report.text);
return { report: report.text, totalTokens };
}
await miniResearchPipeline('AI in der Medizin');

Erklärung: Drei Phasen — Research mit Tool-Loop (max 3 Iterationen), Summarize mit eigenem System Prompt, Format mit Guardrails. Token-Verbrauch wird über alle Phasen kumuliert. Die Pipeline laeuft von Anfang bis Ende durch, auch wenn der Research-Loop frueh abbricht.

Erwarteter Output (ungefaehr):
=== Mini Research Pipeline: "AI in der Medizin" ===
[Phase 1: Research]
Suche: "AI in der Medizin"
1 Iterationen, 342 Tokens
[Phase 2: Summarize]
187 Tokens
[Phase 3: Format + Quality]
Quality-Checks bestanden.
=== Fertig. Gesamt: 891 Tokens ===
AI in der Medizin — Report
...
Combine: Alle Level-Konzepte (1.5, 2.2, 3.1, 5.x, 6.x, 8.x, 9.x) fliessen in Research Pipeline, Pipeline zu Production-Ready AI System

Das ist das grosse Bild. Du hast jetzt alle Bausteine, um Production-Ready AI-Systeme zu bauen:

  • Level 1: Text generieren, streamen, strukturieren — die Grundlagen
  • Level 2: Token-Verbrauch verstehen und tracken — Kosten im Griff
  • Level 3: Tools und Agents — AI die handeln kann
  • Level 5: Context Engineering — praezise Prompts die konsistente Ergebnisse liefern
  • Level 6: Evals — Qualität messen statt raten
  • Level 8: Workflows — komplexe Aufgaben orchestrieren
  • Level 9: Guardrails, Routing, Comparing — Production-Patterns

In der Boss Fight baust Du ein System das alles vereint.

Part of AI Learning — free courses from prompt to production. Jan on LinkedIn