viby

Client and configuration

createViby() creates the long-lived server-side SDK client. Configure infrastructure once, then derive a tenant/user-scoped client for each authenticated operation.

createViby(config)

import { createViby } from "@viby/sdk";
import { openai } from "@ai-sdk/openai";

const viby = createViby({
  framework: "farmjs",
  model: openai("your-model-id"),
  storage: {
    // Omit database to use DATABASE_URL.
    artifacts,
    connections,
    secrets,
  },
  skills: {
    design: ["farming-labs/design-engineer"],
  },
});

The function validates mutually exclusive configuration, opens the selected storage and adapter boundaries, and returns Viby<Framework>. It does not run database migrations or contact the model. Configuration failures throw ConfigurationError before work begins.

VibyConfig

FieldTypeBehavior
frameworkFrameworkIdRequired single target string. It is persisted with chats and versions and preserved in the generic return type.
modelAI SDK LanguageModelConvenient default generation path. Mutually exclusive with engine.
modelsrecord of LanguageModelOptional request-selectable aliases. default is reserved for the top-level model.
engineGenerationEngineProvider-neutral replacement for the default agent/model runtime. Mutually exclusive with model.
enginesrecord of GenerationEngineOptional request-selectable engine aliases. default is reserved.
storage.databaseDatabaseAdapter | PersistenceAdapterStructured durable records. Omit it to open PostgreSQL from DATABASE_URL.
storage.artifactsArtifactStoreBinary attachments, project entries, generated outputs, screenshots, and prepared deployment archives.
storage.connectionsIntegrationConnectionStorePublic provider connection metadata and authorization state. PostgreSQL is the default.
storage.secretsSecretStoreProvider credentials and secret project variables. The default requires VIBY_SECRET_KEY.
skillsSkillGroupsDefault categorized skill references included in generation configuration.
skillResolverSkillResolverAdapterResolves application-owned catalogs or opaque locators into immutable skill files.
toolsToolSourcesConfigStatic sources, durable source adapters, selection, and effect policy.
sandboxSandboxAdapterOptional source execution and preview infrastructure.
sandboxPolicySandboxCommandPolicyAuthorizes or rejects normalized commands before any provider sees them.
previewPreviewConfigFramework server command, port, environment, timeout, and readiness behavior.
browserBrowserAdapterOptional browser inspection and visual evaluation boundary.
environmentEnvironmentConfigEnables durable per-chat project variables and secret injection.
integrationsVibyIntegrationsRepository and deployment adapters grouped by capability.
deployment.preparationDeploymentPreparationConfigInstall/build/output contract for providers that require prebuilt files.
generation.execution"embedded" | "worker"Defaults to embedded; worker leaves new attempts queued.
generation.qualityGenerationQualityConfigOptional provider-neutral preparation and quality commands that must pass before generated source becomes an immutable version.
generation.workspace{ preview: "eager" }Opens the base version in one reusable sandbox while generation runs, emits the preview as soon as it is ready, and hands that workspace to final quality checks.
retention.deletedChatsMsnumber | nullDefault soft-delete retention. null keeps tombstones indefinitely; 0 allows immediate purge.
events.sinksOutboundEventSink[]Named outbound delivery targets. Delivery is explicit and durable.
telemetryVibyTelemetryProvider-neutral spans and metrics. Telemetry failures are fail-open.
costGenerationCostConfigHost-owned cost calculator stored in integer micro-units.

The deprecated top-level persistence, artifactStore, connectionStore, and secretStore aliases remain for compatibility. Do not configure an alias and its corresponding storage.* field at the same time.

Model or generation engine

Use model for the built-in bounded AI SDK agent. Use engine when the application supplies its own agent, orchestration runtime, or model protocol:

import { defineGenerationEngine } from "@viby/sdk/core";

const engine = defineGenerationEngine({
  id: "company-agent",
  provider: "internal",
  model: "frontend-v3",
  async generate(input, options) {
    return companyAgent.generate(input, options);
  },
});

