On this page

Install the Python SDK

wexa is a single-module HTTP client for the Wexa gateway. No dependencies at all — it is built on urllib from the standard library — and it supports Python 3.9 and later.

Install

pip install wexa

The current published version on PyPI is 0.1.2. Confirm what you actually got:

import wexa
print(wexa.__version__)   # 0.1.2

Reaching a tool with no method on 0.1.2

An unrecognised tool name is sent to the wire verbatim rather than rejected, and the name-to-path transformation is the same mechanical one. So every tool the gateway registers is reachable from 0.1.2 through call():

fabric.call("delete-context", label="Customer", key="id", value="c-1")

With 0.1.2 installed from PyPI, that reached POST /v1/delete-context — the gateway's own access log recorded POST /v1/delete-context -> 404, so the 404 was the gateway saying the tool is not registered in that deployment, not the client failing to route it.

Configure

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 from GET /v1/connection-info itself. Trailing slashes are stripped for you.

Construct the client

from wexa import Fabric

fabric = Fabric()                                   # reads the two environment variables
# or
fabric = Fabric(workspace="https://fabric.wexa.ai", api_key=my_key)

Constructor options

OptionDefaultWhat it does
workspaceWEXA_WORKSPACEWorkspace URL.
api_keyWEXA_API_KEYBearer credential.
timeout70Seconds. Governed tool routes cap near 60s upstream, so 70 lets the server's own deadline fire first.
retries3Attempts when a call passes retry=True. Total, not extra.

Discovery happens in the constructor

Unlike the TypeScript client, the Python client performs the /v1/connection-info round trip inside __init__, so fabric.base is populated the moment the object exists:

fabric = Fabric()
print(fabric.base)      # http://localhost:7123/v1
print(fabric.issuer)    # http://localhost:7123

That means constructing a client is a network operation. Construct it once and reuse it; do not build one per request.

Verify the install

from wexa import Fabric

fabric = Fabric()
print(fabric.whoami())

With 0.1.2 installed from PyPI:

{'dept_id': 'dept_c10', 'org_id': 'org_c10', 'project_id': 'proj_c10',
 'role': 'OWNER', 'user_id': 'u_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']}

There is nothing to release. urlopen closes per request, so the client has no close() and needs none.

One SDK ported to the other

wexa and @wexa-fabric/sdk are deliberate ports of one another, not two independent libraries and not a stack. Neither wraps the other; both are thin HTTP clients for the same gateway. Python is the source of truth and TypeScript is the port, and they share one tool table, one set of server-bound arguments, one error taxonomy, one retry policy and one response envelope.

They are not byte-identical, and a handler moved between them needs four adjustments:

PythonTypeScript
Nothing reached the gatewayurllib's URLError, an OSError — not a WexaErrorTransportError, which is a WexaError
The 504 classTimeoutError_, underscored to dodge the builtinTimeoutError
Retry predicatesisinstance(e, RETRYABLE) / RESUME_RETRYABLEisRetryable(e) / isResumeRetryable(e)
DiscoveryIn __init__Deferred to the first call

Catch WexaError and OSError in Python. A lone except WexaError will not see a refused connection, and that is the failure most likely to happen in production.