Skip to content

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

RequirementMinimum VersionPurpose
Bun1.0+Package manager and runtime
Docker20.10+Run SurrealDB, Redis, and Bifrost locally
Docker Composev2+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 -d

This starts:

ServicePortDescription
SurrealDB8003Document/graph database with HNSW vector indexes and BM25 full-text search. Stores workstreams, messages, memories, plans, and all SDK state.
Redis6382Powers BullMQ job queues (memory extraction, context compaction, etc.) and distributed lease locks.
Bifrost8081AI 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()
WorkerPurpose
startContextCompactionWorkerCompresses long conversation histories to stay within token budgets
startPostChatMemoryWorkerExtracts facts from onboarding conversations into the memory system
startRegularChatMemoryDigestWorkerPeriodic digest-based memory extraction for post-onboarding turns
startMemoryConsolidationWorkerArchives stale memories, resolves contradictions, updates importance scores
startSkillExtractionWorkerIdentifies reusable procedures from conversations
startRecentActivityTitleRefinementWorkerRefines 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: