@botbotgo/better-call 0.1.23 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,10 +8,14 @@
8
8
  [![license](https://img.shields.io/npm/l/@botbotgo/better-call.svg)](LICENSE)
9
9
  [![release](https://github.com/botbotgo/better-call/actions/workflows/release.yml/badge.svg)](https://github.com/botbotgo/better-call/actions/workflows/release.yml)
10
10
 
11
- BetterCall is a small runtime reliability layer for LangChain and LLM tool calls.
11
+ BetterCall is a small-model tool-call reliability layer for LangChain and custom agent runtimes.
12
12
 
13
13
  Wrap your existing tools, validate model-generated calls before execution, and optionally ask a repair model to fix rejected calls. In full BFCL v4 remote Ollama runs, the best measured lift was `granite4.1:3b`: **73.4% raw -> 83.8% with BetterCall**.
14
14
 
15
+ <p align="center">
16
+ <img src="docs/benchmark-lift.svg" alt="BetterCall improved granite4.1:3b tool-call accuracy from 73.4% to 83.8% on BFCL v4 remote Ollama runs">
17
+ </p>
18
+
15
19
  ```ts
16
20
  import { betterTools } from "@botbotgo/better-call";
17
21
 
@@ -30,6 +34,14 @@ Small models often know that a tool is needed but still fail at the boundary: wr
30
34
  - Repair rejected calls with a LangChain chat model or custom callback.
31
35
  - Keep lower-level primitives available for custom runtimes and gateways.
32
36
 
37
+ ## Examples
38
+
39
+ The `examples/` directory has copyable starting points:
40
+
41
+ - `examples/langchain-basic.mjs`: wrap a LangChain-style tool and repair bad args.
42
+ - `examples/ollama-small-model.mjs`: use an Ollama repair callback for a small local model.
43
+ - `examples/gateway-repair.mjs`: repair an invalid tool name at a custom runtime or MCP gateway boundary.
44
+
33
45
  ## Installation
34
46
 
35
47
  ```bash
@@ -230,6 +242,12 @@ Latest completed remote run artifact: `benchmarks/bfcl-real-remote-completed-sum
230
242
  | `qwen3.5:4b` | 3,625 | 43.6% | 43.4% | -0.2pp | 1,847 |
231
243
  | `gemma4:e2b` | 3,625 | 24.3% | 24.7% | +0.4pp | 2,641 |
232
244
 
245
+ ## Positioning and Launch Assets
246
+
247
+ - `docs/marketing/positioning.md`: product positioning, audience, differentiators, and calls to action.
248
+ - `docs/marketing/launch-post.md`: launch-post draft and short social version.
249
+ - `docs/marketing/growth-checklist.md`: channel-by-channel launch and adoption checklist.
250
+
233
251
  ## Requirements
234
252
 
235
253
  BetterCall is an ESM package for modern Node.js runtimes. It has one runtime dependency: `zod`.
@@ -0,0 +1,26 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="920" height="360" viewBox="0 0 920 360" role="img" aria-labelledby="title desc">
2
+ <title id="title">BetterCall BFCL small-model lift</title>
3
+ <desc id="desc">Bar chart showing granite4.1:3b improving from 73.4 percent raw to 83.8 percent with BetterCall on BFCL v4 remote Ollama runs.</desc>
4
+ <rect width="920" height="360" fill="#0f172a"/>
5
+ <rect x="34" y="28" width="852" height="304" rx="16" fill="#111827" stroke="#334155"/>
6
+ <text x="64" y="72" fill="#f8fafc" font-family="Inter, Arial, sans-serif" font-size="28" font-weight="700">Small models fail at the tool boundary</text>
7
+ <text x="64" y="104" fill="#cbd5e1" font-family="Inter, Arial, sans-serif" font-size="16">BFCL v4 remote Ollama run, granite4.1:3b, 3,625 cases</text>
8
+ <line x1="86" y1="282" x2="820" y2="282" stroke="#475569"/>
9
+ <g>
10
+ <text x="132" y="314" fill="#cbd5e1" font-family="Inter, Arial, sans-serif" font-size="15" text-anchor="middle">Raw</text>
11
+ <rect x="86" y="127" width="92" height="155" rx="8" fill="#64748b"/>
12
+ <text x="132" y="116" fill="#f8fafc" font-family="Inter, Arial, sans-serif" font-size="24" font-weight="700" text-anchor="middle">73.4%</text>
13
+ </g>
14
+ <g>
15
+ <text x="328" y="314" fill="#cbd5e1" font-family="Inter, Arial, sans-serif" font-size="15" text-anchor="middle">BetterCall</text>
16
+ <rect x="282" y="105" width="92" height="177" rx="8" fill="#22c55e"/>
17
+ <text x="328" y="94" fill="#f8fafc" font-family="Inter, Arial, sans-serif" font-size="24" font-weight="700" text-anchor="middle">83.8%</text>
18
+ </g>
19
+ <path d="M190 146 C226 118 238 118 268 112" fill="none" stroke="#38bdf8" stroke-width="3"/>
20
+ <polygon points="270,112 258,106 260,120" fill="#38bdf8"/>
21
+ <text x="224" y="142" fill="#38bdf8" font-family="Inter, Arial, sans-serif" font-size="18" font-weight="700">+10.4pp</text>
22
+ <rect x="476" y="126" width="312" height="104" rx="12" fill="#0f172a" stroke="#334155"/>
23
+ <text x="502" y="163" fill="#f8fafc" font-family="Inter, Arial, sans-serif" font-size="20" font-weight="700">Validate, repair, then execute</text>
24
+ <text x="502" y="193" fill="#cbd5e1" font-family="Inter, Arial, sans-serif" font-size="15">Unknown tools, malformed args,</text>
25
+ <text x="502" y="216" fill="#cbd5e1" font-family="Inter, Arial, sans-serif" font-size="15">schema drift, raw tool-call-shaped text.</text>
26
+ </svg>
@@ -0,0 +1,67 @@
1
+ # BetterCall Growth Checklist
2
+
3
+ The goal is to move developers through three stages:
4
+
5
+ 1. Notice the problem.
6
+ 2. Run a small example.
7
+ 3. Keep BetterCall in their runtime or tool gateway.
8
+
9
+ ## Repository
10
+
11
+ - [x] Use a precise GitHub description.
12
+ - [x] Add discoverable GitHub topics: `tool-calling`, `function-calling`, `langchain`, `ollama`, `mcp`, `small-models`, `tool-call-repair`.
13
+ - [x] Put the benchmark lift near the top of the README.
14
+ - [x] Add copyable examples.
15
+ - [ ] Add a short GIF or terminal recording showing before and after repair.
16
+ - [ ] Add a `good first issue` label set for example adapters and docs.
17
+
18
+ ## npm
19
+
20
+ - [x] Improve package description and keywords.
21
+ - [x] Include examples and README assets in the package allowlist.
22
+ - [ ] Publish the next patch version so npm metadata and tarball include the new assets.
23
+ - [ ] Verify the npm package page renders the README image and examples.
24
+
25
+ ## Content
26
+
27
+ - [x] Write launch-post draft.
28
+ - [x] Write short social version.
29
+ - [ ] Publish a technical post using the launch draft.
30
+ - [ ] Publish a benchmark-focused post explaining the BFCL wrapper methodology.
31
+ - [ ] Publish a comparison post: BetterCall vs structured-output retries vs guardrails.
32
+
33
+ ## Developer Communities
34
+
35
+ - [ ] Hacker News: launch with the problem-first title, not a marketing title.
36
+ - [ ] Reddit: post to relevant LLM engineering communities with the benchmark and example.
37
+ - [ ] X/LinkedIn: short thread with before/after tool call examples.
38
+ - [ ] LangChain community: share the `betterTools(...)` example.
39
+ - [ ] Ollama/local-model community: share the BFCL small-model result.
40
+ - [ ] MCP community: share the gateway repair example.
41
+
42
+ ## Ecosystem
43
+
44
+ - [x] Add LangChain-style example.
45
+ - [x] Add Ollama small-model example.
46
+ - [x] Add custom gateway repair example.
47
+ - [ ] Add MCP server/client gateway example.
48
+ - [ ] Add OpenAI-compatible local model example.
49
+ - [ ] Add LangGraph/stable-harness integration note when stable-harness is the public case study.
50
+
51
+ ## Conversion
52
+
53
+ - [ ] Add a one-command reproduction path for the smallest local benchmark.
54
+ - [ ] Add a "When should I use BetterCall?" FAQ.
55
+ - [ ] Add a "When should I not use BetterCall?" FAQ to build trust.
56
+ - [ ] Add a simple issue template for adapter requests.
57
+ - [ ] Track install/download/star movement after each post.
58
+
59
+ ## Launch Sequence
60
+
61
+ 1. Publish the next patch version with the README/assets/examples.
62
+ 2. Verify GitHub and npm pages.
63
+ 3. Post the short social version.
64
+ 4. Post the technical launch article.
65
+ 5. Share the three examples to the matching communities.
66
+ 6. Collect adapter requests as issues.
67
+ 7. Build the top requested adapter/example first.
@@ -0,0 +1,50 @@
1
+ # Launch Post Draft
2
+
3
+ ## Title Options
4
+
5
+ - Small models can choose the right tool and still break at the execution boundary
6
+ - BetterCall: a tiny reliability layer for LLM tool calls
7
+ - Fix malformed LLM tool calls before they execute
8
+
9
+ ## Post
10
+
11
+ LLM tool calling has a boring failure mode that shows up constantly with small models:
12
+
13
+ The model knows a tool is needed, but the actual call is not executable.
14
+
15
+ It may pick a near-miss tool name, send `symbol` instead of `ticker`, use an enum value the schema rejects, include extra fields, or emit raw tool-call-shaped text. If your runtime sends that straight to a real tool, the best case is a failed request. The worse case is the wrong operation reaching production code.
16
+
17
+ BetterCall is a small TypeScript reliability layer for that boundary.
18
+
19
+ ```ts
20
+ import { betterTools } from "@botbotgo/better-call";
21
+
22
+ const tools = betterTools([searchTool, calculatorTool], {
23
+ repairModel,
24
+ });
25
+ ```
26
+
27
+ It wraps existing LangChain-style tools, validates model-generated calls before execution, optionally asks a repair model or custom callback to fix rejected calls, validates again, and only then invokes the original tool.
28
+
29
+ The lower-level API also works at a custom runtime or MCP gateway boundary:
30
+
31
+ ```ts
32
+ import { repairToolCall } from "@botbotgo/better-call";
33
+ ```
34
+
35
+ In full BFCL v4 remote Ollama runs, the best measured lift was `granite4.1:3b`: `73.4%` raw to `83.8%` with BetterCall across `3,625` cases.
36
+
37
+ BetterCall is not an agent framework. It is the small reliability layer inside one.
38
+
39
+ Repo: https://github.com/botbotgo/better-call
40
+ Package: https://www.npmjs.com/package/@botbotgo/better-call
41
+
42
+ ## Short Social Version
43
+
44
+ Small models often know which tool they need, then fail at the execution boundary: wrong tool name, malformed args, schema drift, extra fields, raw tool-call-shaped text.
45
+
46
+ BetterCall wraps existing tools and validates, repairs, or rejects calls before real execution.
47
+
48
+ `granite4.1:3b`: `73.4%` raw to `83.8%` with BetterCall on BFCL v4 remote Ollama runs.
49
+
50
+ https://github.com/botbotgo/better-call
@@ -0,0 +1,43 @@
1
+ # BetterCall Positioning
2
+
3
+ ## One-line Positioning
4
+
5
+ BetterCall is a small-model tool-call reliability layer for LangChain and custom agent runtimes.
6
+
7
+ ## Short Pitch
8
+
9
+ Small models often know that a tool is needed but fail at the execution boundary: wrong tool names, malformed arguments, schema drift, extra fields, or raw tool-call-shaped text. BetterCall wraps existing tools and validates, repairs, or rejects the call before the real tool runs.
10
+
11
+ ## Primary Audience
12
+
13
+ - Developers building LangChain JS or custom TypeScript agent runtimes.
14
+ - Teams using small local models through Ollama or OpenAI-compatible endpoints.
15
+ - Runtime authors who need a tool gateway boundary, not another full agent framework.
16
+ - MCP or tool-server authors who need schema-aware call repair before execution.
17
+
18
+ ## Differentiation
19
+
20
+ | Alternative | What it usually solves | BetterCall position |
21
+ | --- | --- | --- |
22
+ | Agent frameworks | Agent loop, memory, planning, tool invocation | Drop-in reliability layer at the tool boundary |
23
+ | Guardrails frameworks | Input/output safety and policy checks | Tool-call contract validation and repair |
24
+ | Structured-output libraries | JSON/object extraction and retries | Existing tool-call repair before execution |
25
+ | MCP platforms | Hosted API/tool surfaces | Independent npm package for any JS runtime |
26
+
27
+ ## Proof Point
28
+
29
+ In full BFCL v4 remote Ollama runs, the best measured lift was `granite4.1:3b`: `73.4%` raw to `83.8%` with BetterCall across `3,625` cases.
30
+
31
+ ## Core Messages
32
+
33
+ - Small models can pick the right intent and still break at the tool boundary.
34
+ - BetterCall validates and repairs before execution, so unsafe or malformed calls do not reach real tools.
35
+ - It works with existing LangChain-style tools and lower-level custom gateways.
36
+ - It is not an agent framework; it is the reliability layer inside one.
37
+
38
+ ## Calls To Action
39
+
40
+ - Install: `npm install @botbotgo/better-call`
41
+ - Try the 30-line examples in `examples/`
42
+ - Run `npm run bench:bfcl` to reproduce the wrapper sanity benchmark
43
+ - Use `repairToolCall(...)` at a runtime or MCP gateway boundary
@@ -0,0 +1,31 @@
1
+ # BetterCall Examples
2
+
3
+ Each example is intentionally small enough to copy into an app.
4
+
5
+ ## Examples
6
+
7
+ - `langchain-basic.mjs`: Wrap a LangChain-style tool and repair invalid args before execution.
8
+ - `ollama-small-model.mjs`: Use an Ollama-compatible repair model callback with `reliableToolCalls`.
9
+ - `gateway-repair.mjs`: Repair an invalid tool name at a custom runtime or MCP gateway boundary.
10
+
11
+ ## Run
12
+
13
+ Build the package first:
14
+
15
+ ```bash
16
+ npm install
17
+ npm run build
18
+ ```
19
+
20
+ Then run an example:
21
+
22
+ ```bash
23
+ node examples/langchain-basic.mjs
24
+ node examples/gateway-repair.mjs
25
+ ```
26
+
27
+ The Ollama example expects an Ollama-compatible `/api/generate` endpoint:
28
+
29
+ ```bash
30
+ OLLAMA_BASE_URL=http://127.0.0.1:11434 OLLAMA_MODEL=granite4.1:3b node examples/ollama-small-model.mjs
31
+ ```
@@ -0,0 +1,25 @@
1
+ import { repairToolCall } from "../dist/index.js";
2
+
3
+ const visibleTools = [{
4
+ name: "task",
5
+ description: "Delegate a task to a visible specialist.",
6
+ schema: {
7
+ type: "object",
8
+ properties: {
9
+ subagent_type: { type: "string", enum: ["research", "ops"] },
10
+ description: { type: "string" },
11
+ },
12
+ required: ["subagent_type", "description"],
13
+ additionalProperties: false,
14
+ },
15
+ }];
16
+
17
+ const result = await repairToolCall({
18
+ userInput: "Research the current market.",
19
+ visibleTools,
20
+ hiddenTools: [{ name: "shell" }],
21
+ invalidToolName: "research",
22
+ args: { subagent_type: "research", description: "Research the current market." },
23
+ });
24
+
25
+ console.log(JSON.stringify(result, null, 2));
@@ -0,0 +1,30 @@
1
+ import { betterTools } from "../dist/index.js";
2
+
3
+ const stockQuote = {
4
+ name: "stock_quote",
5
+ description: "Get a stock quote.",
6
+ schema: {
7
+ type: "object",
8
+ properties: {
9
+ ticker: { type: "string" },
10
+ market: { type: "string", enum: ["US", "HK", "CN"] },
11
+ },
12
+ required: ["ticker", "market"],
13
+ additionalProperties: false,
14
+ },
15
+ async invoke(args) {
16
+ return { ok: true, quote: args };
17
+ },
18
+ };
19
+
20
+ const [safeStockQuote] = betterTools([stockQuote], {
21
+ userInput: "Get Apple stock in the US market.",
22
+ repair() {
23
+ return [{ tool: "stock_quote", args: { ticker: "AAPL", market: "US" } }];
24
+ },
25
+ });
26
+
27
+ const before = { symbol: "Apple", market: "NASDAQ" };
28
+ const after = await safeStockQuote.invoke(before);
29
+
30
+ console.log(JSON.stringify({ before, after }, null, 2));
@@ -0,0 +1,46 @@
1
+ import { reliableToolCalls } from "../dist/index.js";
2
+
3
+ const baseUrl = process.env.OLLAMA_BASE_URL ?? "http://127.0.0.1:11434";
4
+ const model = process.env.OLLAMA_MODEL ?? "granite4.1:3b";
5
+
6
+ const tools = [{
7
+ name: "stock_quote",
8
+ description: "Get a stock quote.",
9
+ schema: {
10
+ type: "object",
11
+ properties: {
12
+ ticker: { type: "string" },
13
+ market: { type: "string", enum: ["US", "HK", "CN"] },
14
+ },
15
+ required: ["ticker", "market"],
16
+ additionalProperties: false,
17
+ },
18
+ }];
19
+
20
+ const badCall = { tool: "stock_price", args: { symbol: "Apple", market: "NASDAQ" } };
21
+
22
+ const result = await reliableToolCalls({
23
+ userInput: "Get Apple stock in the US market.",
24
+ tools,
25
+ calls: [badCall],
26
+ repair: async ({ userInput, tools, calls, issues }) => {
27
+ const prompt = [
28
+ "Return corrected JSON only as {\"calls\":[{\"tool\":\"name\",\"args\":{}}]}.",
29
+ `User: ${userInput}`,
30
+ `Tools: ${JSON.stringify(tools)}`,
31
+ `Rejected calls: ${JSON.stringify(calls)}`,
32
+ `Issues: ${JSON.stringify(issues)}`,
33
+ ].join("\n");
34
+
35
+ const response = await fetch(`${baseUrl}/api/generate`, {
36
+ method: "POST",
37
+ headers: { "content-type": "application/json" },
38
+ body: JSON.stringify({ model, prompt, stream: false, format: "json" }),
39
+ });
40
+ if (!response.ok) throw new Error(`Ollama request failed: ${response.status}`);
41
+ const json = await response.json();
42
+ return JSON.parse(json.response).calls;
43
+ },
44
+ });
45
+
46
+ console.log(JSON.stringify({ model, badCall, result }, null, 2));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@botbotgo/better-call",
3
- "version": "0.1.23",
4
- "description": "LLM tool-call reliability layer.",
3
+ "version": "0.1.24",
4
+ "description": "Small-model tool-call reliability layer for LangChain and custom agent runtimes.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -18,7 +18,14 @@
18
18
  "tool-calling",
19
19
  "function-calling",
20
20
  "guardrails",
21
- "reliability"
21
+ "reliability",
22
+ "langchain",
23
+ "ollama",
24
+ "mcp",
25
+ "tool-call-repair",
26
+ "function-call-repair",
27
+ "small-models",
28
+ "agent-runtime"
22
29
  ],
23
30
  "exports": {
24
31
  ".": {
@@ -30,7 +37,10 @@
30
37
  "dist",
31
38
  "benchmarks",
32
39
  "scripts",
40
+ "examples",
33
41
  "docs/banner.svg",
42
+ "docs/benchmark-lift.svg",
43
+ "docs/marketing",
34
44
  "README.md",
35
45
  "NOTICE",
36
46
  "LICENSE"