const viby = createViby({ framework: "farmjs", engine });

Concrete provider and model identity are stored on each attempt. Model or engine objects and their credentials are never persisted.

Multiple models from one provider

Use modelsFrom() when one AI SDK provider instance should expose several models. default becomes the top-level model and the remaining keys become stable aliases accepted by generation requests:

import { createViby, modelsFrom } from "@viby/sdk";
import { createOpenAI } from "@ai-sdk/openai";

const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });

const viby = createViby({
  framework: "farmjs",
  ...modelsFrom(openai, {
    default: "gpt-5.6-sol",
    terra: "gpt-5.6-terra",
    luna: "gpt-5.6-luna",
    fast: "gpt-5.6-sol-fast",
  }),
});

The provider instance still owns authentication, requests, streaming, tools, and usage reporting. Viby receives ordinary AI SDK LanguageModel objects and stores only their provider/model identity on durable attempts. Pass model: "terra" when creating or retrying a generation to select an alias.

The same helper accepts another provider instance without changing Viby configuration:

import { anthropic } from "@ai-sdk/anthropic";

const claudeModels = modelsFrom(anthropic, {
  default: "claude-sonnet-4-6",
  opus: "claude-opus-4-6",
});

Spreading claudeModels into createViby() makes Sonnet the default and exposes opus as a request alias. Viby invokes the returned AI SDK model objects internally; it does not call the provider instance through a separate private integration.

Viby

MemberReturnsBehavior
frameworkFrameworkThe configured framework identifier.
integrationsIntegrationClientUnscoped callback and adapter-management surface. User operations should use ScopedViby.integrations.
toolSourcesToolSourceAuthorizationCallbacksPublic provider callback completion surface for durable tool registrations.
forUser(scope)ScopedVibyValidates non-empty identity and returns a tenant/user-bound client.
worker(options)GenerationWorkerCreates a durable worker restricted to this client's framework and model/engine identities.
close(options?)Promise<void>Aborts local runs and closes owned resources. preserveSandboxes keeps durable preview leases running.

ScopedViby

const user = viby.forUser({ tenantId, userId });
PropertyPurpose
scopeThe validated identity pair used by every child operation.
chatsCreate, import, search, restore, and purge projects.
generationsRehydrate a durable generation by ID.
sandboxesRead and reconnect durable sandbox leases.
previewsRead, reconnect, stop, list, and clean preview sessions.
toolSourcesManage durable tool-source registrations and connections.
integrationsUser-scoped repository and deployment providers.

Scoped clients are lightweight and do not own independent database connections. A resource outside the scope resolves to NotFoundError.

GenerationWorker

const worker = viby.worker({
  id: "generation-worker-eu-1",
  concurrency: 4,
  leaseMs: 30_000,
  heartbeatMs: 10_000,
  pollIntervalMs: 500,
});
MemberBehavior
idStable host-provided worker identity recorded on claimed attempts.
runningReports whether run() currently owns its processing loop.
runOnce({ signal? })Claims and processes at most one eligible attempt; returns whether work was claimed.
run({ signal? })Runs the polling loop until aborted or stopped, respecting configured concurrency.
stop()Stops accepting work and waits for the active worker loop to settle.

Workers claim with leases and heartbeat while running. Lease tokens fence writes; a stale worker cannot append output after another worker safely reclaims an expired attempt.

Shutdown behavior

Call viby.close() once per root client. It stops embedded runs, previews, sandboxes, tool sources, integrations, environment stores, and persistence resources that Viby owns. The host remains responsible for shutting down its HTTP server, scheduler, telemetry exporter, and application-owned adapter clients.

Request-scoped durable generation workers can preserve sandbox-backed previews while still closing their local stores and provider clients:

await viby.close({ preserveSandboxes: true });

Use this only after the worker has handed its sandbox to a durable preview. The default remains false, so normal application shutdown still stops every locally tracked preview and sandbox.