Appearance
Configuration
The Lota SDK is configured through the LotaRuntimeConfig object passed to createLotaRuntime(). This page covers every configuration field and the environment variables they map to.
LotaRuntimeConfig
ts
import { createLotaRuntime } from '@lota-sdk/core'
const runtime = await createLotaRuntime({
database: { url, namespace, username, password },
redis: { url },
aiGateway: { url, key, admin, pass, embeddingModel },
s3: { endpoint, bucket, region, accessKeyId, secretAccessKey, attachmentUrlExpiresIn },
firecrawl: { apiKey, apiBaseUrl },
logging: { level },
memory: { searchK },
workstreams: { bootstrap: { /* ... */ } },
agents: { /* ... */ },
turnHooks: { /* ... */ },
runtimeAdapters: { /* ... */ },
pluginRuntime: { /* ... */ },
toolProviders: { /* ... */ },
extraSchemaFiles: [],
extraWorkers: {},
})database
| Field | Type | Description |
|---|---|---|
url | string | SurrealDB WebSocket URL (e.g. ws://localhost:8003) |
namespace | string | SurrealDB namespace |
username | string | SurrealDB username |
password | string | SurrealDB password |
The SDK database name is fixed to lotasdk; consumers do not configure it.
redis
| Field | Type | Description |
|---|---|---|
url | string | Redis connection URL (e.g. redis://localhost:6382) |
aiGateway
| Field | Type | Description |
|---|---|---|
url | string | Bifrost AI gateway URL |
key | string | Bifrost virtual key (must start with sk-bf-) |
admin | string? | Gateway admin endpoint (optional) |
pass | string? | Gateway admin password (optional) |
embeddingModel | string? | Embedding model ID. Defaults to openai/text-embedding-3-small |
s3
| Field | Type | Description |
|---|---|---|
endpoint | string | S3-compatible endpoint URL |
bucket | string | S3 bucket name |
region | string? | S3 region. Defaults to garage |
accessKeyId | string | S3 access key |
secretAccessKey | string | S3 secret key |
attachmentUrlExpiresIn | number? | Presigned URL expiry in seconds. Defaults to 1800 |
firecrawl
| Field | Type | Description |
|---|---|---|
apiKey | string | Firecrawl API key (must start with fc-) |
apiBaseUrl | string? | Custom Firecrawl API base URL |
logging
| Field | Type | Description |
|---|---|---|
level | string? | One of trace, debug, info, warning, error, fatal. Defaults to info |
memory
| Field | Type | Description |
|---|---|---|
searchK | number? | Number of memory results returned per search. Defaults to 6 |
workstreams
Use workstreams.bootstrap to define host-specific provisioning rules instead of relying on SDK hardcoded agents or core types.
ts
workstreams: {
bootstrap: {
onboardingDirectAgents: ['chief'],
completedDirectAgents: ['chief', 'ceo', 'cto'],
coreTypesAfterOnboarding: ['daily-activities', 'gtm'],
ensureDefaultGroupOnCompleted: true,
onboardingWelcome: {
directAgentId: 'chief',
buildMessageText: ({ userName }) => `Hello ${userName ?? 'there'}`,
},
},
}| Field | Type | Description |
|---|---|---|
bootstrap.onboardingDirectAgents | readonly string[]? | Direct workstreams created before onboarding is complete |
bootstrap.completedDirectAgents | readonly string[]? | Direct workstreams created once onboarding is complete |
bootstrap.coreTypesAfterOnboarding | readonly string[]? | Group core workstream types provisioned after onboarding |
bootstrap.ensureDefaultGroupOnCompleted | boolean? | Whether to guarantee one standard non-core group workstream after onboarding |
bootstrap.onboardingWelcome | object? | Optional first assistant turn inserted into a configured direct workstream |
Agent Configuration
The agents field controls which agents are registered and how they are created.
ts
agents: {
roster: ['chief', 'ceo', 'cto', 'cpo', 'cmo', 'cfo', 'mentor'],
displayNames: {
chief: 'Chief',
ceo: 'CEO',
cto: 'CTO',
cpo: 'CPO',
cmo: 'CMO',
cfo: 'CFO',
mentor: 'Mentor',
},
shortDisplayNames: { chief: 'Chief', ceo: 'CEO' },
teamConsultParticipants: ['ceo', 'cto', 'cpo', 'cmo', 'cfo', 'mentor'],
getCoreWorkstreamProfile: (coreType) => ({ /* ... */ }),
createAgent: (agentId, options) => { /* ... */ },
buildAgentTools: (agentId, context) => { /* ... */ },
getAgentRuntimeConfig: (agentId) => { /* ... */ },
}| Field | Type | Description |
|---|---|---|
roster | readonly string[] | All agent IDs available in the runtime |
displayNames | Record<string, string> | Human-readable names for agents |
shortDisplayNames | Record<string, string>? | Abbreviated display names |
teamConsultParticipants | readonly string[] | Agent IDs that participate in consultTeam |
getCoreWorkstreamProfile | function | Returns profile config for core workstream types |
createAgent | function | Factory function for creating agent instances |
buildAgentTools | function | Builds the tool set for a given agent |
getAgentRuntimeConfig | function | Returns runtime configuration for an agent |
Turn Hooks
Turn hooks let consumers customize the workstream turn lifecycle. See the Hooks API for full signatures.
ts
turnHooks: {
buildContext: async (params) => { /* return context */ },
afterTurn: async (params) => { /* post-turn side effects */ },
resolveAgent: async (params) => { /* return agent config */ },
buildExtraInstructionSections: async (params) => ['<section>...</section>'],
}| Hook | Description |
|---|---|
buildContext | Called before agent execution to assemble the full context payload |
afterTurn | Called after the SDK completes the turn so the host can trigger non-critical side effects |
resolveAgent | Resolves agent configuration and routing for a given turn |
buildExtraInstructionSections | Returns additional XML instruction sections injected into the system prompt |
Plugin Runtime
Plugins are registered via pluginRuntime. Each plugin contributes services, tools, env keys, and schema files.
ts
pluginRuntime: {
github: githubPlugin,
linear: linearPlugin,
}Each plugin implements the LotaPlugin interface:
ts
interface LotaPlugin<TServices, TTools> {
services: TServices
tools?: TTools
contributions: {
envKeys: readonly string[]
schemaFiles: readonly (string | URL)[]
}
}If a plugin exposes a connectDatabase() service method, call await runtime.connectPluginDatabases() during host startup.
Tool Providers
Register extra runtime-owned tools that should be merged into the shared tool registry:
ts
toolProviders: {
myTool: createMyTool(),
}Runtime Adapters
Use runtimeAdapters when the generic SDK runtime needs to call back into host-owned product behavior without importing host code directly.
ts
runtimeAdapters: {
services: {
workspaceProvider,
},
workstream: {
buildIndexedRepositoriesContext,
buildTeamThinkAgentTools,
},
queues: {
enqueuePostChatOrgAction,
enqueueOnboardingRepoIndexFollowUp,
},
workers: {
connectPluginDatabases,
withWorkspaceMemoryLock,
},
}| Field | Description |
|---|---|
services.workspaceProvider | Host workspace lifecycle, projection, retrieval, and cursor access |
workstream.buildIndexedRepositoriesContext | Builds host-specific repository context for the turn runtime |
workstream.buildTeamThinkAgentTools | Adds host-specific tools for team-think style agent execution |
queues.enqueuePostChatOrgAction | Lets the SDK enqueue a host-owned post-turn org-action job |
queues.enqueueOnboardingRepoIndexFollowUp | Lets the SDK enqueue a host-owned onboarding repo follow-up job |
workers.connectPluginDatabases | Host hook for plugin DB initialization |
workers.withWorkspaceMemoryLock | Host-provided distributed lock wrapper for workspace memory work |
Environment Variables
The SDK validates its environment internally. When using createLotaRuntime(), all env values are passed through the config object. The underlying Zod schemas provide the validation:
| Variable | Default | Notes |
|---|---|---|
AI_GATEWAY_URL | Required | Bifrost gateway URL |
AI_GATEWAY_KEY | Required | Must start with sk-bf- |
AI_GATEWAY_ADMIN | - | Optional admin endpoint |
AI_GATEWAY_PASS | - | Optional admin password |
AI_EMBEDDING_MODEL | openai/text-embedding-3-small | Embedding model routed through Bifrost |
REDIS_URL | Required | Redis connection string |
LOG_LEVEL | info | trace / debug / info / warning / error / fatal |
S3_ENDPOINT | Required | S3-compatible endpoint |
S3_BUCKET | Required | Bucket name |
S3_REGION | garage | Region identifier |
S3_ACCESS_KEY_ID | Required | S3 access key |
S3_SECRET_ACCESS_KEY | Required | S3 secret key |
ATTACHMENT_URL_EXPIRES_IN | 1800 | Presigned URL expiry (seconds) |
FIRECRAWL_API_KEY | Required | Must start with fc- |
FIRECRAWL_API_BASE_URL | - | Optional custom base URL |
MEMORY_SEARCH_K | 6 | Results per memory search |
Extra Schema Files
Add consumer-owned SurrealDB schema files that are applied at startup alongside built-in schemas:
ts
extraSchemaFiles: [
'/path/to/my-custom-table.surql',
]Extra Workers
Register consumer-provided BullMQ workers alongside the built-in queues:
ts
extraWorkers: {
myCustomQueue: myWorkerFactory,
}These entries are merged onto runtime.workers.