> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modulex.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# ModuleX glossary of terms

> The canonical ModuleX terminology reference: definitions for credits, the DenialEnvelope, BYOK vs managed usage, knowledge bases, the nine node types, HITL, the three run-id identities, and the deprecated names to avoid.

export const MediaEmbed = ({id, type = 'screenshot', caption = '', ext, ratio = '16 / 9'}) => {
  const isVideo = type === 'video' || type === 'app_video';
  const resolvedExt = ext || (isVideo ? 'mp4' : type === 'screenshot' ? 'webp' : 'svg');
  const src = 'https://media.modulex.dev/' + id + '.' + resolvedExt;
  const [status, setStatus] = useState('loading');
  const [isDev, setIsDev] = useState(false);
  const [inView, setInView] = useState(false);
  const boxRef = useRef(null);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const h = window.location.hostname;
    setIsDev(h === 'localhost' || h === '127.0.0.1' || h.endsWith('.mintlify.app'));
  }, []);
  useEffect(() => {
    if (inView) return;
    if (typeof IntersectionObserver === 'undefined') {
      setInView(true);
      return;
    }
    const el = boxRef.current;
    if (!el) return;
    const io = new IntersectionObserver(entries => {
      if (entries.some(e => e.isIntersecting)) {
        setInView(true);
        io.disconnect();
      }
    }, {
      rootMargin: '300px'
    });
    io.observe(el);
    return () => io.disconnect();
  }, [inView]);
  if (status === 'missing') {
    if (!isDev) return null;
    return <div style={{
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      gap: '0.4rem',
      padding: '1rem 1.25rem',
      margin: '1.25rem 0',
      width: '100%',
      aspectRatio: ratio,
      boxSizing: 'border-box',
      border: '1px dashed rgba(128,128,128,0.45)',
      borderRadius: '0.75rem',
      background: 'rgba(128,128,128,0.06)',
      color: 'currentColor',
      fontSize: '0.85rem',
      lineHeight: 1.45
    }}>
        <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      opacity: 0.75
    }}>
          <span aria-hidden="true">🎬</span>
          <code style={{
      fontSize: '0.75rem'
    }}>{id}</code>
          <span style={{
      fontSize: '0.65rem',
      textTransform: 'uppercase',
      letterSpacing: '0.04em',
      padding: '0.1rem 0.4rem',
      borderRadius: '0.4rem',
      background: 'rgba(128,128,128,0.18)'
    }}>
            {type}
          </span>
        </div>
        <div style={{
      opacity: 0.9
    }}>{caption || 'Media not uploaded yet.'}</div>
        <div style={{
      fontSize: '0.7rem',
      opacity: 0.5
    }}>
          Upload to R2 as <code>{id}.{resolvedExt}</code> — preview only, hidden in production.
        </div>
      </div>;
  }
  const mediaStyle = {
    display: status === 'loaded' ? 'block' : 'none',
    width: '100%',
    height: 'auto',
    borderRadius: '0.75rem'
  };
  const media = isVideo ? <video src={inView ? src : undefined} autoPlay loop muted playsInline preload="metadata" onLoadedData={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} /> : <img src={inView ? src : undefined} alt={caption} onLoad={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} />;
  return <figure style={{
    margin: '1.25rem 0'
  }}>
      <div ref={boxRef} style={status === 'loaded' ? {
    width: '100%'
  } : {
    width: '100%',
    aspectRatio: ratio,
    borderRadius: '0.75rem',
    background: 'rgba(128,128,128,0.06)'
  }}>
        {media}
      </div>
      {status === 'loaded' && caption ? <figcaption style={{
    marginTop: '0.5rem',
    textAlign: 'center',
    fontSize: '0.85rem',
    opacity: 0.7
  }}>
          {caption}
        </figcaption> : null}
    </figure>;
};

This page is the single source of truth for ModuleX naming. Where the product, the API,
the SDKs, and the codebase use different spellings for the same idea, the **canonical**
term here is the one the documentation standardizes on, and the **avoid** entries call out
the deprecated or wrong names you may still see in older code, screenshots, or community
posts.

Terms are listed A to Z. Each entry links to the page that explains the concept in full,
so use this glossary to find the right word and the canonical page behind it.

<MediaEmbed id="MX-MEDIA-1310" type="image" caption={"A one-screen \"naming map\" that groups the canonical ModuleX terms into their subsystems (engine, agents, knowledge, integrations, auth, billing, errors, realtime) so a reader can place a term at a glance."} />

## Terms you should not use

These names are deprecated, wrong, or refer to a path that does not work. They appear in
older code and stale snapshots; do not use them in your own integrations, requests, or
documentation.

<Warning>
  Every term in this section is an **anti-pattern**. The canonical replacement is given in
  each row, with the page that documents the live behavior.
</Warning>

