On this page

Install the TypeScript SDK

@wexa-fabric/sdk is a thin HTTP client for the Wexa gateway. Zero runtime dependencies, ESM and CommonJS, Node 18 or later, and it also runs in browsers and edge runtimes.

Install

npm install @wexa-fabric/sdk

The current published version is 0.2.3; the Wexa repository carries 0.3.0, which adds the schedule, trigger and Data Table methods. The package exports its own version as VERSION, and that constant is asserted equal to the one in package.json at build time, so what the client reports is what you installed:

import { VERSION } from '@wexa-fabric/sdk'
console.log(VERSION)   // 0.2.3

Configure

Two values, and the client reads both from the environment when you do not pass them:

export WEXA_WORKSPACE=https://fabric.wexa.ai    # your workspace URL
export WEXA_API_KEY=fab_sk_…                    # any bearer credential the gateway accepts

WEXA_WORKSPACE is the workspace URL, not the API base. The client discovers the API base itself from GET /v1/connection-info, which means the gateway decides its own address and moving it needs no change on your side. Trailing slashes are stripped for you.

WEXA_API_KEY takes any bearer credential — a fab_sk_… API key or an OAuth 2.1 access token. See REST authentication for which kind you want.

Construct the client

import { Fabric } from '@wexa-fabric/sdk'

const fabric = new Fabric()                              // reads the two environment variables
// or
const fabric = new Fabric({
  workspace: 'https://fabric.wexa.ai',
  apiKey: process.env.MY_KEY,
})

An explicitly-passed empty string falls through to the environment variable, and an environment variable set to the empty string counts as absent — so a half-configured deployment fails the same way as an unconfigured one rather than silently pointing at nothing.

Constructor options

OptionDefaultWhat it does
workspaceWEXA_WORKSPACEWorkspace URL.
apiKeyWEXA_API_KEYBearer credential.
timeout70Seconds. Governed tool routes cap near 60s upstream, so 70 leaves the server's own deadline to fire first.
retries3Attempts when a call passes retry: true. Total, not extra.
fetchglobal fetchAn injected fetch, for tests, a proxy agent, or connection pooling.

Discovery is deferred

fabric.base is undefined until the first request. A TypeScript constructor cannot await, so the /v1/connection-info round trip is deferred to the first call and memoised — including its rejection, so a bad workspace URL does not re-fetch on every call.

const fabric = new Fabric()
console.log(fabric.base)          // undefined
await fabric.whoami()
console.log(fabric.base)          // http://localhost:7123/v1
console.log(fabric.issuer)        // http://localhost:7123

This is the one structural difference from the Python client, which performs discovery inside its constructor. Credential validation happens synchronously in both.

Verify the install

import { Fabric } from '@wexa-fabric/sdk'

const fabric = new Fabric()
console.log(await fabric.whoami())
fabric.close()

That prints:

{
  "user_id": "u_c10", "role": "OWNER",
  "org_id": "org_c10", "dept_id": "dept_c10", "project_id": "proj_c10",
  "grants": ["fabric:query.read", "fabric:docs.read", "fabric:ontology.write",
             "fabric:orchestrate.read", "fabric:orchestrate.write", "fabric:agent.run",
             "fabric:skill.write", "fabric:model.write"]
}

If that works, the workspace URL resolves, discovery succeeded, and your credential is accepted.

Releasing the client

close() aborts any in-flight request and any approval poll. Calling it twice is a no-op, and the client cannot be reused afterwards. It is also wired to Symbol.asyncDispose:

await using fabric = new Fabric()
// released at the end of the scope

Python has no equivalent, because urlopen closes per request and there is nothing to release.

One SDK ported to the other

The TypeScript and Python clients are deliberate ports of one another, not two independent libraries and not a stack — neither wraps the other, and the TypeScript package has no dependency on Python. They share one tool table, one set of server-bound arguments, one error taxonomy, one retry policy and one response envelope, so an integration written against either reads the same way.

They are not byte-identical, and pretending otherwise would cost you a handler. The documented differences are listed on error handling and Python SDK — install.