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

@once-agent/sdk

v0.1.25

Published

Block duplicate consequential writes after lost acknowledgements; replay confirmed results and reconcile uncertain outcomes.

Downloads

4,986

Readme

@once-agent/sdk

Your action succeeded. Its response disappeared. Should the caller retry? Once replays confirmed results and blocks another consequential write while the original outcome is unknown.

Start with the account-free local refund proof or existing installed-SDK quickstart. The standalone refund proof runs with SDK 0.1.24 or later; SDK 0.1.25 also includes it as once prove. No cloud account or financial transaction is required.

If provider-native idempotency or a database constraint fully solves your operation, use it. Harmless repetition does not need Once. Keep native idempotency where available. Once does not promise universal exactly-once execution.

Local protection requires Node 24.15+, one durable shared same-machine SQLite authority, developer-owned logical identity, and complete effect/account binding. UNKNOWN is protection: retain state and identity, reconcile authoritative read-only truth, and never bypass the wrapper to force progress.

SDK 0.1.25 adds once prove (controlled fixture only) and once check [directory] (read-only candidates). Existing once doctor remains available.

Natural placement (0.1.24)

For a host-owned unary tool callback, wrapTool(callback, semantics) delegates to protectToolCall:

import { wrapTool } from "@once-agent/sdk";

const protectedSend = wrapTool(sendMessage, {
  statePath: "./durable/once.sqlite",
  operationId: ({ orderId }) => `order:${orderId}:send`,
  effect: ({ orderId, message }) => ({
    tool: "messaging.account-A.send",
    args: { orderId, message },
  }),
  reconcile: ({ effect }) => readExactMessage(effect),
});

The callback receives frozen effect.args; bind fixed account authority and every consequential argument. Identity and complete semantics remain application-owned. UNKNOWN never triggers another execution. Internal callback retries and model-side connectors without host execution control are outside this boundary. Requires Node 24.15+ and one durable local state file. See two execution surfaces and design. Introduced in SDK 0.1.24.

Explicit connected-tool calls

protectToolCall protects a host-supplied async tool function without provider credentials in the agent process. Supply a stable logical ID, complete effect, and a persistent local state file (Node.js 24.15+):

import { protectToolCall } from "@once-agent/sdk";

await protectToolCall({
  operationId: "account-A:comment:request-001",
  statePath: "./persistent/once.sqlite",
  effect: {
    tool: "github.account-A.add_comment",
    args: { repo: "owner/lab", issue: 217, body: "Exact comment text" },
  },
  execute: ({ args }) => connectedTools.addComment(args),
  reconcile: ({ effect }) => connectedTools.findMatchingComment(effect.args),
});

Exact retries replay confirmed receipts; changed effects return CONFLICT. Errors after entering execute remain UNKNOWN. Reconciliation returns CONFIRMED with a JSON-safe result, NOT_FOUND, or UNKNOWN; only positive confirmation enables recovery. Neither NOT_FOUND nor missing reconciliation permits redispatch. The host must bind account identity, use the supplied frozen effect snapshot, normalize tool errors, and prevent duplicate internal retries. Keep all effect-bearing inputs in effect.args; transport metadata may be supplied separately as metadata. This requires one preserved local authority across retries. Full source contract: PROTECT_TOOL_CALL.md.

Automatic Connect (introduced in 0.1.12): the current SDK includes the @once-agent/sdk/connect public surface for automatic tool classification, whole-toolset wiring, trusted intent identity, conservative effect binding, and OpenAI Agents FunctionTool wrapping. It has passed source, packed-package, ESM/CommonJS, and Node.js 24.15 protected-execution gates.

Full guide: https://github.com/stringsofthemind-oss/once/blob/main/docs/CONNECT_AUTO.md

Local protection: protectLocal wraps an existing async function using a durable same-machine SQLite file. This feature requires Node.js 24.15 or later. See the local function guide: https://github.com/stringsofthemind-oss/once/blob/main/examples/local-function/README.md

Automatic Connect

Automatic Connect is designed for the integration path where an application already has a registry or framework list of agent tools.

import {
  connectLocalAgentToolsetAuto
} from "@once-agent/sdk/connect";

