On this page

SDKs and APIs

How every tool call works

Every Wexa tool is the same tool on four surfaces: the Wexa MCP server, the REST API, the TypeScript SDK and the Python SDK. Each tool page shows only what is specific to that tool. Everything else is here, once.

Naming on each surface

A tool has one wire name, written in lowercase with hyphens: run-agent. Each surface spells it its own way.

SurfaceName for run-agentRule
Wexa MCP serverrun-agentThe wire name.
REST APIPOST /v1/run-agentPOST https://fabric.wexa.ai/v1/ plus the wire name.
TypeScript SDKfabric.runAgent()The wire name in camel case.
Python SDKfabric.run_agent()The wire name with underscores.

Argument names are the wire names on every surface; only method names change.

More naming

create-ontology is the one tool whose REST route differs: both SDKs post to /v1/ontology, and /v1/create-ontology answers too.

Both SDKs also have fabric.call(name, ...), which takes either spelling, run-agent or run_agent.

Return shape

Every tool returns the same data on every surface, wrapped differently on each. Code ported by hand between the two SDKs gets undefined rather than an error, because the id names differ.

SurfaceWhat you get
REST API{"lifecycle_id": "qlc_...", "result": { ... }}. Read result.
TypeScript SDKThe result, already unwrapped: const result = await fabric.runAgent({...}). There is no .result to read: result.result is undefined. The ids are non-enumerable properties named lifecycleId and traceId, so Object.keys() and JSON.stringify() omit them.
Python SDKThe result, already unwrapped. The ids are attributes named lifecycle_id and trace_id.
Wexa MCP server{"content": [{"type": "text", "text": "..."}], "isError": false}, where text is the REST body as a JSON string. Parse it.

Lifecycle and governance

Every call passes the same stages, in order, and each is recorded: authenticate, resolve scope, rate and quota, validate, policy, approval, dry run, execute, post-process, record. A call that fails a stage stops there. The lifecycle_id in the response is the handle to that call's record. Keep it, and quote it when asking why a call was allowed, refused or held.

A tool that changes something is consequential. It is audited in full, and a policy rule may hold it for a person to approve. A tool page shows a "Can be held for approval" badge under its title when the write gate can hold its tool. A held call returns status 202 on REST, and the SDKs raise ApprovalRequired, which carries the approval id. The Wexa MCP server returns a non-error result (isError: false) holding the pending-approval payload instead. When a project admin turns on the project's write gate, an API key or an SDK session also has its consequential writes held. The write gate never holds a read, but a policy rule may still hold or refuse any tool, and every call uses quota.

To wait for the decision and carry on, pass wait_for_approval=True in Python or waitForApproval: true in TypeScript. The wait is 600 seconds by default.

The platform fills in four arguments from your credential: project_id, projectID, organization_id and executed_by. They are server-bound arguments. Both SDKs refuse them before the request leaves your process. See what scope a call carries.

Each tool page names the grant its tool needs. For the stages in full, see lifecycle and audit.

Errors

Both SDKs raise the same typed errors, all extending WexaError. They choose the class from the gateway's error string, then the HTTP status, so one refusal is the same class in both. In Python the timeout class is TimeoutError_. A parameter's rule sits in its row on a tool page; a refusal tied to no parameter sits in its collapsed Errors block.

ClassStatusRaised when
AuthError401Missing, malformed or revoked credential.
ForbiddenError403The credential lacks the tool's grant or the project's scope.
PolicyDenied403A policy rule refused the call. Extends ForbiddenError.
ValidationError400 / 422A value breaks its parameter's rule, or the body is malformed.
ApprovalRequired202A person must approve the call first.
ApprovalError403The resume token is bad, expired or spent.
QuotaExceeded429Over the request window or credit balance.
NotFound404An id or name matches nothing in your project.
ConflictError409The change collides with current state.
UpstreamError502A downstream service refused or was unreachable.
TimeoutError504An upstream deadline was exceeded. Extends UpstreamError.
ConfigurationError502 / 503The tool is not enabled in your deployment.
TransportErrornoneNo response arrived. TypeScript only: Python raises OSError, which is not a WexaError.

These are the defaults for every tool, so a tool page does not restate them. It names any exception in a parameter's row or its Errors block:

  • An id from another project is NotFound (404). It reads as an id that never existed.
  • A value that breaks its parameter row's rule is ValidationError (422): missing, empty, the wrong type or format, out of range.
  • A call that the write gate or a policy rule holds is not a failure. It raises ApprovalRequired (202 on REST). The "Can be held for approval" badge marks the tools the write gate can hold; a policy rule may hold any tool, for example a read of classified data. See lifecycle and governance and policy and approvals.

On REST you get the status and an error and error_description pair. On the Wexa MCP server a refusal comes back as isError: true, with the stage and message in content[0].text. An unknown tool name is a JSON-RPC error instead.

Retries are off unless you pass retry. Only UpstreamError (so TimeoutError too) and QuotaExceeded are retried; ConfigurationError never is. The gateway's Retry-After is honoured. For the full set of classes and what to retry, see errors and retries.

Identifiers

Wexa issues opaque ids and checks their format before a tool runs, so an id in the wrong argument is refused. Read the id from the output field that names it and pass it unchanged. Which identifier goes where covers the two cases that need care.

Find a tool

Every tool has a page in the sidebar, except the documentation tool docs. The tools array of GET /v1/connection-info lists the tools your deployment registers; see discovery.

Sign-in calls are not governed tools

login, refresh-session and logout sign a Wexa user in through an SDK. They run before any tool call, on the REST API and both SDKs only, and they do not pass the lifecycle above. See login, refresh-session and logout.

See also