On this page

run-model

Send a prompt to one of this organization's AI models and get the answer back, with the tokens consumed, the cost and the latency. model takes any id list-models returns and is optional: omit it to run the organization's default. Every response echoes the model that actually ran and a source saying why it was chosen.

What it is called on each surface

The wire name is run-model everywhere: it is what the Wexa MCP server advertises, the REST path is POST /v1/run-model, and each SDK exposes it under its own language's naming convention.

SurfaceName
Wexa MCP serverrun-model
REST APIPOST /v1/run-model
TypeScript SDKfabric.runModel()
Python SDKfabric.run_model()

Arguments

Send either prompt or messages. Everything else is optional.

ArgumentTypeRequiredNotes
promptstringOne ofThe prompt, treated as a single user message. Ignored when messages is set.
messagesarrayOne ofA conversation as {role, content} pairs. Roles are system, user, assistant. Wins over prompt.
modelstringOptionalAny id list-models returns. Omit to run the organization's default.
max_tokensintegerOptionalCeiling on the tokens generated. Defaults to 512.
temperaturenumberOptional0 to 2. Defaults to 0.2.
top_pnumberOptionalNucleus sampling, 0 to 1.
stoparrayOptionalUp to four sequences that end generation.
seedintegerOptionalBest-effort determinism, where the provider supports it.
response_formatobjectOptionale.g. {"type": "json_object"}.
streambooleanOptionalNot supported. true is refused — see no streaming.

A value outside its range is refused, not clamped. Silently adjusting a number you chose would hand you a call you did not ask for.

project_id, projectID, organization_id and executed_by are not arguments you pass: the platform binds all four from the credential you authenticated with, and both SDKs refuse them before the request leaves your process — see server-bound arguments.

Arguments bound to the model

run-model refuses a further set, bound to the model rather than to your credential: endpoint, api_base, api_version, secret_ref, secret_param, api_key, provider and extra_params. Wexa fills all of them from the model's own registry entry, and both SDKs refuse them before the request leaves your process.

This is deliberate rather than incidental. The provider host is checked against your organization's allow-list at call time, not when the model was registered, so withdrawing permission for a host immediately blocks a model registered while it was still permitted. Provider pass-through is administered per model and checked before it reaches execution. A per-request version of either would be an unchecked route into provider routing and credential placement. Your provider credential is resolved at the point of execution and never reaches you.

Which models you can name

run-model accepts exactly the identifiers list-models returns — a registry id from settable, or a composite from available. Discovery and invocation are one story: list, then call. There is no second naming scheme.

A free-text provider name such as gpt-4o is refused. A bare provider name has no credential to resolve and no host to check, and two registered entries may share a provider model id with different credentials, so there is no correct one to pick. See which identifier goes where.

What it returns

The three surfaces wrap this differently, and code written against one will not read another correctly — see return shape.

A real response, captured from a live call to run-model:

{
  "lifecycle_id": "qlc_000023",
  "result": {
    "output": "pong",
    "model": "mdl_bx_anthropic-claude-haiku-4-5-20251001-v1_28ccc24bfca8",
    "source": "requested",
    "tokens": 28,
    "cost_usd": 0.000028,
    "latency_ms": 621
  }
}

model is the model that actually ran, not the one you asked for. source says why it was chosen:

sourceMeaning
requestedYou named this model
organization defaultYou named none, and this is the default the organization chose
platform defaultYou named none and the organization has chosen none, so a platform fallback ran

Read both before attributing a charge. A platform default you did not expect is the signal that nobody has chosen an organization default. On an enterprise deployment the call is refused outright in that state rather than routed to a fallback, so no work runs on a model nobody selected.

Calling it

The same call on all four surfaces. Pick a tab once and every code block in the documentation follows it.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "run-model",
    "arguments": {
      "model": "mdl_bx_anthropic-claude-haiku-4-5-20251001-v1_28ccc24bfca8",
      "prompt": "Summarize Q3 in one line."
    }
  }
}

A conversation

messages carries a system message and as many turns as you like.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "run-model",
    "arguments": {
      "model": "mdl_bx_anthropic-claude-haiku-4-5-20251001-v1_28ccc24bfca8",
      "messages": [
        { "role": "system", "content": "Answer in one sentence." },
        { "role": "user", "content": "What changed in Q3?" }
      ],
      "temperature": 0.2
    }
  }
}

There is no tool role, and no tool calling. Call run-agent when you want an agent's tools.

Each call is independent: Wexa keeps no conversation for you. Send the turns you want the model to see.

Errors

Both SDKs raise the same typed errors, chosen from the gateway's own error string first and its HTTP status second. run-model checks the fabric:model.run grant, and reaches the seven classes every tool reaches — listed under the common set. These are the ones specific to it:

CodeStatusRaised whenRetry?
S8:model-not-found404No such model in this organizationNo — fix the id
S8:model-forbidden403The model's host is no longer permittedNo — an administrator must act
S8:model-invalid-parameters422A parameter was outside its range, or is not yours to setNo — fix the request
S8:model-call-limited429This key's own model-call budget is fullYes, shortly
S8:model-rate-limited429The provider rate-limited the callYes, with backoff
S8:model-upstream-error502The provider failedYes

The two 429s are separate on purpose: one means you are asking Wexa for too much at once, the other means your provider is. The provider's own message is passed through, because it is what makes a credential or access failure diagnosable.

Both SDKs classify these for you and stop retrying the terminal ones, so a revoked model does not cost you a full backoff cycle on every call.

When the model registry is briefly unreachable

Calls naming a composite keep working — a registry interruption is not a total model-calling outage. Calls naming a registry id fail with a reason that says the registry could not be read, deliberately not with S8:model-not-found, which is terminal and would read as a typo. Retry those.

list-models reports the same condition, so you can tell a short model list from a truncated one.

Limits and billing

Model calls are limited separately from ordinary API calls, and by how many are in flight rather than by how many per minute — a long generation and a listing are not the same load. Exhausting your model-call budget does not block your other calls, and exhausting the ordinary budget does not block your model calls.

Every call is metered against the API key that made it, so per-key spend answers "which of my integrations is spending this" before the invoice does. The spend draws down the same balance as every other metered use; there is not a second one to watch. The response's tokens and cost_usd let you meter yourself without waiting for a billing report.

No streaming

run-model does not stream. stream: true is refused with a clear message rather than served the whole answer framed as a single chunk.

A stream that does not stream invites interfaces built against timing and chunk boundaries that would change the moment real streaming arrived, with no way to tell who depended on the old behaviour. An honest refusal is a smaller promise than one that has to be kept.

Governance

Every call to run-model runs through the same ten-stage lifecycle as every other Wexa tool: the credential is resolved to a scope, the fabric:model.run grant is checked, quota is drawn down, the arguments are validated, policy rules are evaluated, the call is executed, the result is shaped and redacted, and an audit record is written. The lifecycle_id in the response is the handle to that record.

run-model is not marked consequential, so it does not enter the approval workflow. It does spend money, as running an agent does, but a human approval per model call would make the capability unusable in a request path; spend is controlled by metering and the separate rate-limit bucket instead.

fabric:model.run is its own grant, deliberately not fabric:model.write: reading or editing a model's configuration and spending money through it are different privileges, so an application key that calls models cannot reconfigure the registry.

See also

Models for how a model is chosen and what platform-provided versus bring-your-own means for the bill, list-models, set-model, the tool index, and errors.