| Avoid                                                               | Why                                                                                                                                                                                                | Use instead                                                                                                                                                    |
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `member` role                                                       | The `member` organization role is **retired** (deprecated 2026-06-20) and is not a current first-class role. Composer, Assistant, schedules, and managed knowledge all require `owner` or `admin`. | The `owner` and `admin` roles — see [Roles & permissions](/security/roles-permissions) and [Organizations, roles & membership](/concepts/organizations-roles). |
| `X-Authorization` header                                            | This header is not used for authentication. Both SDKs send `Authorization: Bearer`.                                                                                                                | `Authorization: Bearer mx_live_…` (or the alternative `X-API-KEY`) plus `X-Organization-ID` — see [Authentication](/api-reference/authentication).             |
| `X-Organization-Id` (lowercase `d`)                                 | The org-context header name is case-significant in code; the canonical spelling capitalizes `ID`.                                                                                                  | `X-Organization-ID` — see [Org context & X-Organization-ID](/security/org-context).                                                                            |
| `pip install modulex-integrations[all]` / `[github,slack]` extras   | Per-tool `pip` extras are not published.                                                                                                                                                           | Install the core package and add each tool's SDK as needed — see [Installing & using integrations](/integrations/install).                                     |
| `[ghost]` integrations `canvas`, `cogmento`, `help_scout`, `medium` | These names are not real ModuleX integrations.                                                                                                                                                     | Browse the live catalog of 175 integrations — see [Integration catalog](/integrations/catalog).                                                                |
| "136 integrations"                                                  | A stale count from an out-of-date vendored manifest.                                                                                                                                               | **175 integrations** — see [Integrations overview](/integrations/overview).                                                                                    |
| Legacy LLM-only `POST /workflows/run` ("agentic mode")              | The legacy LLM-only request mode on the run endpoint now returns **HTTP 410 Gone**.                                                                                                                | Use the [Assistant](/concepts/assistant) (`assistant.chat`) instead — see [How the Assistant works](/assistant/how-it-works).                                  |

## A

<ParamField path="ActionDefinition" type="manifest type">
  One callable action declared in an integration's `manifest.py`. The action's
  **output shape is not declared here** — it is derived from the `@tool` function's
  return annotation. Action names match `^[a-z][a-z0-9_]*$`. See
  [Manifest & schema contract](/integrations/building/manifest-schema).
</ParamField>

