Package Exports
- @usecarte/core
- @usecarte/core/drizzle
Readme
@usecarte/core
Framework-agnostic kernel for Carte — a typed query carte for putting LLMs in front of databases without giving them SQL.
@usecarte/core defines the carte itself (a fixed list of named, typed queries the LLM picks from), the plan schema the LLM emits, and the validation/execution pipeline. No React, no UI, no HTTP — those live in companion packages.
Install
pnpm add @usecarte/core zoddrizzle-orm is an optional peer for the @usecarte/core/drizzle helpers; not required if you bring your own query functions.
Usage
import { defineCarte, defineEntry, generatePrompt, parsePlan, executePlan } from "@usecarte/core";
import { z } from "zod";
const carte = defineCarte([
defineEntry({
id: "orders.recentByCustomer",
description: "Recent orders for a single customer",
params: z.object({ customerId: z.string(), limit: z.number().int().max(100).default(20) }),
returns: z.array(z.object({ id: z.string(), placedAt: z.string(), total: z.number() })),
titleTemplate: "Recent orders for customer {customerId}",
query: async ({ params }) => db.orders.findRecent(params.customerId, params.limit),
}),
]);
// Build the prompt the LLM sees — no schema, no row data, no SQL.
const prompt = generatePrompt(carte, uiAdapter, ctx);
// LLM returns a JSON plan. Validate, then execute.
const parsed = parsePlan(llmJson, carte, uiAdapter, ctx);
if (parsed.ok) {
const results = await executePlan(parsed.plan, carte);
// results is a map: panelIndex → rows. The LLM never sees this.
}Security model
Carte enforces three named architectural invariants — no schema in prompt, no result data in prompt or repair channel, statically-declared returns. See the security model for the full story.
More
The repo root README has the design motivation, the full request lifecycle, and a runnable 60-second SQLite tour.
License
MIT