const connected = connectLocalAgentToolsetAuto(
  {
    search_web: {
      async execute(input: { query: string }) {
        return search(input.query);
      }
    },
    send_email: {
      async execute(input: {
        intentId: string;
        destination: string;
        body: string;
      }) {
        return mailer.send({
          to: input.destination,
          body: input.body
        });
      }
    }
  },
  {
    manifest: [
      {
        name: "search_web",
        description: "Search the public web."
      },
      {
        name: "send_email",
        description: "Send an email to a recipient.",
        _meta: {
          once: {
            identityFields: ["intentId"],
            effectFields: ["destination", "body"]
          }
        }
      }
    ],
    statePath: ".once/agent-tools.sqlite"
  }
);

// Give the agent only the connected tools.
const toolsForAgent = connected.tools;

Automatic Connect classifies tools as BYPASS, PROTECT, or UNKNOWN. UNKNOWN fails closed. Whole-toolset connection is all-or-nothing: duplicate, missing, undeclared, invalid, or unresolved tools block connection rather than silently exposing a partially protected registry.

Protected automatic local execution still requires a trustworthy logical action identity and a payload that represents the consequential effect. Explicit identityFields and effectFields are preferred when available. Framework or transport attempt IDs are not automatically treated as business intent.

The automatic local path requires Node.js 24.15+ and shared durable SQLite state on one machine. It is not a universal exactly-once or multi-host guarantee.

[!IMPORTANT]

ONCE is currently in Stripe Sandbox / Test Mode

ONCE billing is currently connected to a Stripe sandbox. No real payment is taken and no real money moves while this beta is running in sandbox mode.

Do not enter real card details.

If Stripe asks for payment details during testing, use:

  • Card number: 4242 4242 4242 4242
  • Name: John Doe (or any name)
  • Expiry: 12/34 (or any future date)
  • CVC: 123 (or any 3 digits)
  • Postcode / ZIP: any valid-looking value

These are Stripe test credentials only.

ONCE will clearly announce when billing moves from sandbox to live payments.

Make side-effecting AI agent tools safe to retry.

Once helps prevent an AI agent, workflow, or application from accidentally performing the same consequential action twice when the outcome of the first request is uncertain.

Typical examples include:

  • payments and refunds
  • bookings and reservations
  • emails and messages
  • account changes
  • order creation
  • webhook-triggered actions
  • other irreversible or externally visible writes

Install

npm install @once-agent/sdk

Requires Node.js 18 or later.

Configure

Set your Once API key:

ONCE_API_KEY=your_api_key

Node note: saving ONCE_API_KEY in .env does not make vanilla Node load it automatically. Use your framework/runtime's environment loader, export the variable before starting the process, or on supported Node versions run your application with node --env-file=.env <your-entry-file>.

new Once() reads ONCE_API_KEY automatically.

Do not commit API keys to source control.

60-second quick start

Runtime HTTP protection

For supported POST + JSON HTTP writes, configure the exact protected HTTPS target:

npx once setup . --runtime-http=https://api.example.com/v1/action

This setup pins that exact target in the provider allowlist and opts the immutable provider version into durable HTTP response replay.

import { createOnceRuntimeFetch } from "@once-agent/sdk";

const onceFetch = createOnceRuntimeFetch({
  provider: "my-provider"
});

async function main() {
  const response = await onceFetch(
    "https://api.example.com/v1/action",
    {
      method: "POST",
      headers: {
        "content-type": "application/json",
        "idempotency-key": "order_123"
      },
      body: JSON.stringify({ example: true })
    }
  );

  console.log(response.status);
  console.log(await response.text());
}

main().catch(console.error);

Retry the same logical real-world action with the same stable identity. In this Runtime HTTP example, that identity is carried by the idempotency-key.

The Runtime fails closed rather than silently falling back to a direct target write when an operation cannot be safely protected.

Direct SDK execution

First configure a provider with once setup ., or use a provider alias already registered with your Once account.

import { Once } from "@once-agent/sdk";

async function main() {
  const once = new Once();

  const operationId = Once.id(
    "refund",
    "order_123"
  );

  const result = await once.execute({
    operationId,
    provider: "my-provider",
    action: {
      type: "refund",
      order_id: "123"
    }
  });

  console.log(result.state);
}

