@botbotgo/better-call 0.1.25 → 0.1.27

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
@@ -30,6 +30,8 @@ Try the built-in demo after installing:
30
30
  npx @botbotgo/better-call demo
31
31
  ```
32
32
 
33
+ New users can start with `docs/adoption.md` for the shortest path from demo to integration.
34
+
33
35
  ## Why BetterCall?
34
36
 
35
37
  Small models often know that a tool is needed but still fail at the boundary: wrong tool names, malformed arguments, schema drift, extra fields, or raw tool-call-shaped text. BetterCall sits at that boundary and gives you a typed, auditable way to accept, repair, or reject the call before the real tool runs.
@@ -256,6 +258,7 @@ Latest completed remote run artifact: `benchmarks/bfcl-real-remote-completed-sum
256
258
  - `docs/marketing/positioning.md`: product positioning, audience, differentiators, and calls to action.
257
259
  - `docs/marketing/launch-post.md`: launch-post draft and short social version.
258
260
  - `docs/marketing/growth-checklist.md`: channel-by-channel launch and adoption checklist.
261
+ - `docs/adoption.md`: start-here guide from demo to integration.
259
262
  - `docs/recipes/`: focused integration recipes.
260
263
  - `docs/faq.md`: adoption and boundary FAQ.
261
264
  - `docs/case-studies/stable-harness-tool-gateway.md`: production gateway integration pattern.
@@ -0,0 +1,67 @@
1
+ # Start Using BetterCall
2
+
3
+ This guide is for developers who want to try BetterCall quickly and then decide where it belongs in their runtime.
4
+
5
+ ## 1. Run the Demo
6
+
7
+ ```bash
8
+ npx @botbotgo/better-call demo
9
+ ```
10
+
11
+ The demo shows three failure modes:
12
+
13
+ - invalid tool arguments repaired before invocation
14
+ - wrong tool name repaired into a visible tool
15
+ - gateway repair diagnostics for audit logs
16
+
17
+ Use JSON output when wiring the result into docs or tests:
18
+
19
+ ```bash
20
+ npx @botbotgo/better-call demo --json
21
+ ```
22
+
23
+ ## 2. Pick Your Integration Path
24
+
25
+ | If you use | Start here |
26
+ | --- | --- |
27
+ | LangChain-style tools | `examples/langchain-basic.mjs` |
28
+ | A custom runtime or tool gateway | `examples/gateway-repair.mjs` |
29
+ | MCP-style dispatch | `examples/adapters/mcp-gateway-boundary.mjs` |
30
+ | Ollama local models | `examples/ollama-small-model.mjs` |
31
+ | OpenAI-compatible local endpoints | `examples/adapters/openai-compatible-repair.mjs` |
32
+ | A production tool gateway | `docs/case-studies/stable-harness-tool-gateway.md` |
33
+
34
+ ## 3. Decide the Boundary
35
+
36
+ BetterCall should sit immediately before real tool execution:
37
+
38
+ ```text
39
+ model/tool intent -> runtime gateway -> BetterCall -> real tool
40
+ ```
41
+
42
+ Keep these responsibilities outside BetterCall:
43
+
44
+ - planning
45
+ - memory
46
+ - human approval
47
+ - authorization
48
+ - agent orchestration
49
+
50
+ Keep these responsibilities inside or near BetterCall:
51
+
52
+ - tool-call schema validation
53
+ - tool-name repair inside a visible inventory
54
+ - argument normalization
55
+ - repair diagnostics
56
+ - block-on-failure behavior
57
+
58
+ ## 4. Bring a Broken Tool Call
59
+
60
+ If you are not sure how to integrate your framework, open an adapter request with:
61
+
62
+ - your current tool shape
63
+ - the model's broken call
64
+ - the call you expect after repair
65
+ - any hidden tools, policy rules, or approval constraints
66
+
67
+ Use the adapter request or broken tool-call issue templates in this repository.
@@ -16,6 +16,8 @@ The goal is to move developers through three stages:
16
16
  - [x] Add focused recipes for common integration problems.
17
17
  - [x] Add a stable-harness gateway case study.
18
18
  - [x] Add an adapter request issue template.
19
+ - [x] Add a broken tool-call issue template.
20
+ - [x] Add a start-here adoption guide.
19
21
  - [ ] Add a short GIF or terminal recording showing before and after repair.
20
22
  - [ ] Add a `good first issue` label set for example adapters and docs.
21
23
 
@@ -53,6 +55,7 @@ The goal is to move developers through three stages:
53
55
  - [x] Add LangChain adapter helper example.
