npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@easynet/better-call

v0.1.84

Published

Framework-agnostic tool-call reliability boundary for LLM agents and gateways.

Readme

BetterCall

BetterCall is a framework-agnostic tool-call reliability boundary. It accepts a tool inventory, proposed model tool calls, schemas, and typed policy; it returns validated, repaired, or blocked calls with diagnostics before any real tool executes.

It belongs at the last boundary before tool execution:

model/tool intent -> runtime gateway -> BetterCall -> real tool

BetterCall validates, repairs when policy allows it, preserves diagnostics, and blocks invalid calls instead of silently executing them. The key product promise is simple: a proposed call becomes a visible, schema-valid, diagnosable call, or it does not reach the real tool.

BetterCall core -> adapters/gateways -> agent runtimes and products
tool-call reliability -> integration surface -> user-facing workflows

This is intentionally narrower than an agent framework. Use your own runtime, OpenAI-compatible gateways, MCP servers, Gemini adapters, DeepAgents, or LangChain for planning, memory, approvals, orchestration, and user-facing product workflows. Use BetterCall only at the tool-call boundary where a proposed call must become a visible, valid, diagnosable call or be blocked before execution.

License

BetterCall is licensed under the Apache License, Version 2.0. Copyright 2026 BotBotGo. Please preserve the included license and attribution notices when you use, copy, modify, or distribute this software.

For engineering workflows, this means read-only evidence tools can stay visible while publish, deploy, push, or shell-mutation tools remain hidden or blocked. The runnable DevOps proof is:

npm run build
node examples/devops-gateway-boundary.mjs

The example repairs a near-miss GitHub Actions read call into a visible read-only evidence tool, rejects a hidden release_publish call, and blocks a mutating git command through schema validation.

Install

npm install @easynet/better-call

Quick Start

At a framework or gateway boundary, repair a proposed call before dispatch and only execute a visible, valid tool:

import { repairToolCall } from "@easynet/better-call";

const result = await repairToolCall({
  userInput: "Research the current market.",
  visibleTools: [{
    name: "task",
    description: "Delegate to a visible specialist.",
    schema: {
      type: "object",
      properties: {
        subagent_type: { type: "string", enum: ["research", "ops"] },
        description: { type: "string" },
      },
      required: ["subagent_type", "description"],
      additionalProperties: false,
    },
  }],
  hiddenTools: [{ name: "shell" }],
  invalidToolName: "research",
  args: {
    subagent_type: "research",
    description: "Research the current market.",
  },
});

if (result.status !== "repaired" && result.status !== "unchanged") {
  throw new Error(`Blocked tool call: ${result.reason}`);
}

await dispatch(result.toolName, result.args);

For a validate-only gateway decision, use the packaged gateway helper:

import { decideToolCallGateway } from "@easynet/better-call/gateway";

const decision = await decideToolCallGateway({
  userInput,
  visibleTools,
  hiddenTools,
  call: proposedToolCall,
});

if (!decision.executable) {
  return { status: "blocked", reason: decision.reason };
}

The repair result is structured. Production gateways can log status, reason, violations, selected toolName, repaired args, and selection diagnostics before execution.

API Surfaces

Core APIs live at the package root:

  • guardToolCalls(...): validate proposed calls against visible tools and schemas.
  • repairToolCall(...): repair or reject one proposed call at a gateway boundary.
  • normalizeArgsBySchema(...): apply policy-controlled argument normalization.
  • reliableToolCalls(...): combine guard, repair, and second-pass validation.
  • summarizeBetterCallTelemetry(...): turn decisions into compact telemetry.

Adapter APIs live under explicit subpaths:

  • @easynet/better-call/gateway: framework-agnostic validate/repair/block decisions for HTTP, MCP, OpenAI-compatible, or custom tool gateways.
  • @easynet/better-call/langchain: LangChain-style tool adapter.