<ParamField path="admin (role)" type="org role">
  A live [organization](#organization-org) role with elevated permissions. Together with
  `owner`, it is one of the two current roles, and it is required to use Composer, the
  Assistant, schedules, and managed knowledge. See
  [Roles & permissions](/security/roles-permissions).
</ParamField>

<ParamField path="agent node" type="node type">
  One of the [nine node types](#node-type). An autonomous step that can call tools and
  loop until it decides it is done. See [Agent node](/workflow-builder/nodes/agent).
</ParamField>

<ParamField path="AI Composer" type="product surface">
  The canonical name for the text-to-workflow agent: it turns a plain-English description
  into a complete, editable [workflow graph](#workflow-workflow-graph). The backend router
  and surface are `/composer`.

  <Warning>
    Drift: marketing also uses "AI Workflow Composer" and "text-to-workflow composer". The
    documentation standardizes on **AI Composer**.
  </Warning>

  See [AI Composer](/concepts/ai-composer) and [AI Composer in the builder](/workflow-builder/composer).
</ParamField>

<ParamField path="API key" type="auth credential">
  A user API key with the prefix **`mx_live_`**. Send it as `Authorization: Bearer mx_live_…`
  or, alternatively, as `X-API-KEY: mx_live_…`. Any bearer token that does **not** start
  with `mx_live_` is treated as a [Clerk JWT](#clerk-jwt). See
  [Authentication](/api-reference/authentication) and [Auth model: JWT vs API key](/security/authentication).
</ParamField>

<ParamField path="approval" type="agent capability">
  The point at which an agent stops before a sensitive action and waits for a person to
  approve it. Approval is enforced by the tool-execution gating policy and is a
  [human-in-the-loop](#hitl-human-in-the-loop) interaction. See
  [Human-in-the-loop](/assistant/human-in-the-loop).
</ParamField>

<ParamField path="Assistant" type="product surface">
  The workflow-independent agentic chat: it searches your connected tools, decides next
  steps, drafts outputs, calls tools, and pauses for approval. It has **no** workflow-editing
  tools (that is the [AI Composer](#ai-composer)). The backend router and profile are
  `assistant`.

  <Note>
    The home page tile calls this "Deep Agentic Assistant". The documentation standardizes on
    **Assistant**.
  </Note>

  See [Assistant overview](/assistant/overview) and [Assistant](/concepts/assistant).
</ParamField>

<ParamField path="AuthSchema" type="manifest type">
  The discriminated union (on [`auth_type`](#auth_type)) of the six auth variants an
  integration [manifest](#integrationmanifest) may expose. See
  [Manifest & schema contract](/integrations/building/manifest-schema).
</ParamField>

<ParamField path="auth_type" type="enum">
  The auth-variant discriminator in a manifest: one of `oauth2`, `bearer_token`, `api_key`,
  `modulex_key`, `custom`, `internal` (**six** schema variants).

  <Warning>
    Drift: the backend `CHECK` constraint allows **seven** values (it also accepts the legacy
    `bearer`), and `internal` is defined but unused in the catalog. Author manifests against
    the six canonical variants. See [Authentication & credentials](/integrations/authentication).
  </Warning>
</ParamField>

## B

<ParamField path="BillingDenied" type="exception">
  The exception the credit [gate](#gate-gate_run_admission) raises when a managed call is
  denied. It carries a [`DenialEnvelope`](#denialenvelope), an HTTP status, and headers, and
  is serialized to the flat envelope shape (no `detail` wrapper). See
  [Errors & status codes](/api-reference/errors) and [Usage gating & limits](/billing/usage-gating).
</ParamField>

<ParamField path="BYOK (Bring Your Own Key)" type="usage mode">
  Connecting your own model, tool, or vector-store provider accounts so that usage is billed
  directly by that provider, with no ModuleX markup. **BYOK usage is not metered in
  [credits](#credit)** — it is tracked for analytics only. There is no `feature.byok`
  entitlement; BYOK is ungated.

  This is the alternative to [ModuleX-managed usage](#modulex-managed-usage-managed-models).
  See [LLM providers](/integrations/llm-providers/overview), [External knowledge providers](/platform/knowledge/external-providers),
  and [Credits & metering](/billing/credits).
</ParamField>

## C

<ParamField path="checkpointer / thread" type="engine">
  Checkpoint-thread state persistence. A **thread** is identified by its `thread_id`;
  see [thread\_id](#thread_id). See [Workflow engine & nodes](/concepts/workflow-engine).
</ParamField>

<ParamField path="chunk (KBChunk)" type="knowledge type">
  A text segment of a [document](#document-kbdocument) with the embedding vector.
  Chunks are the unit that [retrieval](#retrieval) searches over. See
  [Managed knowledge (modulexdb)](/platform/knowledge/managed).
</ParamField>

<ParamField path="Clerk JWT" type="auth credential">
  The user-auth bearer token used by the app (anything that does **not** start with
  `mx_live_`), verified against Clerk's JWKS. The programmatic alternative is an
  [API key](#api-key). See [Auth model: JWT vs API key](/security/authentication).
</ParamField>

<ParamField path="ComposerChat" type="data model">
  The shared conversation store backing both [AI Composer](#ai-composer) and the
  [Assistant](#assistant). Its `id` is the conversation
  [`thread_id`](#thread_id). The `kind` field (`composer` or `assistant`) decides which
  surface a chat belongs to. See [Data model reference](/reference/data-model).
</ParamField>

<ParamField path="conditional node" type="node type">
  One of the [nine node types](#node-type). Branches on an expression, an LLM decision, or
  loops over data. See [Conditional node](/workflow-builder/nodes/conditional).
</ParamField>

<ParamField path="credential" type="data model">
  A stored, encrypted auth record linking an [organization](#organization-org) to an
  integration; identified by `credential_id`. See
  [Credentials & OAuth2](/concepts/credentials-oauth) and [Managing credentials](/integrations/managing-credentials).
</ParamField>

<ParamField path="credit" type="billing unit" required>
  The unit of [managed usage](#modulex-managed-usage-managed-models) billing.
  **100 credits = $1.00**, so **1 credit = $0.01**. Each [organization](#organization-org)
  receives a monthly [credit allowance](#credit-allowance) from its [plan](#plan-tier); when
  that is exhausted, a paid org with [overage](#overage) enabled spends down its
  [wallet](#wallet). [BYOK](#byok-bring-your-own-key) usage is **not** charged in credits.
  See [Credits & metering](/billing/credits).

  <Expandable title="What consumes credits">
    | Usage                                                         | Charge                                                                                                                                       |
    | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
    | A logical run or agent [turn](#turn) (`RUN_CREDIT`)           | 1 credit                                                                                                                                     |
    | Managed [file ingest](#file-ingest) base (`FILE_INGEST_BASE`) | 1 credit                                                                                                                                     |
    | Managed [retrieval](#retrieval) base (`RETRIEVAL_BASE`)       | 1 credit                                                                                                                                     |
    | Integration tool base (`TOOL_BASE`)                           | 1 credit                                                                                                                                     |
    | Managed LLM tokens                                            | `(prompt·in_rate + completion·out_rate) / 1e6 · MARGIN · SCALE`, where `MARGIN = 1.05` (+5%). Unknown models cost 0, never a silent default. |

    See [Credits & metering](/billing/credits) for the full metering model.
  </Expandable>
</ParamField>

<ParamField path="credit allowance" type="entitlement">
  An [organization](#organization-org)'s monthly credit grant from its [plan](#plan-tier).
  The credits/rate-limit values come from the plan configuration, which is canonical:
  **Free = 300 (one-time, trial)**, **Pro = 5,000 monthly**, **Max = 20,000 monthly**,
  **Enterprise = unlimited**.

  <Warning>
    An older internal docstring claims Pro 10,000 / Max 50,000 — that figure is
    stale. Treat the plan configuration (Pro 5,000 / Max 20,000) as canonical. The
    org-level Free grant (300) is distinct from the per-user free pool cap (500); they are
    separate pools. See [Plans & pricing](/billing/plans) and [Credits & metering](/billing/credits).
  </Warning>
</ParamField>

## D

<ParamField path="DenialEnvelope" type="error shape" required>
  The flat billing, credit, rate, and quota denial body. It is **not** wrapped in `detail`:

  ```json theme={null}
  {
    "code": "credit_plan_exhausted",
    "layer": "credit",
    "key": "sync_exec",
    "current": null,
    "limit": 5000.0,
    "reason": "credit_plan_exhausted"
  }
  ```

  This is "shape D" of the four ModuleX error envelopes, and it is **live** on the run,
  Composer, Assistant, and managed-knowledge surfaces. On plain CRUD and org-settings routes,
  a 402/403/429 carries only the `{"detail": …}` shape — it is **not** a `DenialEnvelope`. See
  [Errors & status codes](/api-reference/errors) and [Usage gating & limits](/billing/usage-gating).

  <Expandable title="DenialEnvelope fields">
    <ResponseField name="code" type="string" required>
      The machine-stable denial code your client branches on: `rate_limit_exceeded`,
      `quota_exceeded`, `credit_plan_exhausted`, `wallet_overage_disabled`,
      `wallet_insufficient`, or `upgrade_payment_failed`.
    </ResponseField>

    <ResponseField name="layer" type="string" required>
      Which gate layer denied the call, and therefore the HTTP status:
      `rate` → 429, `quota` → 403, `credit` → 402, `wallet` → 402.
    </ResponseField>

    <ResponseField name="key" type="string | null">
      The limit or counter key that was hit (for example `sync_exec`, `max_knowledge_bases`).
    </ResponseField>

    <ResponseField name="current" type="number | null">
      Observed usage or count at the time of denial.
    </ResponseField>

    <ResponseField name="limit" type="number | null">
      The limit that was hit. `null` when not applicable.
    </ResponseField>

    <ResponseField name="reason" type="string | null">
      A short reason token, for example `overage_disabled` or `credit_plan_exhausted`.
    </ResponseField>
  </Expandable>
</ParamField>

<ParamField path="document (KBDocument)" type="knowledge type">
  An uploaded file in a [knowledge base](#knowledge-base-kb); `status` is one of `pending`,
  `processing`, `completed`, or `failed`. The upload size cap is a [plan](#plan-tier)
  entitlement, not a fixed 50 MB limit. See [Managing documents](/platform/knowledge/documents).
</ParamField>

## E

<ParamField path="edge" type="engine">
  A connection between two [nodes](#node) in a [workflow graph](#workflow-workflow-graph).
  The virtual `__start__` (→ `START`) and `__end__` (→ `END`) endpoints must **not** appear in
  the `nodes[]` array. See [Variables & references](/workflow-builder/variables-and-references).
</ParamField>

<ParamField path="edit_version" type="data model">
  A monotonically increasing integer on a workflow, bumped on each successful Composer edit.
  See [Versioning & history](/workflow-builder/versioning-history).
</ParamField>

<ParamField path="entitlement" type="billing">
  A per-[plan](#plan-tier) limit or flag in the plan configuration. `null` means unlimited
  (the check is skipped), `0` blocks, and an absent key means the feature is not metered. See
  [Usage gating & limits](/billing/usage-gating).
</ParamField>

<ParamField path="EnvVar" type="manifest type">
  An operator-supplied secret or setting under a manifest auth schema. Unlike a
  [`ParameterDef`](#parameterdef), an `EnvVar`'s `required` field defaults to **`True`**. See
  [Manifest & schema contract](/integrations/building/manifest-schema).
</ParamField>

## F

<ParamField path="file ingest" type="knowledge">
  The parse → chunk → embed → store pipeline for an uploaded [document](#document-kbdocument).
  Managed ingest reserves `FILE_INGEST_BASE = 1` [credit](#credit). See
  [Build a RAG knowledge base](/guides/build-a-knowledge-base).
</ParamField>

<ParamField path="function (built-in)" type="engine">
  A registry function callable from a [function node](#function-node). There are exactly four
  built-ins: `http_request`, `send_webhook`, `validate_schema`, and `validate_workflow_schema`.
  See [Function node](/workflow-builder/nodes/function).
</ParamField>

<ParamField path="function node" type="node type">
  One of the [nine node types](#node-type). Runs a built-in [function](#function-built-in) such
  as an HTTP request, a webhook, or schema validation. See [Function node](/workflow-builder/nodes/function).
</ParamField>

## G

<ParamField path="gate / gate_run_admission(...)" type="billing">
  The synchronous admission gate run **before any database write** on managed-usage surfaces.
  It reserves [credit](#credit) and raises [`BillingDenied`](#billingdenied) on denial. It is
  **live** on the run, Composer, Assistant, and managed-knowledge surfaces, and is part of the
  reserve → charge → settle credit lifecycle. See [Usage gating & limits](/billing/usage-gating).
</ParamField>

<ParamField path="guardrails node" type="node type">
  One of the [nine node types](#node-type). Validates content with JSON-schema, regex, PII, and
  placeholder hallucination checks, with `on_failure` in `{block, warn, transform, route}`. See
  [Guardrails node](/workflow-builder/nodes/guardrails).
</ParamField>

## H

<ParamField path="heartbeat" type="SSE event">
  A `{"type": "heartbeat"}` keepalive injected every 15 seconds on the
  [SSE](#sse-server-sent-events) run stream. See [SSE run streaming](/realtime/sse-streaming).
</ParamField>

<ParamField path="HITL (human-in-the-loop)" type="agent flow" required>
  The pattern where an agent or workflow pauses to ask a person a structured question, then
  resumes once the person answers. In Composer and the Assistant the pause is an
  interrupt answered through `/resume`; in a workflow it is an
  [interrupt node](#interrupt-node-hitl). The question is a `UserInputRequest`
  (`single_choice`, `multi_choice`, `yes_no`, `free_text`, or `credential_request`) and the
  answer is a `UserInputResponse`. See [Human-in-the-loop (HITL) resume](/realtime/hitl) and
  [Human-in-the-loop](/assistant/human-in-the-loop).
</ParamField>

## I

<ParamField path="integration" type="product">
  A connector to an external service. One integration exposes many [tools](#tool) (callable
  actions). ModuleX ships **175** integrations.

  <Warning>
    Drift: the marketing site states the tool count three ways ("200+ Integrations",
    "1000+ tools", "600+ tools"). The documentation uses **600+ tools** as the SEO-canonical
    phrasing, and **175 integrations** as the canonical integration count.
  </Warning>

  See [Integrations overview](/integrations/overview) and [Integration catalog](/integrations/catalog).
</ParamField>

<ParamField path="IntegrationManifest" type="manifest type">
  The single Pydantic contract every integration's `manifest.py` must satisfy. It forbids
  unknown fields (`extra="forbid"`), so a typo fails at import time. Its `integration_type` is
  always `"tool"`. See [Manifest & schema contract](/integrations/building/manifest-schema).
</ParamField>

<ParamField path="interrupt node (HITL)" type="node type">
  One of the [nine node types](#node-type). Pauses a workflow run with an
  interrupt to await a resume value; it is **not** retry-wrapped. Distinct from the
  Composer/Assistant [HITL](#hitl-human-in-the-loop) interrupt, which uses the same
  primitive on a different surface. See [Interrupt node (HITL)](/workflow-builder/nodes/interrupt).
</ParamField>

## K

<ParamField path="knowledge / RAG" type="product">
  Company knowledge connected to chats and workflows. ModuleX retrieves relevant context
  automatically using retrieval-augmented generation.

  <Note>
    The home page chip reads "Knowledges" (plural). The documentation standardizes on the
    singular **Knowledge**.
  </Note>

  See [Knowledge & RAG](/concepts/knowledge-rag) and [Knowledge overview](/platform/knowledge/overview).
</ParamField>

<ParamField path="knowledge base (KB)" type="data model" required>
  A knowledge base with its own embedding and chunking configuration — the unit that
  [retrieval](#retrieval) searches over. The API router prefix is `/knowledge-bases`.

  A **native (managed) KB** has `embedding_config.integration_name == "modulexai"` and is
  served by the `modulexdb` provider; its retrieval and ingest are billed in
  [credits](#credit). A **[BYOK](#byok-bring-your-own-key) KB** uses your own vector store and
  is uncosted.

  <Warning>
    The knowledge base quota is non-monotonic across plans: **Free 10 / Pro 3 / Max 50** — Pro
    allows fewer KBs than Free. Verify your limit on [Plans & pricing](/billing/plans).
  </Warning>

  See [Managed knowledge (modulexdb)](/platform/knowledge/managed) and [Knowledge providers](/integrations/knowledge-providers/overview).
</ParamField>

<ParamField path="knowledge node" type="node type">
  One of the [nine node types](#node-type). Retrieves from a [knowledge base](#knowledge-base-kb)
  inside a workflow; its `output_format` is `chunks`, `context`, or `both`. See
  [Knowledge node](/workflow-builder/nodes/knowledge).
</ParamField>

## L

<ParamField path="layer" type="error field">
  The discriminator on a [`DenialEnvelope`](#denialenvelope) that maps to an HTTP status:
  `rate` → 429, `quota` → 403, `credit` → 402, `wallet` → 402. See
  [Errors & status codes](/api-reference/errors).
</ParamField>

<ParamField path="LLM node" type="node type">
  One of the [nine node types](#node-type). Calls a language model with prompts, variables, and
  optional structured output. See [LLM node](/workflow-builder/nodes/llm).
</ParamField>

<ParamField path="loop" type="engine">
  A `for`, `foreach`, or `while` construct, expressed via an edge condition of type `loop` or a
  [conditional node](#conditional-node). See [Conditional node](/workflow-builder/nodes/conditional).
</ParamField>

## M

<ParamField path="ModuleX" type="brand">
  The product and brand. The legal entity is **ModulexAI, LLC**, a Delaware LLC; "the Service"
  is the legal umbrella for the ModuleX websites, applications, APIs, and related services. See
  [Why ModuleX](/get-started/why-modulex).
</ParamField>

<ParamField path="ModuleX MCP" type="product surface">
  The feature that publishes your organization's live workflows, Files, and Knowledge as tools
  on a private [Model Context Protocol](https://modelcontextprotocol.io) server that external AI
  clients (Claude Code, Cursor, Codex) connect to over Streamable HTTP. Here ModuleX is the
  **server** and the client is the consumer — the reverse of a
  [custom MCP server](/integrations/building/custom-mcp), where ModuleX is the client of an
  external server. Clients authenticate with a server-scoped `mx_mcp_` key. See
  [ModuleX MCP](/api-reference/mcp/overview).
</ParamField>

<ParamField path="ModuleX-managed usage / managed models" type="usage mode" required>
  The default alternative to [BYOK](#byok-bring-your-own-key): your calls run through
  ModuleX-provisioned providers and are **billed in [credits](#credit)**. On the wire the
  managed provider is `modulexai` (LLM and tools) or `modulexdb` (knowledge). See
  [ModuleX-managed models](/integrations/llm-providers/modulexai) and [Credits & metering](/billing/credits).
</ParamField>

<ParamField path="month_offset" type="billing">
  The monthly billing-bucket integer, `year*12 + (month-1)`, that partitions paid credit usage
  per period. Free orgs return `0`. See [Credits & metering](/billing/credits).
</ParamField>

## N

<ParamField path="node" type="engine">
  One step in a [workflow graph](#workflow-workflow-graph). Every node writes its result into
  run [state](#state-state_schema) under its own `id`. See
  [Workflow engine & nodes](/concepts/workflow-engine).
</ParamField>

<ParamField path="node type" type="enum" required>
  One of the **nine** node kinds in the `NodeType` enum. Each is documented on its own page:

  <Expandable title="The nine node types">
    <ResponseField name="llm" type="node">
      Call a language model. See [LLM node](/workflow-builder/nodes/llm).
    </ResponseField>

    <ResponseField name="tool" type="node">
      Call an integration [tool](#tool). See [Tool node](/workflow-builder/nodes/tool).
    </ResponseField>

    <ResponseField name="agent" type="node">
      Run an autonomous agent step that can call tools and loop. See [Agent node](/workflow-builder/nodes/agent).
    </ResponseField>

    <ResponseField name="function" type="node">
      Run a built-in [function](#function-built-in). See [Function node](/workflow-builder/nodes/function).
    </ResponseField>

    <ResponseField name="conditional" type="node">
      Branch or loop on a condition. See [Conditional node](/workflow-builder/nodes/conditional).
    </ResponseField>

    <ResponseField name="interrupt" type="node">
      Pause for [HITL](#hitl-human-in-the-loop) input. See [Interrupt node (HITL)](/workflow-builder/nodes/interrupt).
    </ResponseField>

    <ResponseField name="transformer" type="node">
      Reshape and map data between steps. See [Transformer node](/workflow-builder/nodes/transformer).
    </ResponseField>

    <ResponseField name="guardrails" type="node">
      Validate content with JSON, regex, and PII checks. See [Guardrails node](/workflow-builder/nodes/guardrails).
    </ResponseField>

    <ResponseField name="knowledge" type="node">
      Retrieve from a [knowledge base](#knowledge-base-kb). See [Knowledge node](/workflow-builder/nodes/knowledge).
    </ResponseField>
  </Expandable>

  See the [Node types overview](/workflow-builder/nodes/overview).
</ParamField>

## O

<ParamField path="OAuth auto-resume" type="agent flow">
  When a [HITL](#hitl-human-in-the-loop) credential request opens an OAuth flow, the callback
  re-runs the credential guard and resumes the chat without a manual `/resume` call. See
  [Using tools](/assistant/using-tools).

  <Warning>
    The UI's `refreshOAuth2` flow is broken (its BFF route is missing). Reconnect the credential
    instead of relying on a silent refresh. See [Known limitations](/reference/known-limitations).
  </Warning>
</ParamField>

<ParamField path="organization (org)" type="tenancy" required>
  The tenant and billing unit. Every managed-usage record, [plan](#plan-tier),
  [wallet](#wallet), and [knowledge base](#knowledge-base-kb) is org-scoped, and every
  org-scoped request must send the [`X-Organization-ID`](#x-organization-id) header. See
  [Organizations, roles & membership](/concepts/organizations-roles).
</ParamField>

<ParamField path="overage" type="billing">
  Spending beyond the plan [credit allowance](#credit-allowance), funded by the
  [wallet](#wallet). It is paid-plan only and toggled by `extra_usage_enabled`. See
  [Wallet & top-ups](/billing/wallet).
</ParamField>

<ParamField path="owner (role)" type="org role">
  A live [organization](#organization-org) role with full permissions. With `admin`, it is one
  of the two current roles required on the gated surfaces. See
  [Roles & permissions](/security/roles-permissions).
</ParamField>

## P

<ParamField path="ParameterDef" type="manifest type">
  A single parameter of an [`ActionDefinition`](#actiondefinition): `type` in
  `{string, integer, number, boolean, array, object}`, a description, an optional default, and a
  `required` field that defaults to **`False`** (the opposite of [`EnvVar`](#envvar)). See
  [Manifest & schema contract](/integrations/building/manifest-schema).
</ParamField>

<ParamField path="plan / tier" type="billing" required>
  A subscription level: **Free**, **Pro**, **Max**, or **Enterprise** (slugs `free`, `pro`,
  `max`, `enterprise`). Each plan sets the [credit allowance](#credit-allowance), rate limits,
  and [entitlements](#entitlement).

  <Warning>
    Pricing drift: the marketing site and the backend Stripe SKUs disagree on the annual price
    ($240 / $960 with a "Save 20%" label versus $300 / $1,200 with no discount). The canonical
    annual price is an open question; confirm the price at checkout. See [Plans & pricing](/billing/plans).
  </Warning>
</ParamField>

<ParamField path="profile" type="agent">
  The agent profile derived from a chat's [`kind`](#composerchat) — `composer` or `assistant` —
  which selects the tools, middleware, and subagents for that turn. See
  [How the Assistant works](/assistant/how-it-works).
</ParamField>

## R

<ParamField path="reducer" type="engine">
  How a [state](#state-state_schema) field merges updates: `none` replaces, `add` does a smart
  array or operator-add merge, and `update` does a dict-merge. See
  [Variables & references](/workflow-builder/variables-and-references).
</ParamField>

<ParamField path="reference / {{nodeId.path}}" type="engine">
  The template syntax that pulls a prior node's value into a later node, for example
  `{{extract_topic.result}}`. The array-spread variant is `{{...nodeId.path}}`. See
  [Variables & references](/workflow-builder/variables-and-references).
</ParamField>

<ParamField path="retrieval" type="knowledge">
  A search or retrieve call against a [knowledge base](#knowledge-base-kb). Managed retrieval
  reserves `RETRIEVAL_BASE = 1` [credit](#credit) before embedding. See
  [Knowledge & RAG](/concepts/knowledge-rag).
</ParamField>

<ParamField path="role" type="auth">
  The caller's [organization](#organization-org) role. The live roles are **`owner`** and
  **`admin`** only; the `member` role is [retired](#terms-you-should-not-use). Composer, the
  Assistant, schedules, and managed knowledge require `owner` or `admin`. See
  [Roles & permissions](/security/roles-permissions).
</ParamField>

<ParamField path="run / run_id" type="execution" required>
  A single workflow or agent execution. The identifier called "run id" actually refers to
  **three distinct identities**, and you must not assume one for another.

  <Expandable title="The three run-id identities">
    <ResponseField name="run_id (per-execution)" type="string">
      The per-execution identifier used for [SSE](#sse-server-sent-events) streaming, run
      status, and history keys. For agents a **new** `run_id` is minted on every
      [turn](#turn) and on every resume, so `run_id` is **not** stable across a conversation
      and is **not** the chat id.
    </ResponseField>

    <ResponseField name="thread_id" type="string">
      The conversation checkpoint thread, equal to the [`ComposerChat`](#composerchat) id
      (`thread_id == composer_chat_id`). It is **stable across the whole conversation**. See
      [thread\_id](#thread_id).
    </ResponseField>

    <ResponseField name="run_id (durable)" type="string">
      The durable `run_id` — a unique identifier on the run record. Resume
      **reuses** the same value (update-in-place). The SDK history methods accept the run
      record's `id`, which is **not** the same as the per-execution
      `run_id`.
    </ResponseField>
  </Expandable>

  See [Workflows & runs](/concepts/workflows-and-runs) and [Realtime overview](/realtime/overview).
</ParamField>

<ParamField path="run_resumed / resumed" type="SSE event">
  The events that signal a paused run has continued under a **new** [`run_id`](#run-run_id):
  `run_resumed` (agent) and `resumed` (workflow). See [Human-in-the-loop (HITL) resume](/realtime/hitl).
</ParamField>

## S

<ParamField path="snake_case (on the wire)" type="convention">
  API responses are snake\_case JSON (Pydantic v2 default; no global camelCase alias). The
  JavaScript SDK accepts camelCase params and converts them to snake\_case on the way out, but
  its **responses stay snake\_case** (`run_id`, `created_at`); the Python SDK is snake\_case both
  ways. See [SDKs overview](/sdks/overview).
</ParamField>

<ParamField path="SSE (Server-Sent Events)" type="transport" required>
  The streaming transport for runs. Each run event is `data: <json>\n\n` with **no `event:`
  line** — the discriminator is the `type` key inside the JSON (`metadata`, `node_update`,
  `interrupt`, `done`, `error`, and so on).

  <Warning>
    Drift: the sidebar chat-list stream uses **named** SSE events (`event: chat_list_updated`),
    the opposite convention. Do not assume one SSE convention across the whole product.
  </Warning>

  See [SSE run streaming](/realtime/sse-streaming) and [Realtime overview](/realtime/overview).
</ParamField>

<ParamField path="state / state_schema" type="engine">
  The dynamic run-state dictionary. One field is auto-added per node `id` (type `Any`) for
  streaming, alongside any user-defined and loop fields. See
  [Variables & references](/workflow-builder/variables-and-references).
</ParamField>

<ParamField path="subagent" type="agent">
  A Composer-only sub-agent (`integration-resolver`, `credential-resolver`). The Assistant has
  no subagents. See [How the Assistant works](/assistant/how-it-works).
</ParamField>

<ParamField path="subscriptions resource" type="SDK">
  The SDK resource for subscription lifecycle. It exists in the **Python SDK only**; the
  JavaScript SDK has no `subscriptions` methods. See [SDK ⇄ API parity matrix](/sdks/parity)
  and [Subscriptions & Stripe](/billing/subscription-lifecycle).
</ParamField>

## T

<ParamField path="thread_id" type="execution">
  The conversation checkpoint thread identifier, equal to the [`ComposerChat`](#composerchat) id.
  Unlike a per-execution [`run_id`](#run-run_id), `thread_id` is stable across an entire
  conversation. See [Workflows & runs](/concepts/workflows-and-runs).
</ParamField>

<ParamField path="tool" type="product">
  A single callable action exposed by an [integration](#integration). ModuleX advertises
  **600+ tools** across its 175 integrations. See [Tool node](/workflow-builder/nodes/tool) and
  [@tool function contract](/integrations/building/tool-contract).
</ParamField>

<ParamField path="tool node" type="node type">
  One of the [nine node types](#node-type). Calls one integration [tool](#tool). See
  [Tool node](/workflow-builder/nodes/tool).
</ParamField>

<ParamField path="transformer node" type="node type">
  One of the [nine node types](#node-type). Reshapes, maps, and combines data between steps. See
  [Transformer node](/workflow-builder/nodes/transformer).
</ParamField>

<ParamField path="turn" type="agent">
  One user message resulting in one agent run. Billing charges exactly one run
  [credit](#credit) per turn; a resume re-enters through `/resume` rather than `/chat` and
  mints a new [`run_id`](#run-run_id). See [How the Assistant works](/assistant/how-it-works).
</ParamField>

## U

<ParamField path="UserInputRequest / UserInputResponse" type="HITL payload">
  The [HITL](#hitl-human-in-the-loop) question and answer payloads. A `UserInputRequest` is
  discriminated on `kind` (`single_choice`, `multi_choice`, `yes_no`, `free_text`,
  `credential_request`); a `UserInputResponse` is discriminated on `kind`
  (`single_choice`, `multi_choice`, `yes_no`, `free_text`, `credential_added`,
  `credential_failed`, `skipped`). Each pair is bound by a `request_id`. See
  [Human-in-the-loop (HITL) resume](/realtime/hitl).
</ParamField>

## W

<ParamField path="wallet" type="billing">
  The prepaid balance an [organization](#organization-org) spends after its plan
  [credit allowance](#credit-allowance) is gone. The balance may go negative,
  and it supports manual top-ups and auto-top-up. See [Wallet & top-ups](/billing/wallet).
</ParamField>

<ParamField path="workflow / workflow graph" type="data model" required>
  The editable graph of [nodes](#node) and [edges](#edge) that connects tools, data, and agents;
  the backend type is `WorkflowDefinition`. A `WorkflowDefinition` carries `metadata`, `config`,
  `state_schema`, `nodes[]`, `edges[]`, and an `entry_point` (default `"__start__"`). The visual
  edit surface is the [Workflow Builder](#workflow-builder). See
  [Workflows & runs](/concepts/workflows-and-runs) and [Workflow engine & nodes](/concepts/workflow-engine).
</ParamField>

<ParamField path="Workflow Builder" type="product surface">
  The visual canvas for building [workflows](#workflow-workflow-graph), with realtime
  collaboration. See [Workflow builder overview](/workflow-builder/overview).
</ParamField>

<ParamField path="workflow:external-sync" type="Socket.io event">
  The live Socket.io event that propagates external (REST) workflow changes to collaborators.
  It is the canonical external-sync mechanism — **not** the dead `workflow:updated` pub/sub
  channel. See [Socket.io collaboration events](/realtime/socket-events) and
  [Realtime co-editing & external sync](/workflow-builder/realtime-coediting).
</ParamField>

## X

<ParamField path="X-Organization-ID" type="header" required>
  The **required** header that selects the [organization](#organization-org) context for every
  org-scoped endpoint. Note the capital `ID`. A missing header returns **400**. Both SDKs send
  it automatically once an org is configured.

  <Warning>
    Do not confuse this with the non-existent `X-Authorization` header (see
    [terms you should not use](#terms-you-should-not-use)). Authentication uses
    `Authorization: Bearer`; org context uses `X-Organization-ID`.
  </Warning>

  See [Org context & X-Organization-ID](/security/org-context).
</ParamField>

## Putting the canonical names together

The example below uses the canonical terms in the way the rest of the documentation does:
authenticate with an [API key](#api-key) as `Authorization: Bearer mx_live_…`, pass the
[`X-Organization-ID`](#x-organization-id) header, and start a [run](#run-run_id) of a saved
[workflow](#workflow-workflow-graph). The operation is shown once, three ways — see
[Run a workflow (REST + SDK)](/guides/run-a-workflow) for the full walkthrough.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modulex.dev/workflows/run \
    -H "Authorization: Bearer mx_live_8f2c1d4b9a7e6h3k" \
    -H "X-Organization-ID: org_3kd9f2mn7q" \
    -H "Content-Type: application/json" \
    -d '{
      "workflow_id": "wf_a1b2c3d4",
      "input": { "topic": "quarterly revenue" },
      "stream": true
    }'
  ```

  ```python Python theme={null}
  from modulex import Modulex

  async with Modulex(
      api_key="mx_live_8f2c1d4b9a7e6h3k",
      organization_id="org_3kd9f2mn7q",
  ) as client:
      res = await client.executions.run(
          workflow_id="wf_a1b2c3d4",
          input={"topic": "quarterly revenue"},
          stream=True,
      )
      print(res.run_id, res.thread_id)
  ```

  ```javascript JavaScript theme={null}
  import { Modulex } from "modulex-js";

  const client = new Modulex({
    apiKey: "mx_live_8f2c1d4b9a7e6h3k",
    organizationId: "org_3kd9f2mn7q",
  });

  const run = await client.executions.run({
    workflowId: "wf_a1b2c3d4",
    input: { topic: "quarterly revenue" },
    stream: true,
  });
  console.log(run.run_id, run.thread_id);
  ```
</CodeGroup>

The run can return a [`DenialEnvelope`](#denialenvelope) (402/403/429) if the
[billing gate](#gate-gate_run_admission) denies it, because `POST /workflows/run` is a managed
run surface. See [Errors & status codes](/api-reference/errors) for how to branch on each
[layer](#layer).

<Note>
  Looking for the plain-English version of these terms? Start with
  [Core concepts at a glance](/get-started/core-concepts) and [How ModuleX works](/concepts/overview).
</Note>