main().catch(console.error);

Replace my-provider with the provider alias configured for your Once account.

The important part: operationId

For the same logical operation, reuse the same operation ID on every retry.

const operationId = Once.id(
  "refund",
  "order_123"
);

The same supported inputs produce the same deterministic ID.

Different logical operations should use different semantic inputs:

Once.id("refund", "order_123");
Once.id("refund", "order_124");

Do not generate a new random ID for each retry if the retry represents the same real-world operation.

Why this exists

A normal retry can be dangerous when the request causes a real side effect.

For example:

  1. your application sends a refund request;
  2. the provider performs the refund;
  3. the network fails before your application receives the response;
  4. your application cannot tell whether the refund happened;
  5. it retries.

Without reconciliation, the retry may perform the same consequential action again.

Once keeps durable operation state and, for supported provider integrations, can reconcile provider truth before allowing an ambiguous operation to execute again.

Once may preserve an operation as uncertain rather than assume that another execution is safe.

Retries

Retries reuse the same operationId:

await once.execute({
  operationId,
  provider: "my-provider",
  action
});

Check operation truth

You can inspect the durable state of an operation later:

const truth = await once.truth(operationId);

console.log(truth.ledger_state);

This is useful after an ambiguous request, or when another process needs to determine the durable state of an existing operation.

Once.id()

Once.id() generates a deterministic operation ID from semantic values.

const id = Once.id(
  "send-invoice",
  "invoice_4821"
);

Supported parts are:

  • strings
  • safe integers

Examples:

Once.id("payment", "invoice_42");
Once.id("booking", 4821);

Unsupported or ambiguous values are rejected rather than silently producing language-dependent identifiers.

For example, do not pass booleans, null, fractional numbers, or integers outside the JavaScript safe-integer range.

Cross-language identity

Once.id() uses the versioned once-id-v1 encoding.

The TypeScript and Python implementations are checked against the same frozen conformance vectors so supported inputs produce the same operation ID in both languages.

The identity hash uses unambiguous UTF-8 byte-length-prefixed parts, so different part boundaries cannot collapse into the same hash input.

The readable prefix is only a label. The deterministic hash represents the complete semantic input.

Choosing good operation IDs

An operation ID should identify the real-world action, not the network attempt.

Good:

Once.id("refund", "order_123");

Risky:

Once.id("refund", Date.now());

A timestamp changes on every retry, so Once would see each attempt as a different operation.

A useful question is:

If this request times out and I retry it, should the retry represent the same real-world action?

If the answer is yes, reuse the same operation ID.

CLI workflow

The package includes the once CLI.

Start with Doctor:

npx once doctor .

Doctor is local and read-only by default. It does not require ONCE_API_KEY, does not upload source code, and does not change source files. It reports detected project metadata and likely consequential-operation candidates, then prints the exact once protect command for the next step.

A typical first-run workflow is:

doctor -> protect -> setup/integrate -> apply (when eligible)

1. Diagnose locally

npx once doctor .

Generate a review plan and per-callsite integration snippets without changing source:

npx once doctor . --protect

To explicitly verify a configured hosted Once connection as well:

npx once doctor . --connection

Hosted connection verification requires ONCE_API_KEY. The default Doctor scan does not.

2. Review protection candidates

npx once protect .

Include all confidence levels:

npx once protect . --all

Write a review plan:

npx once protect . --all --write-plan

This can create:

.once/protect-plan.json

Generate per-callsite integration guidance:

npx once protect . --all --snippets

3. Set up Once when integration requires it

npx once setup .

Setup can install/configure the SDK, verify your API key, register a supported provider, and prepare local Once configuration.

For Runtime HTTP protection, provide the exact target URL:

npx once setup . --runtime-http=https://api.example.com/v1/action

Runtime HTTP setup registers that exact URL in allowed_urls and requests response_replay="required" for that immutable provider version.

Only non-secret provider metadata is written to .once/config.json; the provider bearer token is not stored there.

Plain npx once setup . preserves the existing provider-registration behavior and does not opt that provider version into HTTP response replay.