For LangChain-style tools, use the adapter subpath before handing tools to your agent runtime:

import { betterTools } from "@easynet/better-call/langchain";

const tools = betterTools(existingTools);

Failure Modes

| Failure mode | BetterCall behavior | | --- | --- | | Unknown tool | Repairs only into the visible tool inventory, or rejects the call. Hidden and blocked tools remain unavailable. | | Malformed args | Parses tool-call-shaped payloads and normalizes arguments against the target schema when policy permits it. | | Enum mismatch | Repairs to an allowed enum value when the intent is clear, otherwise blocks the call with diagnostics. | | Extra fields | Removes fields disallowed by additionalProperties: false when policy permits normalization. | | Missing business facts | Returns a blocked or incomplete result that the runtime can turn into a user question. BetterCall does not invent IDs, prices, credentials, or approvals. | | Unsafe action | Leaves the product/runtime policy in charge of block, approval, or escalation. BetterCall does not approve destructive actions. | | Invalid repair | Rejects the repair result instead of executing a call that still violates schema or inventory policy. |

Repair Policy Examples

Use repair policy to keep mechanical fixes separate from business decisions:

  • allow call-envelope and schema normalization when the intended call is visible and unambiguous
  • allow safe type coercion only when the schema makes the target type obvious
  • request more information for missing business facts such as account IDs, customer IDs, dates, or prices
  • block or escalate destructive and sensitive calls when intent, authority, or approval is unclear
  • preserve diagnostics so downstream runtimes can show the raw call, normalized call, repair decision, validation result, and execution boundary

See examples/repair-policy-catalog.mjs for a runnable policy catalog and docs/recipes/repair-policy-catalog.md for website-ready copy. For the read-only engineering evidence pattern, see docs/recipes/devops-read-only-boundary.md.

Evidence

On a BFCL v4 remote Ollama run with granite4.1:3b over 3,625 cases, BetterCall improved tool-call accuracy from 73.4% raw model output to 83.8% with validation and repair. The more useful operating metric is failure reduction: the failure rate fell from 26.6% to 16.2%, a 10.4 percentage point drop and about 39% fewer failed tool-call cases.

On a newer qwen3.5:4b partial BFCL checkpoint, the completed irrelevance category shows the kind of boundary win BetterCall is built for: failure rate fell from 18.3% raw to 7.5% with BetterCall, a 10.8 percentage point drop and about 59% fewer failures when the model should not call a tool. Across the 1,648 completed cases in that interrupted run, failure rate fell from 25.9% to 16.2%, about 37% fewer failures.

The chart artifact is kept in the repository at docs/benchmark-lift.svg.

Reproduce the local proof table and sanity checks with:

npm run bench:proof

That command builds the package, runs the deterministic BetterCall sanity cases, and prints the checked-in BFCL summary from benchmarks/bfcl-targeted-summary.json. For a live local-model run, provide BFCL data and an Ollama endpoint, then run:

BFCL_DATA_DIR=/path/to/bfcl_eval/data \
OLLAMA_BASE_URL=http://127.0.0.1:11434 \
BENCH_MODELS=granite4.1:3b \
npm run bench:bfcl:real

Boundary

BetterCall is not a planner, memory layer, authorization system, approval workflow, or agent orchestration framework. Keep those responsibilities in your runtime or control plane.

Use BetterCall for:

  • tool-call schema validation
  • visible-inventory tool-name repair
  • argument normalization
  • structured repair diagnostics
  • block-on-failure behavior

Keep outside BetterCall:

  • planning and task decomposition
  • long-term memory
  • user or human approval
  • authorization and credential policy
  • semantic business rules that belong to your tool boundary

Publication Policy

The npm package is publicly installable, but the project source is not open. Published artifacts are limited to minified runtime JavaScript, TypeScript declarations, this README, and required package metadata. Source files, examples, scripts, benchmarks, documentation sources, lockfiles, build config, and source maps are not included in the published package.