Overview
How Voltro treats AI — agents, tools, streaming, RAG — all primitives over the same WebSocket as the rest of the framework.
AI in Voltro isn't a library you bolt on. It's a primitive: agents are files, tools are files, embeddings are columns, streaming is the same WebSocket that carries queries + mutations.
The implementation is the Vercel AI SDK wrapped behind the @voltro/ai surface so the provider choice (Anthropic, OpenAI, the Vercel AI Gateway, mock-for-tests) is one env var — or a per-agent / per-call override carrying its own key.
The model
┌───────────────────────────────────────┐
│ Vercel AI SDK │
│ anthropic / openai / gateway / mock │
└───────────────────┬───────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────┐
│ @voltro/ai │
│ generateText(...) / generateObject(...) │
│ streamText(...) │
│ embed(...) / embedMany(...) │
└────────────────┬────────────────────────────────────┬────────────────┘
│ │
▼ ▼
┌────────────────────────────────┐ ┌─────────────────────────────────┐
│ *.agent.tsx (descriptor) │ │ *.tool.tsx │
│ defineAgent({ name, input }) │ │ defineTool({ name, input, │
│ *.agent.server.tsx (executor) │ │ output }) │
│ defineAgentExecutor(desc, { │ │ typed + wired on the executor │
│ system, tools, model }) │ │ │
└────────────────────────────────┘ └─────────────────────────────────┘What's in this section
- Providers — Anthropic, OpenAI, the Vercel AI Gateway, mock; per-config keys (BYOK), switching at runtime, model-wrapping middleware
- Agents —
*.agent.tsxshape, system prompts, tool wiring - Tools —
*.tool.tsxshape, validation, side effects - Streaming — tokens-over-WebSocket, client hooks, backpressure
- RAG — pgvector, embedding mixin, hybrid search
- Cost tracking — the token
usagereturned on every call
Why one surface
The Vercel AI SDK is excellent. It also rev'd its public API three times in 2024. Wrapping it gives us:
- One break when the SDK changes shape — we update
@voltro/ai, your code keeps working. - One mock implementation for tests —
AI_PROVIDER=mockmakes every call deterministic. - Provider portability — switch the provider with one env var, no call-site changes.
Conceptual differences vs. raw SDK
| Vercel AI SDK | @voltro/ai |
|---|---|
generateText(...) |
generateText({ prompt, system }) returns an Effect |
streamText(...) |
streamText({ prompt, system }) returns an Effect Stream |
Embeddings via embedMany([texts]) |
embed(text) / embedMany(texts) |
| Tool definitions are loose objects | defineTool({ name, input, output, … }) with Schema |
| Provider is hardcoded in code | AI_PROVIDER env var |
When NOT to use Voltro's AI surface
- You need bleeding-edge SDK features before they land in
@voltro/ai. Drop down to the raw SDK viaimport { anthropic } from '@ai-sdk/anthropic'. - You're calling AI from outside an executor. Workers, CLI scripts, etc. can still use
@voltro/aidirectly when they provide the right env/config.
For 95% of app code inside actions, streams, workflows, and agent helpers, use @voltro/ai instead of importing provider SDKs directly. The portability and test mock surface stay in one place.