Skip to main content

Documentation Index

Fetch the complete documentation index at: https://wuweism.com/llms.txt

Use this file to discover all available pages before exploring further.

Send a causal question to the Wu-Weism reasoning engine. The response is streamed as a sequence of Server-Sent Events (SSE), allowing you to display incremental progress — domain classification, SCM loading, intervention evaluation, and answer text — as they complete.
This endpoint uses text/event-stream. You must read the response body as a stream and parse individual SSE frames. Standard fetch with a body reader works in all modern environments.

Endpoint

POST /api/causal-chat

Authentication

Authentication is required on every request. Unauthenticated requests return 401 Unauthorized.
Include either a session cookie (set automatically after sign-in) or a Bearer token in the Authorization header:
Authorization: Bearer <token>

Request

Content-Type: application/json

Headers

Authorization
string
required
Bearer token for API authentication. Format: Bearer <token>.
Content-Type
string
required
Must be application/json.
X-BYOK-Api-Key
string
Bring-your-own-key: pass your own API key for the selected AI provider. When present, this key is forwarded to the upstream provider instead of Wu-Weism’s managed key. Required if your account is configured for BYOK mode.

Body parameters

question
string
required
The causal question to analyze. Should be phrased as a causal query — for example, “Does X causally affect Y?” or “What would happen if we intervene on Z?”. Cannot be empty.
messages
object[]
Previous conversation turns for multi-turn sessions. Each element must include role and content.
sessionId
string
UUID identifying a persistent session. When provided, the server associates this request with the session’s stored history and SCM context. If omitted, the request is treated as stateless.
intervention
object
Do-calculus intervention specification for Rung 2 (interventional) analysis. Requires operatorMode to be set to "intervene".
providerId
string
default:"anthropic"
AI provider to use for language model inference. Accepted values: "anthropic", "openai", "gemini". Defaults to "anthropic" when omitted.
model
string
Specific model ID within the selected provider — for example, "claude-opus-4-5" or "gpt-4o". When omitted, the provider’s default model is used. Must be a valid model for the chosen providerId; mismatches return a 400 error.
operatorMode
string
Activates Rung 2 analysis mode. Accepted values:
  • "intervene" — evaluate the causal effect of a do(·) intervention.
  • "audit" — audit the causal graph for identifiability and policy compliance without applying an intervention.
attachments
object[]
PDF documents to include as context for the analysis. Each attachment is base64-encoded.
modelKey
string
Override the automatic domain classifier and load a specific SCM model by its key. Useful when you know exactly which causal model applies to your question. When omitted, the domain is classified automatically from question.
traceId
string
Trace identifier for counterfactual provenance. Associates this request with a prior causal trace for counterfactual reasoning or audit replay.

Response

Content-Type: text/event-stream The response body is a stream of SSE frames. Each frame has the form:
event: <event_name>
data: <json_payload>

Events arrive in roughly the order listed below, though not all events are emitted on every request — for example, intervention_gate and intervention_effect only appear when an intervention is specified.

SSE events

thinking
object
Emitted periodically during processing to indicate progress. Display to users as a loading indicator.
domain_classified
object
The domain classifier has identified the subject area of the question.
scm_loaded
object
The Structural Causal Model for the identified domain has been loaded.
intervention_gate
object
Gate evaluation result for the requested intervention. Only emitted when operatorMode is "intervene" or "audit".
intervention_effect
object
The computed causal effect of the intervention. Only emitted when operatorMode is "intervene" and the gate allows the operation.
answer_chunk
object
A chunk of the generated answer text. These events are emitted incrementally — concatenate text values in order to reconstruct the full response.
model_fallback
object
The requested model was unavailable and a substitute was used.
web_grounding_completed
object
Web sources were retrieved and used to ground the causal analysis.
common_sense_policy
object
Safety policy evaluation result.
complete
object
Final event indicating the stream has ended successfully.

Error responses

Errors are returned as standard JSON responses before the stream is opened.
StatusBodyDescription
401Missing or invalid authentication credentials.
400{"error": "Question is required"}The question field was empty or missing.
400{"error": "Invalid providerId"}providerId is not one of "anthropic", "openai", "gemini".
400{"error": "Invalid model for selected provider"}model is not valid for the specified providerId.
500{"error": "Configuration Error: Missing API key for provider '...'"}The selected provider has no configured API key. Pass your key via X-BYOK-Api-Key or contact support.

Examples

Basic question

const response = await fetch('https://wuweism.com/api/causal-chat', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer <token>',
  },
  body: JSON.stringify({
    question: 'Does cortisol exposure causally increase hippocampal volume reduction?',
    sessionId: 'my-session-uuid',
    providerId: 'anthropic',
  }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const text = decoder.decode(value);
  // Each SSE frame has the form:
  // "event: answer_chunk\ndata: {"text":"..."}\n\n"
  console.log(text);
}

Do-calculus intervention

Use operatorMode: "intervene" together with the intervention object to evaluate a causal effect under a hypothetical manipulation.
{
  "question": "What would happen if we intervene to reduce cortisol?",
  "sessionId": "my-session-uuid",
  "providerId": "anthropic",
  "operatorMode": "intervene",
  "intervention": {
    "node_id": "cortisol_level",
    "value": 0.3,
    "outcome_var": "hippocampal_volume",
    "known_confounders": ["stress_exposure", "age"],
    "adjustment_set": ["stress_exposure"]
  }
}

Parsing SSE events

A minimal parser for the SSE stream in JavaScript:
function parseSSEFrame(raw) {
  const lines = raw.split('\n');
  let eventName = '';
  let dataLine = '';

  for (const line of lines) {
    if (line.startsWith('event: ')) eventName = line.slice(7).trim();
    if (line.startsWith('data: ')) dataLine = line.slice(6).trim();
  }

  if (!eventName || !dataLine) return null;

  return { event: eventName, data: JSON.parse(dataLine) };
}

// Usage inside the reader loop:
const frame = parseSSEFrame(decoder.decode(value));
if (frame?.event === 'answer_chunk') {
  process.stdout.write(frame.data.text);
}
if (frame?.event === 'complete') {
  console.log('\nStream finished.');
}
SSE frames are separated by a blank line (\n\n). A single read() call may return multiple frames or a partial frame depending on network conditions. For production use, buffer incoming chunks and split on \n\n before parsing.