bolt-foundry/gambit: Agent harness framework for building, running, and verifying LLM workflows

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 deck
inputSchemaThe 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 IO
run/execute For calculation deck. To call a child deck from code, use
ctx.spawnAndWait({ path, input }). Emit structured trace events with
ctx.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

Leave a Comment