> ## 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.

# Meet the Assistant: agentic chat that gets work done

> The ModuleX Assistant is a workflow-independent agentic chat. Describe a task in plain language and it searches your connected tools, calls them step by step, and pauses for your approval — no workflow to build first.

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>;
};

The Assistant is an agentic chat that gets work done with the tools your team has already connected. You describe a task in plain language, and the Assistant decides which tools to call, runs them one step at a time, and pauses to ask you whenever it needs a decision or an approval. There is no workflow to build first — you just start a conversation.

<MediaEmbed id="MX-MEDIA-3220" type="app_video" caption={"The Assistant completing a multi-tool task end to end inside the chat surface."} />

## What the Assistant is

Think of the Assistant as a colleague who already knows how to use every service you have connected to ModuleX. You ask in plain language; it works through the task and reports back.

<CardGroup cols={3}>
  <Card title="It uses your tools" icon="wrench">
    The Assistant searches your connected integrations and calls their actions directly — for example, listing your repositories or sending a message — using your organization's stored credentials.
  </Card>

  <Card title="It works step by step" icon="list-checks">
    Each request becomes a turn. The Assistant streams its thinking, calls one tool at a time, reads the result, and keeps going until the task is done.
  </Card>

  <Card title="It asks before acting" icon="shield-check">
    For sensitive actions it stops and shows an approval card. Nothing risky runs until you say yes.
  </Card>
</CardGroup>

The Assistant runs on the same agent engine as the [AI Composer](/concepts/ai-composer), but with one important difference: it has **no access to your workflows at all**. It cannot list, open, build, edit, or run a workflow. Its job is to act directly with your connected tools and your [knowledge bases](/concepts/knowledge-rag) — not to assemble a workflow graph. To learn what happens under the hood, see [how the Assistant works](/assistant/how-it-works).

### What it can do

<CardGroup cols={2}>
  <Card title="Call integration tools" icon="plug" href="/assistant/using-tools">
    Run a single action on a connected service, like "list my GitHub repos" or "create a Linear issue." The Assistant discovers which tools exist and runs them for you.
  </Card>

  <Card title="Connect what's missing" icon="key" href="/integrations/authentication">
    If a task needs a service you have not connected yet, the Assistant asks you to add the credential — including starting an OAuth connection — right inside the chat.
  </Card>

  <Card title="Search your knowledge" icon="book-open" href="/concepts/knowledge-rag">
    Answer questions from your connected knowledge bases with retrieval, so replies are grounded in your own documents.
  </Card>

  <Card title="Pause for your input" icon="hand" href="/assistant/human-in-the-loop">
    Ask you a question, offer choices, or request approval mid-task, then continue once you answer.
  </Card>
</CardGroup>

<Note>
  The Assistant is text-only today: each turn is a single text message. It does not build or run workflows, and it does not accept file uploads or `messages[]` history in a single turn.
</Note>

## Assistant vs Composer vs Builder

ModuleX gives you three ways to get things done. They are easy to tell apart once you know what each one produces.

<CardGroup cols={3}>
  <Card title="Assistant" icon="bot">
    **Acts for you, now.** A chat that calls your tools step by step to complete a task. Produces results and answers — not a saved workflow.
  </Card>

  <Card title="AI Composer" icon="wand-sparkles">
    **Builds a workflow for you.** A chat copilot inside the builder that turns a plain-English description into an editable workflow graph you can save and reuse.
  </Card>

  <Card title="Workflow builder" icon="workflow">
    **You build it by hand.** The visual canvas where you drag, connect, and configure nodes yourself for full control.
  </Card>
