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

# AI Composer & Assistant — help

> Quick answers about ModuleX's two AI helpers: the AI Composer that builds workflows from plain English, and the Assistant that uses your connected tools step by step — including who can run them and what to do when one pauses.

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

ModuleX has two AI helpers, and they do different jobs. The **AI Composer** turns a plain-English description into an editable workflow. The **Assistant** is a chat that uses your connected tools step by step to get something done, without building a workflow. This page answers the questions people ask most about both. Each answer links to a fuller guide.

<CardGroup cols={2}>
  <Card title="AI Composer" icon="wand-magic-sparkles" href="/concepts/ai-composer">
    The text-to-workflow agent that drafts an editable workflow from a prompt.
  </Card>

  <Card title="Assistant" icon="messages" href="/assistant/overview">
    The agentic chat that uses your tools to finish a task — no workflow needed.
  </Card>
</CardGroup>

<MediaEmbed id="MX-MEDIA-4540" type="app_video" caption={"The AI Composer generating a workflow from a plain-English prompt."} />

## Common questions

<AccordionGroup>
  <Accordion title="What's the difference between Composer and the Assistant?" icon="code-compare">
    The **AI Composer** turns a plain-English description into a complete, editable workflow that you save and run later. The **Assistant** is a chat that uses your connected tools step by step to finish a task right now, and it does not build or change any workflow. In short: use the Composer to *build* something reusable; use the Assistant to *get something done* in the moment. See [AI Composer](/concepts/ai-composer) and the [Assistant overview](/assistant/overview).
  </Accordion>

  <Accordion title="How do I use the Composer?" icon="wand-magic-sparkles">
    Open the Composer in the workflow builder and describe what you want — for example, "Search GitHub and summarize the top result." It builds the workflow on the canvas for you, then you review the changes and **save** them (or **revert** to undo). You can keep chatting to refine it. See [AI Composer in the builder](/workflow-builder/composer) and the [build with Composer guide](/guides/build-with-composer).
  </Accordion>

  <Accordion title="Why can't my teammate use the Composer or the Assistant?" icon="lock">
    Both the Composer and the Assistant require an **owner** or **admin** role in the organization. There is no longer a read-only `member` role, so anyone without owner or admin access cannot run them. Ask an owner or admin to change the teammate's role, or to run the task for them. See [roles & permissions](/security/roles-permissions).
  </Accordion>

  <Accordion title="Why is the Assistant asking me to connect something?" icon="plug">
    A tool it wants to use needs a credential for that service, so it pauses and asks you to connect the account. Connect it when prompted — for an OAuth service this sends you to the provider to approve access — and the Assistant continues on its own from where it stopped. See [credentials & integrations help](/help/credentials-integrations).
  </Accordion>

  <Accordion title="My Composer or Assistant run stopped without finishing — why?" icon="circle-pause">
    It is almost always **paused waiting for your input**, not failed. The Composer and the Assistant pause to ask a question — a choice, a yes/no, some text, or a request to connect a service. Answer the prompt and the run picks up where it left off. See the [Assistant overview](/assistant/overview).
  </Accordion>
</AccordionGroup>

<Note>
  The Composer and the Assistant each charge **one run credit per turn** (one message you send), plus the cost of any AI model and tool usage. Bringing your own model key (BYOK) is not charged in credits. See [credits & metering](/billing/credits).
</Note>

## Keep reading

<CardGroup cols={2}>
  <Card title="Build a workflow with Composer" icon="rocket" href="/guides/build-with-composer">
    A full walkthrough from a prompt to a running workflow.
  </Card>

  <Card title="Roles & permissions" icon="shield-check" href="/security/roles-permissions">
    Who can use the Composer, the Assistant, and schedules.
  </Card>
</CardGroup>
