> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usecontextlayer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK

> Import paths, resource APIs, React Router integration, and build configuration for @usecontextlayer/sdk.

`@usecontextlayer/sdk` connects a slate's authored code to ContextLayer. It provides the app's document layout, request-scoped Tools and Databases capabilities, and the Vite and Worker integration used by the starter.

The CLI installs and configures the SDK when it creates a slate. For initial setup, use [Installation](https://docs.usecontextlayer.com/installation.md) and the [Quickstart](https://docs.usecontextlayer.com/quickstart.md). This page describes the SDK's imports, contracts, and integration points.

## Import paths

Use the entry point for the environment in which the import runs:

| Import | Purpose |
| - | - |
| `@usecontextlayer/sdk` | Tools and Databases contexts, typed database helper, and setup-response schemas. |
| `@usecontextlayer/sdk/react` | The app's document `Layout`. |
| `@usecontextlayer/sdk/vite` | The `contextlayer` Vite plugin. |
| `@usecontextlayer/sdk/worker` | `createSlateWorker` and its Worker type. |
| `@usecontextlayer/sdk/database` | `databaseDialect` for native Kysely CLI configuration. |
| `@usecontextlayer/sdk/html` | `htmlPage` for a standalone server-rendered HTML document. |
| `@usecontextlayer/sdk/local` | The local resource Worker integration used by the generated checkout. |

The app and each agent declare their required resources in `slate.json`; importing an SDK function does not make an undeclared resource available. See [Resources](https://docs.usecontextlayer.com/core-concepts/resources) for declarations, modes, and assignments.

## Tools

`toolsContext` supplies the Tools capability for a React Router request. Use it inside a loader or action, where ContextLayer can bind the call to the current slate and resource configuration.

### Call connected services

In a loader or action, obtain Tools with `context.get(toolsContext)` from `@usecontextlayer/sdk`. Call `tools.call(connectionSlug, toolName, arguments)` with a connection slug declared in `public/slate.json`. Calls resolve to `{ data, logId }`; validate the tool-specific `data` before using it.

| Argument | Meaning |
| - | - |
| `connectionSlug: string` | A connection in the app's declaration, such as `work-email`. |
| `toolName: string` | The provider's tool name, such as `GMAIL_FETCH_EMAILS`. |
| `arguments: Record<string, unknown>` | The input object defined by that provider tool. |

```ts theme={null}
import { toolsContext } from "@usecontextlayer/sdk"

// Inside a loader or action with a declared and assigned work-email connection:
const tools = context.get(toolsContext)
const { data, logId } = await tools.call("work-email", "GMAIL_FETCH_EMAILS", {
  max_results: 5,
})
```

The promise resolves to `{ data: unknown, logId: string }`. `data` contains the provider result, and `logId` identifies the execution. Composio owns the provider's argument and result schemas. Treat the result as external data and parse the fields your app uses. [Connect an account](https://docs.usecontextlayer.com/how-to/connect-an-account.md) provides a complete assignment workflow.

## Databases

`databasesContext` supplies the `Databases` capability for a React Router request. `database<DB>(databases, slug)` accepts that capability and a string slug and returns a `Kysely<DB>` instance for the declared database. The root SDK entry point also exports the `Tools` and `Databases` types.

Declare the slug in `public/slate.json`. An agent that should use the same logical database must declare it too, with the same mode. The app and agent share stored rows only when their resource selection chooses the same Owner. Each database keeps its configuration, migrations, and generated query types under `databases/<slug>`.

### Query through Kysely

This loader excerpt selects the starter's `notes` database and reads its `notes` table. The first name selects storage; the second names a table within that storage:

```tsx theme={null}
import { database, databasesContext } from "@usecontextlayer/sdk"
import type { DB } from "@/databases/notes/types"
import type { Route } from "./+types/home"

export async function loader({ context }: Route.LoaderArgs) {
  const db = database<DB>(context.get(databasesContext), "notes")
  return db.selectFrom("notes").selectAll().orderBy("id", "desc").execute()
}
```

The helper uses SQLite compilation and returns native Kysely query results. Mutations return affected-row counts and SQLite insert IDs; use `.returning()` to retrieve the rows written by an insert or update. Bigint parameters are converted to decimal strings before binding.

### Query with SQL

Use the request capability directly when you need SQL:

```ts theme={null}
const databases = context.get(databasesContext)
const { rows } = await databases.query(
  "notes",
  "select id, body from notes where id > ? order by id desc",
  [0],
)
```

`query(slug, sql, params?)` takes a database slug and SQL string. The optional parameter array accepts `string`, `number`, or `null` values. Pass values through that array rather than interpolating them into SQL.

The returned promise resolves to this result shape:

| Field | Type | Meaning |
| - | - | - |
| `rows` | `Record<string, string \| number \| null>[]` | Result rows keyed by column name. |
| `columns` | `string[]` | Column names in the result. |
| `rowsRead` | `number` | Reported rows read. |
| `rowsWritten` | `number` | Reported rows written. |
| `changes` | `number`, optional | Mutation change count, when present. |
| `lastInsertRowid` | `number`, optional | SQLite's last insert row ID, when present. |

Agents use `database_query` to reach their own declared databases with the same SQL contract. The result type is not a named export from the SDK root; use the return type of `query` when you need to derive it.

SQL transactions are not supported by the ContextLayer database interface. Kysely, direct SQL, and agent queries use the same storage when their slate, selected Owner, and slug match.

### Configure migrations and generated types

A database's native config selects only its declared logical slug. ContextLayer supplies the local connection during development or the scoped connection inside the hosted sandbox:

```ts theme={null}
import { databaseDialect } from "@usecontextlayer/sdk/database"
import { defineConfig } from "kysely-ctl"

export default defineConfig({
  dialect: databaseDialect("notes"),
  migrations: { migrationFolder: "./migrations" },
})
```

With `pnpm dev` running, use the native CLI to create a migration, edit its `up(db)` and optional `down(db)`, then apply it. Type generation is a separate command:

```sh theme={null}
pnpm exec kysely --config databases/notes/kysely.config.ts migrate make add_created_at
pnpm exec kysely --config databases/notes/kysely.config.ts migrate latest
pnpm db.codegen notes
```

Commit the authored migrations and generated `databases/notes/types.ts`; do not hand-maintain query types. Local startup also applies pending migrations before app queries, and local tools access only local storage. [Add a database](https://docs.usecontextlayer.com/how-to/add-a-database.md) covers the full authoring sequence, including when to restart the app.

Hosted builds apply the selected commit's migrations before deployment. New members' databases are provisioned and migrated in the background before their schedules are installed. Migration failure stops the deployment or provisioning that ran it, and earlier SQL statements may remain applied. See [Databases](https://docs.usecontextlayer.com/core-concepts/resources/databases.md) for the lifecycle and [the database architecture](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#slate-databases-and-authored-migrations) for the isolation boundary.

## Missing resource setup

Missing required setup produces a native HTTP 409 response that React Router can render through an error boundary. The generated root already handles these responses:

| Missing input | Payload | Exported schema |
| - | - | - |
| A declared connection's account assignment | `{ reason: "connection-required", slug }` | `connectionRequiredSchema` |
| A declared viewer-mode secret value | `{ reason: "secret-required", name }` | `secretRequiredSchema` |

In a custom error boundary, first use React Router's `isRouteErrorResponse(error)`, then parse `error.data` with the appropriate schema's `safeParse()` method. A missing secret affects preparation of the consumer's resources, so these responses can arise from hosted database queries as well as tool calls. See the starter root for the existing setup UI and [the resource model](https://docs.usecontextlayer.com/core-concepts/resources) for selection rules.

## App Layout

The generated `app/root.tsx` re-exports the SDK's document Layout:

```tsx theme={null}
export { Layout } from "@usecontextlayer/sdk/react"
```

Keep this re-export when editing the app's root component, error boundary, stylesheet, and font links. Layout supplies React Router's document elements and mounts the [chrome](https://docs.usecontextlayer.com/core-concepts/slate#the-chrome) on the hosted app. The chrome is disabled during Vite development. Configure hosted resources through the chrome and local assignments through the CLI.

## Vite and Worker configuration

Compose `contextlayer` with the app's React Router and Tailwind plugins:

```ts vite.config.ts theme={null}
import { contextlayer } from "@usecontextlayer/sdk/vite"
import { reactRouter } from "@react-router/dev/vite"
import tailwindcss from "@tailwindcss/vite"
import { defineConfig } from "vite"

export default defineConfig((env) => ({
  plugins: [contextlayer(env), tailwindcss(), reactRouter()],
  resolve: { tsconfigPaths: true },
}))
```

This integration supplies the Cloudflare plugin; do not add a second instance. Keep the generated `workers/local-resources/wrangler.jsonc` and `workers/local-resources/index.ts` for local development. Follow the [startup and restart prerequisites](#local-login-and-assignment) when changing resources.

Keep the generated `workers/app.ts` wiring to `createSlateWorker` from `@usecontextlayer/sdk/worker`. It supplies the virtual React Router server build, Vite mode and development flag, and authored MCP modules. `createSlateWorker` returns the exported `SlateWorker` type. The [runtime architecture](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#resource-configuration-and-execution--principles) owns capability wiring and trust boundaries.

The Worker factory takes these options:

| Option | Purpose |
| - | - |
| `build` | The server build accepted by React Router's `createRequestHandler`. |
| `mode` | The Vite mode string. |
| `development` | Whether the Worker is running in development. |
| `mcp`, optional | A record of authored MCP modules, each exporting a tool definition and handler. |

The Worker entry point also exports the `McpToolModule` type. Keep the starter's module discovery wiring when adding tools; [Expose MCP tools](https://docs.usecontextlayer.com/how-to/expose-mcp-tools.md) covers the authored files and deployment.

## Standalone HTML pages

Use `htmlPage` for a complete server-rendered document with a centered, responsive white card. It loads pinned Bootstrap 6 CSS through a CDN stylesheet link and uses Bootstrap classes for layout. Supply the card's contents with Hono's `html` helper and standard Bootstrap markup; no React, custom CSS or frontend build configuration is required.

| Input | Type | Purpose |
| - | - | - |
| `title` | `string` | The document title. |
| `children` | The return value of Hono's `html` helper. | Markup inside the page's card. |

Use it inside a Hono handler, where `c` is the request context:

```ts theme={null}
import { htmlPage } from "@usecontextlayer/sdk/html"
import { html } from "hono/html"

return c.html(htmlPage({
  title: "Connect your account",
  children: html`<h1 class="h4">Connect your account</h1>
    <form action="/authorize" method="get">
      <!-- Application-owned fields and authorization parameters -->
      <button class="btn-solid theme-inverse" type="submit">Continue</button>
    </form>`,
}))
```

The caller owns the content, form destination, validation and authorization flow. The helper supplies only the document and presentation shell.

## Local login and assignment

Declare app resources in `public/slate.json` and agent resources in `agents/<name>/slate.json`; see [Resources](https://docs.usecontextlayer.com/core-concepts/resources). Use the CLI's `accounts` and `connections` commands for account setup, with [Connect an account](https://docs.usecontextlayer.com/how-to/connect-an-account.md) as the walkthrough. Local assignments are saved in ignored `.contextlayer/connections.json`.

For local tool calls, assign your personal connected accounts even when the hosted declaration uses `owner` mode or the slate belongs to an organization. Keep `.contextlayer/` ignored in Git. Local database state lives in `.contextlayer/databases`; local secret values come from environment variables with their declared names.

When the app declares connections, Vite startup needs a matching CLI login and the generated Git origin to identify the slate. This also applies when running a local agent because that command starts Vite. Restart `pnpm dev` after changing declarations, assignments, or secret values, and when the startup access token expires. Apply new migrations with the native Kysely CLI while development is running. The [local resource architecture](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#resource-configuration-and-execution--principles) describes preparation and credential boundaries.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.