@atlas/ai#

Unified AI provider abstraction with chat, embeddings, streaming, RAG, and agent support. Zero external dependencies -- uses fetch for all API calls.

Exports#

Provider:

  • createProvider({ provider, key?, baseUrl? })AiProvider — provider is "openai" | "anthropic" | "ollama"
  • AiProvider exposes .chat(opts), .chatStream(opts), .embed(opts)

Chat:

  • createConversation(system?)Conversation
  • addMessage(conv, msg)Conversation (immutable)
  • send(provider, conv, content, opts?){ conversation, response }
  • userMessage, assistantMessage, systemMessage, toolMessage

Stream:

  • parseSSE(text) → events
  • collectStream(stream)ChatResponse
  • streamToSse(stream)ReadableStream (for HTTP responses)

Embeddings:

  • embed(provider, inputs)number[][] — inputs: string | string[]
  • cosineSimilarity(a, b)number
  • createVectorStore(){ add, search, size }

Structured / tools:

  • generateJson<T>(provider, prompt, opts?)T
  • tool(name, description, parameters)ToolDef

RAG:

  • index(rag, id, text)Promise<void>rag = { ai, store, topK? }
  • query(rag, question){ answer, sources }

Agents:

  • runAgent({ ai, system?, tools, maxIterations? }, prompt) → result

Server pipe:

  • withAi(provider)PipeFn — adds provider to conn.assigns.ai

Types#

  • ProviderConfig, Message, ChatOptions, ChatResponse, StreamChunk
  • EmbedOptions, EmbedResponse, ToolDef, ToolCall
  • Conversation, VectorStore, VectorEntry, RagOptions
  • AgentTool, AgentOptions

Provider setup#

import { createProvider } from "@atlas/ai"

const openai = createProvider({ provider: "openai", key: process.env.OPENAI_API_KEY! })
const anthropic = createProvider({ provider: "anthropic", key: process.env.ANTHROPIC_API_KEY! })
const ollama = createProvider({ provider: "ollama" }) // local, no key needed

Chat#

import { createConversation, send } from "@atlas/ai"

const conv = createConversation("You are a helpful assistant")
const { conversation, response } = await send(openai, conv, "Hello!")
// conversation tracks full message history immutably

Streaming#

import { collectStream, streamToSse } from "@atlas/ai"

const stream = openai.chatStream({ messages: [{ role: "user", content: "Hi" }] })
const full = await collectStream(stream) // collect into ChatResponse
const sse = streamToSse(stream) // convert to ReadableStream for HTTP responses
import { embed, cosineSimilarity, createVectorStore } from "@atlas/ai"

const vectors = await embed(openai, ["hello", "world"])
const score = cosineSimilarity(vectors[0]!, vectors[1]!)

const store = createVectorStore()
store.add("id1", vectors[0]!, { text: "hello" })
const results = store.search(vectors[1]!, 5) // top 5 nearest

Structured output#

import { generateJson, tool } from "@atlas/ai"

const user = await generateJson<{ name: string }>(openai, "Generate a user")
const searchTool = tool("search", "Search the web", { type: "object", properties: { query: { type: "string" } } })

RAG#

import { index, query, createVectorStore, createProvider } from "@atlas/ai"

const store = createVectorStore()
const rag = { ai: openai, store, topK: 3 }

await index(rag, "doc1", "Document text here...")
const result = await query(rag, "What does the document say?")
// result.answer, result.sources

Agent loop#

import { runAgent, tool } from "@atlas/ai"

const result = await runAgent({
  ai: openai,
  system: "You are a calculator assistant",
  tools: [{
    definition: tool("multiply", "Multiply two numbers", {
      type: "object",
      properties: { a: { type: "number" }, b: { type: "number" } },
    }),
    handler: async (args) => String((args.a as number) * (args.b as number)),
  }],
  maxIterations: 5,
}, "What is 6 times 7?")

Server pipe#

import { withAi } from "@atlas/ai"

// Add AI provider to conn.assigns.ai in a server pipeline
const aiPipe = withAi(openai)

Architecture#

  • provider/ -- Provider interface and adapters (openai, anthropic, ollama)
  • chat/ -- Immutable conversation management
  • stream/ -- SSE parsing, stream collection, SSE response generation
  • embeddings/ -- Vector embeddings and in-memory vector store
  • structured/ -- JSON mode and tool definitions
  • rag/ -- Retrieval-augmented generation pipeline
  • agents/ -- Tool-use agent loop with iteration limits
  • pipes/ -- Server middleware integration

Dependencies#

  • @atlas/server — only for the withAi pipe; the rest of the package stands alone.
  • External: none. All provider calls go through fetch.

Testing#

All tests use mock providers. No real API calls.

bun test packages/ai/
Canonical sourcepackages/ai/AGENTS.md
Type to search guides and package references.