LLM-Features, die dein Framework
nicht neu erfinden.

Der Standardweg für "KI in meine App bringen" liegt irgendwo zwischen "das Vercel-SDK direkt verdrahten und beten" und "ein separates Agent-Framework mit eigener Datenbank einführen". Voltro geht einen dritten Weg: Agents, Tools, RAG, Streaming-Threads — allesamt First-Class-Primitive in derselben Runtime wie deine Mutations und deine reaktiven Queries. Das Vercel AI SDK übernimmt die Schwerarbeit; @voltro/ai gibt dir eine stabile Oberfläche, die mit deinen Tests funktioniert.

support.agent.tsx
TypeScript
// agents/support.agent.tsx — DESCRIPTOR (browser-safe wire contract)
import { defineAgent } from '@voltro/ai/agent'
import { Schema } from 'effect'

export const support = defineAgent({
  name:  'support',
  input: Schema.Struct({ prompt: Schema.String }),
})

// agents/support.agent.server.tsx — EXECUTOR (server-only behaviour)
import { defineAgentExecutor } from '@voltro/ai'
import { searchDocs } from '../tools/searchDocs.tool'

export default defineAgentExecutor(support, {
  system:   'You are a friendly support agent. Be concise.',
  tools:    { searchDocs },
  maxSteps: 8,
})

// The framework synthesises TWO procedures for free:
//   support.send     — kicks off a streaming turn
//   support.messages — reactive query, streams deltas

// On the client:
const { data: messages } = useSubscription(
  'app', ['support.messages', { threadId }], { threadId },
)
const send = useMutation('app', 'support.send')
// Live typewriter bubble is just a row with streaming: true.

Sechs Primitive für das AI-Feature, das du sowieso bauen wolltest.

defineAgent — das Chat-Primitiv

Eine einzige .agent.tsx-Datei deklariert einen LLM-Chat mit typisiertem Input, einem System-Prompt, optionalen Tools und einem Token-Budget. Das Framework synthetisiert automatisch eine streamende send-Action plus eine reaktive Query, die persistierte Message-Deltas in den Browser streamt.

defineTool — typisiertes Function-Calling

Eine *.tool.tsx-Datei deklariert einen Schema-typisierten Input und Output. Das Framework bindet sie als Model-Tool ein. Inputs werden validiert; das Ergebnis wird gegen das Output-Schema dekodiert, bevor das Modell es sieht.

pgvector-RAG out of the box

vector(1536) ist ein First-Class-Spaltentyp. Der vectorEmbedding()-Mixin fügt die Spalte, den HNSW-Index UND einen Re-Embed-Hook hinzu, der bei jedem Insert/Update das embed von @voltro/ai aufruft. nearestNeighbours('text', k) embeddet die Query inline.

Streaming als React-Zeile

runAssistant patcht eine persistierte Message-Zeile, während die Deltas eintreffen. Die reaktive Subscription streamt jeden Patch. Der Live-Schreibmaschineneffekt ist einfach eine Zeile mit streaming: true — kein manuelles WebSocket-Geflecht, kein SSE-Handler.

Durable Agent-Loops per Workflows

Für mehrstufiges Agent-Reasoning, das einen Crash überleben muss (der Model-Call, dann ein Tool-Call, dann das Warten auf eine menschliche Freigabe), wickle die Schleife in eine *.workflow.tsx. Jedes Schritt-Ergebnis wird journaled; die Wiederaufnahme spielt ab der Stelle weiter, an der sie abgebrochen ist.

Provider-Wechsel + Mock für Tests

@voltro/ai kapselt das Vercel AI SDK hinter einer stabilen Oberfläche. Tausche den Provider (Anthropic, OpenAI, lokales Ollama), ohne die Aufrufstellen anzufassen. mockAi(...) installiert einen deterministischen Provider für Tests — keine echten Model-Calls in der CI.

Der Agent-Loop IST die Runtime.

Ein Agent, der (a) Tokens in einen Browser streamen, (b) Tools aufrufen muss, die deine Datenbank berühren, (c) einen Deploy mitten im Loop überleben und (d) 1000 gleichzeitige Nutzer bedienen soll — das sind vier Probleme, die Voltros vorhandene Primitive bereits lösen. Reaktive Queries übernehmen das Streaming. Mutations + Actions übernehmen die Tool-Calls. Workflows übernehmen die Durability. Multi-Tenancy übernimmt die Isolation.

Wähle die richtige Form:

  • One-Shot-Prompt → Text. generateText(prompt). In jedem Handler.
  • Schema-beschränkter Output. generateObject(schema, prompt). In einer Mutation oder Action.
  • Live-Chat-Thread. defineAgent + useSubscription auf der synthetisierten messages-Query.
  • Langer Agent-Loop mit Freigaben. Wickle die Schleife in einen Workflow; nutze awaitSignal für die Freigabe.
  • RAG-Suche. vectorEmbedding()-Mixin an der Quell-Tabelle; nearestNeighbours auf der Query.

AI ist nur eine weitere Handler-Form.

Öffne das Framework. Schau es dir selbst an.

Jede Primitive auf dieser Seite ist heute im Framework. Klone den Starter, lass `voltro dev` laufen, in zwei Minuten ist es auf dem Bildschirm.