npm.io
0.1.1 • Published 10h ago

@eggai-sdk/core

Licence
Apache-2.0
Version
0.1.1
Deps
0
Size
118 kB
Vulns
0
Weekly
0

eggai — the EGGai Node.js SDK

Four SDKs, one behaviour model. This package is the official Node.js client for api.eggai.tech: offer optimization, lead generation, survey response and assortment optimization over EGGai-v1, a Large Behavior Model grounded in real till history.

Zero runtime dependencies — written in TypeScript, compiled to ESM on the global fetch, declarations included. Node 18+.

npm install @eggai-sdk/core

Requirements

Floor Why
Node 18.0+ global fetch (18.0) and AbortSignal.timeout (17.3) — no HTTP dependency, no polyfill
TypeScript 4.7+ declarations resolve through the exports map, so moduleResolution must be node16, nodenext or bundler

This package is ESM-only"type": "module", no CommonJS build:

import { EggAI } from '@eggai-sdk/core';            // any supported Node
const { EggAI } = await import('@eggai-sdk/core');  // from CommonJS

require('@eggai-sdk/core') resolves only on Node 22.12+ / 20.19+, where require() of ESM landed; on earlier 18.x and 20.x it throws ERR_REQUIRE_ESM — use the dynamic import() above.

Authenticate

Every client takes a workspace API key (issued in the EGGai app under Settings → API keys). Pass it directly, or set EGGAI_API_KEY once:

export EGGAI_API_KEY="pk_live_..."

Practice keys work everywhere live keys do, but are capped per job so you can integrate without spending real volume. EGGAI_BASE_URL overrides the endpoint when you are pointed at staging.

The four products

import { EggAI } from '@eggai-sdk/core';

const client = new EggAI();          // reads EGGAI_API_KEY

// 1 · Offer Optimization — what is the least this customer would accept?
const terms = await client.offers.cheapestAccepted({
  customer:   'c_8813',
  profile:    'shops fortnightly, small baskets, coupon-led',
  offer:      'Fresh Picks Weekend — 15% off produce, min spend 500',
  guidelines: 'discount caps at 12%, min spend above 300.',
});
terms.text;       // "8% off produce, min spend 349"
terms.tagline;    // "Weekend Picks"
terms.changed;    // ["discount", "min_spend", "tagline"]
terms.objection;  // "threshold above my usual basket"

// 2 · Lead Generation — which of these people is worth the call?
const ranked = await client.leads.rank(
  { c_8813: 'fortnightly, coupon-led', c_2291: 'weekly family shop' },
  {
    offer:       'Fresh Picks Weekend — 15% off produce',
    guidelines:  'hold the 15%, the aisle may change',
    tailorOffer: true,
  },
);
ranked.at(0).score;   // 0.71
ranked.at(0).reason;  // "buys dairy most weeks, produce rarely"
ranked.above(0.5);    // the slice worth calling

// 3 · Survey Response (preview) — what would a panel of your customers say?
const result = await client.surveys.ask(
  'Would you switch to our own-brand line?',
  {
    options: ['Definitely', 'Maybe', 'No'],
    panel:   'shoppers aged 18-55 who buy fresh produce most weeks',
    n:       150,
  },
);
result.distribution;         // { Definitely: 0.21, Maybe: 0.44, No: 0.35 }
result.crosstab('segment');  // the same spread, split by trait

// 4 · Assortment Optimization — who follows the shelf, and who walks?
const impact = await client.assortment.impact(customers, {
  scenario: {
    kind:      'delist',
    category:  'chilled juice',
    change:    'Tropicana Orange 1L 119',
    remaining: 'own-label 1L 79 · Malee 1L 95',
  },
});
impact.retained;            // 0.91 of category spend kept
impact.counts;              // { switches: 214, leaves_store: 6 }
impact.watchlist;           // who walks, and the basket at stake
impact.rows[0].substitute;  // where the demand lands

Or import a product directly, as the product pages show:

import { OfferOptimizer } from '@eggai-sdk/core';
const terms = await new OfferOptimizer(apiKey).cheapestAccepted({ ... });

Jobs, streaming, results

Every batch call is a job on EGGai's servers. wait: false hands you the job instead of the result:

const job = await client.leads.rank(customers, { offer, wait: false });
for await (const ev of job.stream()) {      // progress / live / twin events
  console.log(ev.stage ?? ev.text);
}
const ranked = new RankedLeads(await job.resultRows());

client.assortment.preview(panel, { scenario }) answers sampled what-ifs synchronously (≤64 rows, nothing persisted). client.score(rows) returns bare probabilities for up to 64 rows. client.usage('2026-08') is the same metering rollup billing reads.

Errors

Everything thrown on purpose subclasses EggAIError and carries the server's own message: AuthenticationError, InvalidRequestError, RateLimitError, FeatureNotEnabledError (Survey Response is preview, enabled per workspace), JobFailedError (with .job), APIError.

Docs

Full documentation: docs.eggai.tech — concepts, CSV schemas, the REST reference underneath this client, and the studies behind each product.

Keywords