Gambit helps you build reliable LLM workflows by composing small, typed “decks”
With clear inputs/outputs and guardrails. Run the deck locally, trace streams, and
Debug with the built-in UI.
Requirements: Node.js 18+ and OPENROUTER_API_KEY (set OPENROUTER_BASE_URL
If
You proxy OpenRouter-style API).
Run the CLI directly with npx (no install):
export OPENROUTER_API_KEY=...
npx @bolt-foundry/gambit init
Downloads example files (Hello Deck Plus). examples/ gallery) and sets the environment variables.
Run an example in the terminal (repl):
npx @bolt-foundry/gambit repl gambit/hello.deck.md
This example simply says “Hello” and repeats your message back to you.
Run an example in the browser (serve):
npx @bolt-foundry/gambit serve gambit/hello.deck.md
open http://localhost:8000/debug
- Most teams connect a long prompt to multiple devices and expect model root
in the right manner. - The context often comes as a single huge fetch or RAG blob, so costs increase
Hallucinations set in. - Inputs/outputs are rarely typed, making orchestration brittle and difficult
Test offline. - Debugging relies on provider logs rather than local traces, so reproducibility
Failures are slow.
- Treat each stage as a small deck with clear inputs/outputs and guardrails;
Model call is just one type of action. - Combine LLMs and calculate functions seamlessly and interchangeably
Deck tree. - Feed models only what they need per step; Inject references and cards instead
Dumping every document. - Keep orchestration logic local and testable; play deck offline
Predictable marks. - Ship with built-in observability (streaming, REPL, debug UI) to enable debugging
It seems like it’s regular software, not a guess.
Use the CLI to run the deck locally, stream output, and capture traces/status.
Run with npx (no install):
Run the deck once:
npx @bolt-foundry/gambit run --init --message
Join REPL (stream by default):
npx @bolt-foundry/gambit repl
Play Persona against Root Deck (test bot):
npx @bolt-foundry/gambit test-bot --test-deck
Grade a saved session:
npx @bolt-foundry/gambit grade --state
Start the Debug UI Server:
npx @bolt-foundry/gambit serve --port 8000
Tracing and positioning:
--trace for JSONL trace--verbose to print events--state To continue a session.
The simulator is the local debug UI that runs the stream and renders traces.
Run with npx (no install):
Start it:
npx @bolt-foundry/gambit serve --port 8000
Then open:
This also works:
http://localhost:8000/test-bot
http://localhost:8000/calibrate
The debug UI shows the transcript lanes and trace/tools feed. If there is one in the deckinputSchemaThe UI presents a schema-driven form with defaults and a raw JSON
Tab. is stored under local-first state .gambit/ (Sessions, excerpts, notes).
Use the library when you need TypeScript decks/cards or custom compute steps.
Import helpers from JSR:
import { defineDeck, defineCard } from "jsr:@bolt-foundry/gambit";
define inputSchema/outputSchema With Zod to validate and implement IOrun/execute For calculation deck. To call a child deck from code, usectx.spawnAndWait({ path, input }). Emit structured trace events withctx.log(...).
Minimal Markdown Deck (Model-Driven): hello_world.deck.md
+++
label = "hello_world"
[modelParams]
model = "openai/gpt-4o-mini"
temperature = 0
+++
You are a concise assistant. Greet the user and echo the input.
run it:
npx @bolt-foundry/gambit run ./hello_world.deck.md --init '"Gambit"' --stream
Compute deck in TypeScript (no model calls): echo.deck.ts
// echo.deck.ts
import { defineDeck } from "jsr:@bolt-foundry/gambit";
import { z } from "zod";
export default defineDeck({
label: "echo",
inputSchema: z.object({ text: z.string() }),
outputSchema: z.object({ text: z.string(), length: z.number() }),
run(ctx) {
return { text: ctx.input.text, length: ctx.input.text.length };
},
});
run it:
npx @bolt-foundry/gambit run ./echo.deck.ts --init '{"text":"ping"}'
Deck with child action (calls TypeScript tool): agent_with_time.deck.md
+++
label = "agent_with_time"
modelParams = { model = "openai/gpt-4o-mini", temperature = 0 }
[[actionDecks]]
name = "get_time"
path = "./get_time.deck.ts"
description = "Return the current ISO timestamp."
+++
A tiny agent that calls get_time, then replies with the timestamp and the input.
and child action: get_time.deck.ts
// get_time.deck.ts
import { defineDeck } from "jsr:@bolt-foundry/gambit";
import { z } from "zod";
export default defineDeck({
label: "get_time",
inputSchema: z.object({}), // no args
outputSchema: z.object({ iso: z.string() }),
run() {
return { iso: new Date().toISOString() };
},
});
run it:
npx @bolt-foundry/gambit run ./agent_with_time.deck.md --init '"hello"' --stream
If you prefer Deno, use the deno command below.
Quick Start:
export OPENROUTER_API_KEY=...
deno run -A jsr:@bolt-foundry/gambit/cli init
Play a deck:
deno run -A jsr:@bolt-foundry/gambit/cli run --init --message
Start debug UI:
deno run -A jsr:@bolt-foundry/gambit/cli serve --port 8000
<a href