54
56
  - [x] Add OpenAI-compatible local model example.
55
57
  - [x] Add LangGraph/stable-harness integration note when stable-harness is the public case study.
58
+ - [x] Add LangChain, MCP, and OpenAI-compatible recipes.
56
59
 
57
60
  ## Conversion
58
61
 
@@ -12,7 +12,7 @@ LLM tool calling has a boring failure mode that shows up constantly with small m
12
12
 
13
13
  The model knows a tool is needed, but the actual call is not executable.
14
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.
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 worst case is the wrong operation reaching production code.
16
16
 
17
17
  BetterCall is a small TypeScript reliability layer for that boundary.
18
18
 
@@ -3,9 +3,12 @@
3
3
  Each recipe solves one integration problem with a small copyable pattern.
4
4
 
5
5
  - `wrong-tool-name.md`: Repair a tool name before gateway dispatch.
6
+ - `langchain-wrapper.md`: Wrap LangChain-style tools.
7
+ - `mcp-gateway.md`: Repair at an MCP-style gateway boundary.
6
8
  - `zod-schema.md`: Use Zod object schemas or Zod-shaped records.
7
9
  - `validate-only.md`: Run without a repair model and block invalid calls.
8
10
  - `ollama-repair.md`: Use a local Ollama model as the repair callback.
11
+ - `openai-compatible.md`: Use an OpenAI-compatible local endpoint as the repair callback.
9
12
  - `semantic-validator.md`: Keep domain validation in your tool boundary.
10
13
 
11
14
  See also `../faq.md` for adoption and boundary guidance.
@@ -0,0 +1,21 @@
1
+ # Recipe: Wrap LangChain-style Tools
2
+
3
+ Use `betterTools(...)` when your tool already has `name`, `schema`, and `invoke(input)`.
4
+
5
+ ```ts
6
+ import { betterTools } from "@botbotgo/better-call";
7
+
8
+ const tools = betterTools([searchTool, calculatorTool], {
9
+ repairModel,
10
+ });
11
+ ```
12
+
13
+ If you want a named helper in your own codebase:
14
+
15
+ ```ts
16
+ export function withBetterCallLangChainTools(tools, options = {}) {
17
+ return betterTools(tools, options);
18
+ }
19
+ ```
20
+
21
+ See `examples/adapters/langchain-tool-wrapper.mjs` for a runnable version.
@@ -0,0 +1,28 @@
1
+ # Recipe: Repair at an MCP-style Gateway Boundary
2
+
3
+ Use `repairToolCall(...)` before dispatching a tool request to an MCP server or gateway.
4
+
5
+ ```ts
6
+ import { repairToolCall } from "@botbotgo/better-call";
7
+
8
+ const repaired = await repairToolCall({
9
+ userInput,
10
+ visibleTools,
11
+ hiddenTools,
12
+ invalidToolName: request.name,
13
+ args: request.arguments,
14
+ repairPolicy: {
15
+ allowCoercion: true,
16
+ allowClamp: true,
17
+ allowDropUnknownKeys: true,
18
+ },
19
+ });
20
+
21
+ if (repaired.status === "rejected") {
22
+ return { error: repaired.reason, violations: repaired.violations };
23
+ }
24
+
25
+ return dispatch(repaired.toolName, repaired.args);
26
+ ```
27
+
28
+ The gateway still owns authorization. BetterCall only repairs into the visible tool inventory.
@@ -0,0 +1,41 @@
1
+ # Recipe: Use an OpenAI-compatible Repair Endpoint
2
+
3
+ Use this pattern for local servers that expose `/v1/chat/completions`.
4
+
5
+ ```ts
6
+ import { reliableToolCalls } from "@botbotgo/better-call";
7
+
8
+ const result = await reliableToolCalls({
9
+ userInput,
10
+ tools,
11
+ calls,
12
+ repair: async ({ userInput, tools, calls, issues }) => {
13
+ const response = await fetch(`${baseUrl}/v1/chat/completions`, {
14
+ method: "POST",
15
+ headers: {
16
+ "Authorization": `Bearer ${apiKey}`,
17
+ "content-type": "application/json",
18
+ },
19
+ body: JSON.stringify({
20
+ model,
21
+ response_format: { type: "json_object" },
22
+ messages: [{
23
+ role: "user",
24
+ content: [
25
+ "Return corrected JSON only as {\"calls\":[{\"tool\":\"name\",\"args\":{}}]}.",
26
+ `User: ${userInput}`,
27
+ `Tools: ${JSON.stringify(tools)}`,
28
+ `Rejected calls: ${JSON.stringify(calls)}`,
29
+ `Issues: ${JSON.stringify(issues)}`,
30
+ ].join("\n"),
31
+ }],
32
+ }),
33
+ });
34
+
35
+ const json = await response.json();
36
+ return JSON.parse(json.choices[0].message.content).calls;
37
+ },
38
+ });
39
+ ```
40
+
41
+ See `examples/adapters/openai-compatible-repair.mjs` for a runnable version.
@@ -33,5 +33,5 @@ The Ollama and OpenAI-compatible examples expect local model endpoints:
33
33
 