Preview setup without making changes:

npx once setup . --plan

4. Use the standalone scanner when you want raw scan output

npx once scan .

The scanner looks locally for likely side-effecting operations that may benefit from Once protection. Source code is reviewed locally by the CLI and is not uploaded.

5. Preview or apply an eligible transformation

Preview a patch without modifying application source:

npx once protect . --all --patch

Apply exactly one eligible, revalidated transformation:

npx once protect . --apply

--apply is intentionally conservative.

Automatic application only proceeds for a narrowly supported callsite that is fully revalidated before modification.

The apply engine checks the source fingerprint, recomputes the proposed transformation, verifies TypeScript, writes a backup, uses a temporary file, verifies the result, and rolls back if post-write validation fails.

If there are zero or multiple PATCHABLE candidates, automatic apply is rejected rather than guessing.

protect status meanings

Protection review may report statuses such as:

  • PATCHABLE - the current narrow transformer can produce a validated automatic patch
  • PROVIDER_MAPPING_REQUIRED - the call needs a provider mapping before protection can be planned
  • PROVIDER_CAPABILITY_DECLARED - provider capability is declared, but automatic transformation still requires an exact supported match
  • ADAPTER_REQUIRED - the operation needs provider-specific integration work
  • MANUAL_REVIEW - the CLI will not automatically rewrite the callsite

The CLI is designed to prefer manual review over unsafe automatic modification.

Safety model

Once does not claim universal exactly-once execution.

Its safety properties depend on:

  • a stable operation ID
  • durable Once operation state
  • the provider integration being used
  • sufficiently authoritative provider truth
  • the failure mode being within that provider integration's supported model

For supported provider integrations, Once is designed to suppress duplicate execution across retries and ambiguous transport failures by reconciling provider truth before permitting re-execution.

For Runtime HTTP providers registered with response_replay="required", Once also requires a durable, sanitized application-visible HTTP response replay before the local operation can become CONFIRMED. Confirmed retries can return that stored response without executing the provider again.

When Once cannot determine whether an external side effect occurred, or when required replay evidence is missing after an effect may have happened, it preserves the operation as uncertain rather than assume another execution is safe.

This means Once may sacrifice availability temporarily in order to avoid an unsafe duplicate side effect.

The external effect itself is not atomically committed with Once's local ledger. The supported claim is duplicate suppression on confirmed/replay paths plus fail-closed handling of ambiguous outcomes, not generic exactly-once execution.

Provider truth

Once is strongest when the external system can answer a question equivalent to:

Did operation X already happen?

A provider integration defines both:

  1. how the consequential action is executed;
  2. how Once later determines authoritative provider truth.

Provider-specific guarantees should therefore be evaluated separately from the SDK itself.

Errors

Once exports OnceError for SDK and service errors.

import {
  Once,
  OnceError
} from "@once-agent/sdk";

const once = new Once();

try {
  await once.execute({
    operationId,
    provider: "my-provider",
    action
  });
} catch (error) {
  if (error instanceof OnceError) {
    console.error(
      error.code,
      error.message
    );
  }

  throw error;
}

Do not automatically treat every error as permission to execute the external side effect directly.

An error may represent an ambiguous outcome. Querying operation truth or retrying through Once with the same operation ID preserves the safety model.

API overview

new Once(options?)

Creates a Once client.

The default configuration reads ONCE_API_KEY from the environment.

Supported client options include:

  • apiKey
  • baseUrl
  • timeoutMs
  • networkRetries

Once.id(...parts)

Creates a deterministic operation ID from supported semantic parts.

const operationId = Once.id(
  "charge",
  "invoice_123"
);

once.execute(input)

Executes, resumes, or resolves a consequential operation through Once.

const result = await once.execute({
  operationId,
  provider: "my-provider",
  action
});

console.log(result.state);

The canonical execute response exposes state.

once.truth(operationId)

Reads the durable truth record for an operation.

const truth = await once.truth(operationId);

console.log(truth.ledger_state);

The canonical truth response exposes ledger_state.

Design principle

Do not repeat an irreversible action merely because the response was lost.

That is the failure mode Once is built to address.

License

MIT