Skip to main content
@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 and the Quickstart. 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: 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 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.
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 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:
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:
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: 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:
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:
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 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 for the lifecycle and the database architecture 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: 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 for selection rules.

App Layout

The generated app/root.tsx re-exports the SDK’s document Layout:
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 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:
vite.config.ts
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 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 owns capability wiring and trust boundaries. The Worker factory takes these options: The Worker entry point also exports the McpToolModule type. Keep the starter’s module discovery wiring when adding tools; Expose MCP tools 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. Use it inside a Hono handler, where c is the request context:
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. Use the CLI’s accounts and connections commands for account setup, with Connect an account 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 describes preparation and credential boundaries.