34
34
  ```bash
35
35
  OLLAMA_BASE_URL=http://127.0.0.1:11434 OLLAMA_MODEL=granite4.1:3b node examples/ollama-small-model.mjs
36
- OPENAI_BASE_URL=http://127.0.0.1:8000/v1 OPENAI_MODEL=local-model node examples/adapters/openai-compatible-repair.mjs
36
+ OPENAI_BASE_URL=http://127.0.0.1:8000 OPENAI_MODEL=local-model node examples/adapters/openai-compatible-repair.mjs
37
37
  ```
@@ -1,6 +1,6 @@
1
1
  import { reliableToolCalls } from "../../dist/index.js";
2
2
 
3
- const baseUrl = process.env.OPENAI_BASE_URL ?? "http://127.0.0.1:8000/v1";
3
+ const baseUrl = process.env.OPENAI_BASE_URL ?? "http://127.0.0.1:8000";
4
4
  const model = process.env.OPENAI_MODEL ?? "local-model";
5
5
  const apiKey = process.env.OPENAI_API_KEY ?? "not-needed-for-local";
6
6
 
@@ -23,10 +23,10 @@ const result = await reliableToolCalls({
23
23
  tools,
24
24
  calls: [{ tool: "stock_price", args: { symbol: "Apple", market: "NASDAQ" } }],
25
25
  repair: async ({ userInput, tools, calls, issues }) => {
26
- const response = await fetch(`${baseUrl}/chat/completions`, {
26
+ const response = await fetch(`${baseUrl}/v1/chat/completions`, {
27
27
  method: "POST",
28
28
  headers: {
29
- "authorization": `Bearer ${apiKey}`,
29
+ "Authorization": `Bearer ${apiKey}`,
30
30
  "content-type": "application/json",
31
31
  },
32
32
  body: JSON.stringify({
@@ -17,12 +17,12 @@ const tools = [{
17
17
  },
18
18
  }];
19
19
 
20
- const badCall = { tool: "stock_price", args: { symbol: "Apple", market: "NASDAQ" } };
20
+ const invalidToolCall = { tool: "stock_price", args: { symbol: "Apple", market: "NASDAQ" } };
21
21
 
22
22
  const result = await reliableToolCalls({
23
23
  userInput: "Get Apple stock in the US market.",
24
24
  tools,
25
- calls: [badCall],
25
+ calls: [invalidToolCall],
26
26
  repair: async ({ userInput, tools, calls, issues }) => {
27
27
  const prompt = [
28
28
  "Return corrected JSON only as {\"calls\":[{\"tool\":\"name\",\"args\":{}}]}.",
@@ -43,4 +43,4 @@ const result = await reliableToolCalls({
43
43
  },
44
44
  });
45
45
 
46
- console.log(JSON.stringify({ model, badCall, result }, null, 2));
46
+ console.log(JSON.stringify({ model, invalidToolCall, result }, null, 2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/better-call",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Small-model tool-call reliability layer for LangChain and custom agent runtimes.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -41,6 +41,7 @@
41
41
  "benchmarks",
42
42
  "scripts",
43
43
  "examples",
44
+ "docs/adoption.md",
44
45
  "docs/banner.svg",
45
46
  "docs/benchmark-lift.svg",
46
47
  "docs/faq.md",
package/scripts/demo.mjs CHANGED
@@ -34,6 +34,7 @@ const wrappedOutput = await wrappedStockQuote.invoke(badArgs);
34
34
  const reliableResult = await reliableToolCalls({
35
35
  userInput: "Get Apple stock in the US market.",
36
36
  tools: [stockQuote],
37
+ // The tool name is intentionally wrong to demonstrate repair to stock_quote.
37
38
  calls: [{ tool: "stock_price", args: badArgs }],
38
39
  repair() {
39
40
  return [{ tool: "stock_quote", args: { ticker: "AAPL", market: "US" } }];