Appearance
Getting Started
What is Lota SDK?
Lota SDK is an AI runtime framework for building agent-powered applications. It provides persistent workstreams (conversation threads with full history), a durable memory system backed by vector and full-text search, multi-agent orchestration with team consultation, and structured execution plans for complex task management. The SDK handles the infrastructure plumbing -- database schemas, background workers, context compaction, memory extraction -- so you can focus on defining agents and building product features on top.
Prerequisites
| Requirement | Minimum Version | Purpose |
|---|---|---|
| Bun | 1.0+ | Package manager and runtime |
| Docker | 20.10+ | Run SurrealDB, Redis, and Bifrost locally |
| Docker Compose | v2+ | Orchestrate local infrastructure |
TIP
Lota SDK uses Bun as its package manager and test runner. All commands in this guide use bun.
Installation
The SDK ships as three packages. Install them based on what you need:
bash
# Core runtime -- agents, workstreams, memory, workers, DB, Redis
bun add @lota-sdk/core
# Shared schemas -- message types, constants, tool contracts
bun add @lota-sdk/shared
# UI helpers -- headless chat, tool views, streaming utilities (for client apps)
bun add @lota-sdk/ui@lota-sdk/core is the main package. It contains the runtime factory, all services, database and Redis wiring, background workers, and built-in tools. This is what your server uses.
@lota-sdk/shared contains TypeScript schemas, constants, and message contracts shared between server and client code. It has no runtime dependencies.
@lota-sdk/ui provides headless chat helpers, tool-view rendering utilities, and streaming support for building client applications. It depends on @lota-sdk/shared but not on @lota-sdk/core.
Start Infrastructure
The SDK requires three infrastructure services: SurrealDB (document + graph database with vector search), Redis (queues, locks, pub/sub), and Bifrost (AI gateway for routing LLM requests).
Start them all with Docker Compose:
bash
docker compose -f infrastructure/docker-compose.yml up -dThis starts:
| Service | Port | Description |
|---|---|---|
| SurrealDB | 8003 | Document/graph database with HNSW vector indexes and BM25 full-text search. Stores workstreams, messages, memories, plans, and all SDK state. |
| Redis | 6382 | Powers BullMQ job queues (memory extraction, context compaction, etc.) and distributed lease locks. |
| Bifrost | 8081 | AI gateway that routes LLM requests to configured providers (OpenAI, Anthropic, etc.) with centralized key management. |
WARNING
The Bifrost gateway requires provider API keys configured in your .env file and infrastructure/bifrost.config.json. See the Bifrost guide for setup details.
Create Your First Runtime
The runtime is the central object that wires everything together. Create one with createLotaRuntime():
typescript
import { createLotaRuntime } from '@lota-sdk/core'
const runtime = await createLotaRuntime({
// SurrealDB connection. The SDK always uses the database name "lotasdk"
// internally -- you only provide the server URL, namespace, and auth.
database: {
url: 'ws://localhost:8003/rpc',
namespace: 'lota',
username: 'root',
password: 'root',
},
// Redis connection for BullMQ queues and distributed locks.
redis: {
url: 'redis://localhost:6382/0',
},
// Bifrost AI gateway for routing all LLM and embedding requests.
aiGateway: {
url: 'http://localhost:8081/v1',
key: 'sk-bf-your-virtual-key',
},
// S3-compatible storage for file attachments and generated documents.
s3: {
endpoint: 'http://localhost:3910',
bucket: 'lota-attachments',
accessKeyId: 'your-access-key',
secretAccessKey: 'your-secret-key',
},
// Firecrawl for web scraping capabilities.
firecrawl: {
apiKey: 'fc-your-key',
},
// Agent roster -- which agents exist in your application.
agents: {
roster: ['assistant'],
displayNames: { assistant: 'Assistant' },
teamConsultParticipants: [],
},
})
// Connect to SurrealDB and Redis, apply database schemas.
await runtime.connect()INFO
runtime.connect() applies all built-in .surql schema files to the lotasdk database, establishes the Redis connection, and prepares the runtime for use. Schema files use IF NOT EXISTS semantics, so calling connect() is safe on an already-initialized database.
Register Users and Organizations
The SDK maintains its own identity records for users and organizations inside the lotasdk database. These are lightweight references -- your host application manages the full user model in its own database.
The key principle is shared IDs: use the same record ID values in both your host database and the SDK database so they can cross-reference each other.
typescript
// Upsert a user into the SDK's identity store
await runtime.lota.users.upsert({
id: 'user:alice',
name: 'Alice',
email: 'alice@example.com',
})
// Upsert an organization
await runtime.lota.organizations.upsert({
id: 'organization:acme',
name: 'Acme Corp',
})
// Link the user to the organization with a role
await runtime.lota.memberships.add({
userId: 'user:alice',
organizationId: 'organization:acme',
role: 'owner',
})TIP
Call these upserts during your application's login or onboarding flow. They are idempotent -- calling them multiple times with the same ID is safe.
Create Your First Workstream
With a user and organization registered, you can create a workstream and send a message:
typescript
const { workstreamService, createWorkstreamTurnStream } = runtime.services
// Create a group workstream
const workstream = await workstreamService.createWorkstream(
'user:alice',
'organization:acme',
{
mode: 'group',
title: 'My First Conversation',
},
)
// Send a message and get a streaming response
const stream = await createWorkstreamTurnStream({
workstreamId: workstream.id,
userId: 'user:alice',
organizationId: 'organization:acme',
message: { content: 'Hello! What can you help me with?' },
})The stream follows the AI SDK streaming protocol and emits text, reasoning, tool calls, and data parts in real time.
Start Background Workers
The SDK uses BullMQ workers for asynchronous processing. These run alongside your application and handle memory extraction, context compaction, and other background tasks.
typescript
// Start the workers you need
runtime.workers.startContextCompactionWorker()
runtime.workers.startPostChatMemoryWorker()
runtime.workers.startRegularChatMemoryDigestWorker()
runtime.workers.startMemoryConsolidationWorker()
runtime.workers.startSkillExtractionWorker()
runtime.workers.startRecentActivityTitleRefinementWorker()
// Schedule the recurring memory consolidation job (runs every 24 hours)
runtime.workers.scheduleRecurringConsolidation()| Worker | Purpose |
|---|---|
startContextCompactionWorker | Compresses long conversation histories to stay within token budgets |
startPostChatMemoryWorker | Extracts facts from onboarding conversations into the memory system |
startRegularChatMemoryDigestWorker | Periodic digest-based memory extraction for post-onboarding turns |
startMemoryConsolidationWorker | Archives stale memories, resolves contradictions, updates importance scores |
startSkillExtractionWorker | Identifies reusable procedures from conversations |
startRecentActivityTitleRefinementWorker | Refines sidebar activity titles from conversation content |
WARNING
Without workers running, memory extraction and context compaction will not happen. Your workstreams will still function, but agent context will grow unbounded and no long-term memories will be created.
What's Next
Now that you have a running runtime, explore the key concepts:
- Architecture -- understand how all the pieces fit together
- Configuration -- full reference for every config field
- Workstreams -- persistent conversation threads with state tracking
- Memory -- fact extraction, vector search, and memory consolidation
- Agents -- defining agent rosters, rules, and skills
- Tools -- built-in and custom tool definitions
- Turn Lifecycle -- trace a message through the full pipeline
- Execution Plans -- structured task management
- Bifrost -- AI gateway configuration
- Queues & Workers -- background processing