</CardGroup>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>Assistant</th>
      <th>AI Composer</th>
      <th>Workflow builder</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>**What you get**</td>
      <td>Work done in the chat — answers and completed actions</td>
      <td>An editable, reusable workflow graph</td>
      <td>An editable, reusable workflow graph</td>
    </tr>

    <tr>
      <td>**How you drive it**</td>
      <td>Plain-language chat</td>
      <td>Plain-language chat</td>
      <td>Drag, connect, and configure nodes by hand</td>
    </tr>

    <tr>
      <td>**Touches your workflows?**</td>
      <td>No — it has no workflow tools</td>
      <td>Yes — it creates and edits the graph</td>
      <td>Yes — you are editing the graph</td>
    </tr>

    <tr>
      <td>**Calls your tools live?**</td>
      <td>Yes, directly during the chat</td>
      <td>While building, not as a saved run</td>
      <td>When you run the workflow</td>
    </tr>

    <tr>
      <td>**Reusable later?**</td>
      <td>The chat is saved; the result is one-off</td>
      <td>Yes — the workflow can be run again</td>
      <td>Yes — the workflow can be run again</td>
    </tr>

    <tr>
      <td>**Best for**</td>
      <td>One-off tasks and quick questions</td>
      <td>Going from idea to a workflow fast</td>
      <td>Precise, complex automations</td>
    </tr>
  </tbody>
</table>

<Note>
  The Assistant and the AI Composer share the same chat engine and the same approval and pause-for-input behavior, but they are separate surfaces. The Composer edits a workflow graph; the Assistant has no workflow tools whatsoever. The [workflow builder](/workflow-builder/overview) is the canvas both of them — and you — can edit.
</Note>

## When to use the Assistant

<CardGroup cols={2}>
  <Card title="Use the Assistant when" icon="circle-check">
    * You want something done once, right now — a lookup, a summary, a quick post.
    * The task spans a few connected services and you would rather describe it than wire it.
    * You want an answer grounded in your own knowledge.
    * You are exploring what your connected tools can do.
  </Card>

  <Card title="Use Composer or the builder when" icon="repeat">
    * You will repeat the task and want to save it as a [workflow](/concepts/workflows-and-runs).
    * You need to schedule it, trigger it from an API, or run it from chat.
    * You need branching, loops, retries, or precise control over each step.
    * You want to share a reusable automation with your team.
  </Card>
</CardGroup>

Many people start with the Assistant to prove a task is possible, then rebuild the repeatable version with the [AI Composer](/concepts/ai-composer) or the [workflow builder](/workflow-builder/overview).

## How to start a session

The Assistant lives at the chat surface of the ModuleX app. Starting a session takes one message.

<Steps>
  <Step title="Open the chat surface">
    Sign in to the ModuleX app and open the chat. The Assistant greets you with a few starter prompts you can use as a launching point.

    <MediaEmbed id="MX-MEDIA-3221" type="screenshot" caption={"The Assistant's empty-state landing with the greeting, the centered message box, and starter prompt chips."} />
  </Step>

  <Step title="Describe your task in plain language">
    Type what you want done — for example, "Summarize my newest support tickets" — and send. A starter chip fills the box for you but does not send on its own, so you can edit it first.
  </Step>

  <Step title="Watch it work">
    The Assistant streams its reply live: you see its thinking, each tool it calls, and the result of each call as it goes. You can stop a turn at any time. Learn more in [streaming responses](/assistant/streaming).
  </Step>

  <Step title="Answer when it asks">
    If the Assistant needs a choice, a piece of information, or approval for a sensitive action, it pauses and shows you a question or an approval card. Answer it and the Assistant continues. See [human-in-the-loop](/assistant/human-in-the-loop).
  </Step>

  <Step title="Connect a tool if prompted">
    If the task needs a service you have not connected, the Assistant asks you to add the credential — including starting an OAuth connection — without leaving the chat. See [authentication and credentials](/integrations/authentication).
  </Step>
</Steps>

Your conversations are saved, so you can reopen a chat later, pick up where you left off, and browse your history.

<Accordion title="Who can use the Assistant?">
  The Assistant is scoped to one of your [organizations](/concepts/organizations-roles). As built today, you must have the **owner** or **admin** role in that organization to start or continue an Assistant chat; other members receive a permission error. The retired `member` role is not a current role. See [roles and permissions](/security/roles-permissions) and [permissions and limits](/assistant/permissions-and-limits) for the full picture.
</Accordion>

<Accordion title="One question at a time per chat">
  A chat can hold only one open question at a time. While the Assistant is waiting for your answer, or while a turn is still running, it will not start another turn on the same chat — you finish the current step first. This keeps each conversation predictable.
</Accordion>

<Accordion title="Does the Assistant use credits?">
  Yes. Each turn is metered like any other managed run, and language-model token usage is recorded separately. If your plan's allowance is exhausted, the turn is declined before anything runs, and you will see a clear billing message. See [credits and the billing model](/concepts/credits-billing) and [usage gating and limits](/billing/usage-gating).
</Accordion>

## Start the Assistant from your own code

You can also drive the Assistant programmatically. A turn starts with one authenticated request that creates or continues a chat and returns a stream URL; you then open that stream to watch the turn unfold. Every request uses `Authorization: Bearer mx_live_…` plus your `X-Organization-ID` header — see [authentication](/api-reference/authentication).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modulex.dev/assistant/chat \
    -H "Authorization: Bearer mx_live_your_api_key" \
    -H "X-Organization-ID: org_your_organization_id" \
    -H "Content-Type: application/json" \
    -d '{
      "message": "List my GitHub repositories",
      "llm": {
        "integration_name": "openai",
        "provider_id": "openai",
        "model_id": "gpt-4o"
      }
    }'
  ```

  ```python Python theme={null}
  import httpx

  resp = httpx.post(
      "https://api.modulex.dev/assistant/chat",
      headers={
          "Authorization": "Bearer mx_live_your_api_key",
          "X-Organization-ID": "org_your_organization_id",
      },
      json={
          "message": "List my GitHub repositories",
          "llm": {
              "integration_name": "openai",
              "provider_id": "openai",
              "model_id": "gpt-4o",
          },
      },
  )
  data = resp.json()
  print(data["stream_url"])  # open this to stream the turn
  ```

  ```javascript JavaScript theme={null}
  const resp = await fetch("https://api.modulex.dev/assistant/chat", {
    method: "POST",
    headers: {
      Authorization: "Bearer mx_live_your_api_key",
      "X-Organization-ID": "org_your_organization_id",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      message: "List my GitHub repositories",
      llm: {
        integration_name: "openai",
        provider_id: "openai",
        model_id: "gpt-4o",
      },
    }),
  });
  const data = await resp.json();
  console.log(data.stream_url); // open this to stream the turn
  ```
</CodeGroup>

A successful response returns the chat and run identifiers plus a `stream_url`, which you open over Server-Sent Events to receive the Assistant's actions and output as they happen:

```json Response theme={null}
{
  "status": "running",
  "chat_id": "f2b1c0de-1111-2222-3333-444455556666",
  "run_id": "a1b2c3d4-aaaa-bbbb-cccc-dddddddddddd",
  "thread_id": "f2b1c0de-1111-2222-3333-444455556666",
  "stream_url": "/assistant/chat/f2b1c0de-1111-2222-3333-444455556666/listen/a1b2c3d4-aaaa-bbbb-cccc-dddddddddddd"
}
```

<Note>
  To talk to the Assistant programmatically, always use the `/assistant/chat` request shown above — that is the supported path. For the full set of Assistant operations, see [how the Assistant works](/assistant/how-it-works) and [streaming responses](/assistant/streaming).
</Note>

## Where to go next

<CardGroup cols={2}>
  <Card title="How the Assistant works" icon="cog" href="/assistant/how-it-works">
    The agentic loop: how the Assistant reasons, picks a tool, acts, observes the result, and decides when it is done.
  </Card>

  <Card title="The Assistant concept" icon="lightbulb" href="/concepts/assistant">
    Where the Assistant fits in the ModuleX mental model, and how it relates to the Composer and the engine.
  </Card>

  <Card title="Using tools" icon="wrench" href="/assistant/using-tools">
    How the Assistant discovers and calls integration tools, and how it requests credentials.
  </Card>

  <Card title="Chat overview" icon="messages-square" href="/platform/chat/overview">
    A tour of the chat surface where the Assistant lives, and how it sits alongside knowledge and workflow runs.
  </Card>

  <Card title="Human-in-the-loop" icon="hand" href="/assistant/human-in-the-loop">
    How the Assistant pauses for a question or an approval, and how you respond.
  </Card>

  <Card title="Examples" icon="sparkles" href="/assistant/examples">
    Worked examples of common Assistant tasks, end to end.
  </Card>
</CardGroup>
