> ## Documentation Index
> Fetch the complete documentation index at: https://ctrlrun-docs-assurance-case-fits.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Stop wrong, restricted, or malicious AI agent actions

> Every AI agent action is checked against your rules before it runs. Allowed ones go through, sensitive ones wait for a person, forbidden ones are blocked.

export const CommercialTiers = ({intent}) => {
  const ENDPOINT = 'https://ctrlrun-review-form.vercel.app/api/interest';
  const TIERS = [{
    intent: 'pro-waitlist',
    cta: 'Request early access',
    field: 'agents',
    label: 'What do your agents do?',
    optional: true,
    rows: 2,
    max: 200,
    placeholder: 'For example, a support agent that issues refunds',
    submit: 'Join the waiting list →',
    done: 'You are on the list. We will write to that address when Pro opens up.'
  }, {
    intent: 'enterprise-contact',
    cta: 'Discuss your deployment',
    field: 'message',
    label: 'What does your deployment need?',
    optional: false,
    rows: 3,
    max: 600,
    placeholder: 'Controls, integrations, deployment constraints, timeline',
    submit: 'Send enquiry →',
    done: 'Thank you. We will reply from contact@arpanghoshal.com to arrange a call.'
  }];
  const tier = TIERS.find(candidate => candidate.intent === intent);
  const [open, setOpen] = useState(false);
  const [sent, setSent] = useState(false);
  const [email, setEmail] = useState('');
  const [company, setCompany] = useState('');
  const [detail, setDetail] = useState('');
  const [website, setWebsite] = useState('');
  const [sending, setSending] = useState(false);
  const [error, setError] = useState('');
  const requestId = useRef(null);
  const sendingRef = useRef(false);
  const track = name => window.dispatchEvent(new CustomEvent('ctrlrun:conversion', {
    detail: {
      name
    }
  }));
  if (!tier) return null;
  const eventName = suffix => tier.intent.replace(/-/g, '_') + suffix;
  const openTier = () => {
    setOpen(true);
    setEmail('');
    setCompany('');
    setDetail('');
    setError('');
    requestId.current = null;
    track(eventName('_opened'));
  };
  const send = async event => {
    event.preventDefault();
    if (sendingRef.current || sent) return;
    if (!requestId.current) requestId.current = crypto.randomUUID();
    sendingRef.current = true;
    setSending(true);
    setError('');
    try {
      const payload = {
        intent: tier.intent,
        email,
        company,
        website,
        requestId: requestId.current
      };
      payload[tier.field] = detail;
      const response = await fetch(ENDPOINT, {
        method: 'POST',
        credentials: 'omit',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload),
        signal: AbortSignal.timeout(15000)
      });
      const data = await response.json();
      if (!response.ok || data.ok !== true || typeof data.id !== 'string') throw new Error(data.error || 'We could not confirm submission. Please retry or email us directly.');
      setSent(true);
      track(eventName('_submitted'));
    } catch (failure) {
      setError(failure.name === 'TimeoutError' || failure.name === 'TypeError' ? 'We could not confirm submission. You can retry the same request safely, or email us directly.' : failure.message);
    } finally {
      sendingRef.current = false;
      setSending(false);
    }
  };
  return <div className="cr-tier-action">
      {sent && <p className="cr-tier-done" role="status">{tier.done}</p>}
      {!sent && !open && <button type="button" className="cr-button" onClick={openTier}>{tier.cta} <span aria-hidden="true">→</span></button>}
      {!sent && open && <form className="cr-tier-form" onSubmit={send}>
          <fieldset disabled={sending}>
            <label className="cr-field">Work email<input type="email" autoComplete="email" required maxLength={254} value={email} onChange={event => {
    setEmail(event.target.value);
    setError('');
  }} /></label>
            <label className="cr-field">Company<input autoComplete="organization" required maxLength={100} value={company} onChange={event => {
    setCompany(event.target.value);
    setError('');
  }} /></label>
            <div className="cr-honeypot" aria-hidden="true"><label>Website<input tabIndex={-1} autoComplete="off" value={website} onChange={event => setWebsite(event.target.value)} /></label></div>
            <label className="cr-field">{tier.label}{tier.optional && <span className="cr-caption"> (optional)</span>}<textarea rows={tier.rows} required={!tier.optional} maxLength={tier.max} placeholder={tier.placeholder} value={detail} onChange={event => {
    setDetail(event.target.value);
    setError('');
  }} /></label>
            <button type="submit" className="cr-button">{sending ? 'Sending…' : error ? 'Retry →' : tier.submit}</button>
            <p className="cr-caption">Sent to the CTRLRun team through Resend, only to answer this request. Please leave out credentials and customer data.</p>
          </fieldset>
          {error && <p role="alert" className="cr-form-error">{error} <a href="mailto:contact@arpanghoshal.com">contact@arpanghoshal.com</a></p>}
        </form>}
    </div>;
};

export const HowDiagram = () => <>
    <svg className="cr-diagram cr-dia-wide" viewBox="0 0 1200 418" role="img" aria-labelledby="cr-dia-t cr-dia-d" preserveAspectRatio="xMidYMid meet">
      <title id="cr-dia-t">How CTRLRun works</title>
      <desc id="cr-dia-d">An action leaves the agents, tools and workflows you already run. Inside CTRLRun it is normalized into one action, decided against your rules, held for approval, reserved so it cannot run twice, executed, resolved and recorded. Only then does it reach your systems. An action with no rule is blocked, changed arguments void the approval, and an unknown outcome is never retried.</desc>
      <rect className="cr-dia-strip" x="1" y="1" width="1198" height="54" rx="6" />
      <text className="cr-dia-label" x="24" y="33">YOUR AGENTS, TOOLS AND WORKFLOWS</text>
      <text className="cr-dia-claim" x="390" y="34">An action is about to run.</text>
      <text className="cr-dia-note" x="628" y="34">Any model, any framework. Existing code stays as it is.</text>
      <path className="cr-dia-arrow" d="M600 56V83" />
      <path className="cr-dia-head" d="M595 82h10L600 90Z" />
      <rect className="cr-dia-box" x="1" y="92" width="1198" height="230" rx="6" />
      <text className="cr-dia-label" x="24" y="122">CTRLRun · THE EXECUTION BOUNDARY</text>
      <rect className="cr-dia-node" x="24" y="138" width="144" height="86" rx="5" />
      <text className="cr-dia-num" x="37" y="162">1</text>
      <text className="cr-dia-name" x="37" y="186">Normalize</text>
      <text className="cr-dia-gloss" x="37" y="206">one action, one id</text>
      <path className="cr-dia-arrow" d="M173 181h11" />
      <path className="cr-dia-head" d="M183 176.5l7 4.5-7 4.5Z" />
      <rect className="cr-dia-node" x="192" y="138" width="144" height="86" rx="5" />
      <text className="cr-dia-num" x="205" y="162">2</text>
      <text className="cr-dia-name" x="205" y="186">Decide</text>
      <text className="cr-dia-gloss" x="205" y="206">allow / ask / block</text>
      <path className="cr-dia-arrow" d="M341 181h11" />
      <path className="cr-dia-head" d="M351 176.5l7 4.5-7 4.5Z" />
      <rect className="cr-dia-node" x="360" y="138" width="144" height="86" rx="5" />
      <text className="cr-dia-num" x="373" y="162">3</text>
      <text className="cr-dia-name" x="373" y="186">Approve</text>
      <text className="cr-dia-gloss" x="373" y="206">bound to this action</text>
      <path className="cr-dia-arrow" d="M509 181h11" />
      <path className="cr-dia-head" d="M519 176.5l7 4.5-7 4.5Z" />
      <rect className="cr-dia-node" x="528" y="138" width="144" height="86" rx="5" />
      <text className="cr-dia-num" x="541" y="162">4</text>
      <text className="cr-dia-name" x="541" y="186">Reserve</text>
      <text className="cr-dia-gloss" x="541" y="206">claimed once</text>
      <path className="cr-dia-arrow" d="M677 181h11" />
      <path className="cr-dia-head" d="M687 176.5l7 4.5-7 4.5Z" />
      <rect className="cr-dia-node" x="696" y="138" width="144" height="86" rx="5" />
      <text className="cr-dia-num" x="709" y="162">5</text>
      <text className="cr-dia-name" x="709" y="186">Execute</text>
      <text className="cr-dia-gloss" x="709" y="206">your code runs</text>
      <path className="cr-dia-arrow" d="M845 181h11" />
      <path className="cr-dia-head" d="M855 176.5l7 4.5-7 4.5Z" />
      <rect className="cr-dia-node" x="864" y="138" width="144" height="86" rx="5" />
      <text className="cr-dia-num" x="877" y="162">6</text>
      <text className="cr-dia-name" x="877" y="186">Resolve</text>
      <text className="cr-dia-gloss" x="877" y="206">unknown is not failed</text>
      <path className="cr-dia-arrow" d="M1013 181h11" />
      <path className="cr-dia-head" d="M1023 176.5l7 4.5-7 4.5Z" />
      <rect className="cr-dia-node" x="1032" y="138" width="144" height="86" rx="5" />
      <text className="cr-dia-num" x="1045" y="162">7</text>
      <text className="cr-dia-name" x="1045" y="186">Record</text>
      <text className="cr-dia-gloss" x="1045" y="206">a receipt either way</text>
      <path className="cr-dia-div" d="M24 252H1176" />
      <text className="cr-dia-rule" x="24" y="278">No rule for it</text>
      <text className="cr-dia-rule-note" x="24" y="298">The action is blocked. Silence is never permission.</text>
      <text className="cr-dia-rule" x="418" y="278">Arguments changed after sign-off</text>
      <text className="cr-dia-rule-note" x="418" y="298">The old approval is void. A person signs again.</text>
      <text className="cr-dia-rule" x="812" y="278">Outcome unknown</text>
      <text className="cr-dia-rule-note" x="812" y="298">No retry until a person resolves it. Nothing runs twice on a guess.</text>
      <path className="cr-dia-arrow" d="M600 324V353" />
      <path className="cr-dia-head" d="M595 352h10L600 360Z" />
      <rect className="cr-dia-strip" x="1" y="362" width="1198" height="54" rx="6" />
      <text className="cr-dia-label" x="24" y="394">YOUR SYSTEMS</text>
      <text className="cr-dia-claim" x="252" y="395">The action arrives already checked.</text>
      <text className="cr-dia-note" x="560" y="395">Allowed by your rules, approved where you require it, and never run twice.</text>
    </svg>
    <svg className="cr-diagram cr-dia-narrow" viewBox="0 0 360 748" role="img" aria-labelledby="cr-dia-tn cr-dia-dn" preserveAspectRatio="xMidYMid meet">
      <title id="cr-dia-tn">How CTRLRun works</title>
      <desc id="cr-dia-dn">An action leaves the agents, tools and workflows you already run. Inside CTRLRun it is normalized into one action, decided against your rules, held for approval, reserved so it cannot run twice, executed, resolved and recorded. Only then does it reach your systems. An action with no rule is blocked, changed arguments void the approval, and an unknown outcome is never retried.</desc>
      <rect className="cr-dia-strip" x="1" y="1" width="358" height="76" rx="6" />
      <text className="cr-dia-label" x="16" y="25">YOUR AGENTS, TOOLS AND WORKFLOWS</text>
      <text className="cr-dia-claim" x="16" y="47">An action is about to run.</text>
      <text className="cr-dia-note" x="16" y="66">Any model, any framework. Existing code stays as it is.</text>
      <path className="cr-dia-arrow" d="M180 78V95" />
      <path className="cr-dia-head" d="M175 94h10L180 102Z" />
      <rect className="cr-dia-box" x="1" y="104" width="358" height="536" rx="6" />
      <text className="cr-dia-label" x="16" y="130">CTRLRun · THE EXECUTION BOUNDARY</text>
      <path className="cr-dia-spine" d="M28 150V420" />
      <rect className="cr-dia-node" x="28" y="142" width="316" height="34" rx="4" />
      <text className="cr-dia-num" x="40" y="164">1</text>
      <text className="cr-dia-name" x="58" y="164">Normalize</text>
      <text className="cr-dia-gloss" x="156" y="164">one action, one id</text>
      <rect className="cr-dia-node" x="28" y="184" width="316" height="34" rx="4" />
      <text className="cr-dia-num" x="40" y="206">2</text>
      <text className="cr-dia-name" x="58" y="206">Decide</text>
      <text className="cr-dia-gloss" x="156" y="206">allow / ask / block</text>
      <rect className="cr-dia-node" x="28" y="226" width="316" height="34" rx="4" />
      <text className="cr-dia-num" x="40" y="248">3</text>
      <text className="cr-dia-name" x="58" y="248">Approve</text>
      <text className="cr-dia-gloss" x="156" y="248">bound to this action</text>
      <rect className="cr-dia-node" x="28" y="268" width="316" height="34" rx="4" />
      <text className="cr-dia-num" x="40" y="290">4</text>
      <text className="cr-dia-name" x="58" y="290">Reserve</text>
      <text className="cr-dia-gloss" x="156" y="290">claimed once</text>
      <rect className="cr-dia-node" x="28" y="310" width="316" height="34" rx="4" />
      <text className="cr-dia-num" x="40" y="332">5</text>
      <text className="cr-dia-name" x="58" y="332">Execute</text>
      <text className="cr-dia-gloss" x="156" y="332">your code runs</text>
      <rect className="cr-dia-node" x="28" y="352" width="316" height="34" rx="4" />
      <text className="cr-dia-num" x="40" y="374">6</text>
      <text className="cr-dia-name" x="58" y="374">Resolve</text>
      <text className="cr-dia-gloss" x="156" y="374">unknown is not failed</text>
      <rect className="cr-dia-node" x="28" y="394" width="316" height="34" rx="4" />
      <text className="cr-dia-num" x="40" y="416">7</text>
      <text className="cr-dia-name" x="58" y="416">Record</text>
      <text className="cr-dia-gloss" x="156" y="416">a receipt either way</text>
      <path className="cr-dia-div" d="M28 446H344" />
      <text className="cr-dia-rule" x="28" y="470">No rule for it</text>
      <text className="cr-dia-rule-note" x="28" y="488">The action is blocked.</text>
      <text className="cr-dia-rule-note" x="28" y="504">Silence is never permission.</text>
      <text className="cr-dia-rule" x="28" y="534">Arguments changed after sign-off</text>
      <text className="cr-dia-rule-note" x="28" y="552">The old approval is void.</text>
      <text className="cr-dia-rule-note" x="28" y="568">A person signs again.</text>
      <text className="cr-dia-rule" x="28" y="598">Outcome unknown</text>
      <text className="cr-dia-rule-note" x="28" y="616">No retry until a person resolves it.</text>
      <text className="cr-dia-rule-note" x="28" y="632">Nothing runs twice on a guess.</text>
      <path className="cr-dia-arrow" d="M180 642V661" />
      <path className="cr-dia-head" d="M175 660h10L180 668Z" />
      <rect className="cr-dia-strip" x="1" y="670" width="358" height="76" rx="6" />
      <text className="cr-dia-label" x="16" y="694">YOUR SYSTEMS</text>
      <text className="cr-dia-claim" x="16" y="716">The action arrives already checked.</text>
      <text className="cr-dia-note" x="16" y="735">Allowed by your rules, approved where you require it.</text>
    </svg>
  </>;

export const HomeSlides = () => {
  const SLIDE_MEDIA = '(min-width: 801px) and (hover: hover)';
  const SLIDES = [{
    id: 'overview',
    label: 'Overview'
  }, {
    id: 'how-it-works',
    label: 'How it works'
  }, {
    id: 'pro-and-enterprise',
    label: 'Free, Pro, Enterprise'
  }];
  const LAST = SLIDES.length - 1;
  const [active, setActive] = useState(0);
  const [ready, setReady] = useState(false);
  const activeRef = useRef(0);
  const targetRef = useRef(-1);
  const targetExpiry = useRef(0);
  const currentIndex = () => targetRef.current >= 0 && performance.now() < targetExpiry.current ? targetRef.current : activeRef.current;
  const goTo = index => {
    const slide = document.getElementById(SLIDES[index].id);
    if (!slide) return;
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    targetRef.current = index;
    targetExpiry.current = performance.now() + 1200;
    slide.scrollIntoView({
      behavior: reduced ? 'instant' : 'smooth',
      block: 'start'
    });
  };
  useEffect(() => {
    const root = document.documentElement;
    const home = document.querySelector('.cr-home');
    if (!home) return;
    const sections = SLIDES.map(slide => document.getElementById(slide.id));
    let frame = 0;
    let headerHeight = 64;
    const media = window.matchMedia(SLIDE_MEDIA);
    const updateActive = () => {
      frame = 0;
      let best = 0;
      let visible = -1;
      sections.forEach((section, index) => {
        if (!section) return;
        const rect = section.getBoundingClientRect();
        const amount = Math.max(0, Math.min(rect.bottom, innerHeight) - Math.max(rect.top, headerHeight));
        if (amount > visible) {
          visible = amount;
          best = index;
        }
      });
      activeRef.current = best;
      if (best === targetRef.current) {
        targetRef.current = -1;
        targetExpiry.current = 0;
      }
      setActive(best);
    };
    const onScroll = () => {
      if (!frame) frame = requestAnimationFrame(updateActive);
    };
    const onResize = () => {
      headerHeight = Math.max(0, Math.round(home.getBoundingClientRect().top + window.scrollY));
      if (media.matches) {
        root.style.setProperty('--cr-slide-top', `${headerHeight}px`);
        root.style.setProperty('--cr-slide-height', `${Math.max(240, window.innerHeight - headerHeight)}px`);
      }
      onScroll();
    };
    const onKeyDown = event => {
      if (!media.matches) return;
      if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
      const target = event.target;
      if (target instanceof Element && target.closest('input, textarea, select, video, a, [contenteditable], [role="dialog"], [role="slider"]')) return;
      if (target instanceof Element && target.closest('button') && !target.closest('.cr-slide-dots')) return;
      const current = currentIndex();
      let next;
      if (['ArrowDown', 'ArrowRight', 'PageDown'].includes(event.key)) next = Math.min(LAST, current + 1); else if (['ArrowUp', 'ArrowLeft', 'PageUp'].includes(event.key)) next = Math.max(0, current - 1); else if (event.key === 'Home') next = 0; else if (event.key === 'End') next = LAST; else return;
      event.preventDefault();
      if (!event.repeat) goTo(next);
    };
    const applyMedia = () => {
      if (media.matches) {
        onResize();
        root.classList.add('cr-slides-active');
      } else {
        root.classList.remove('cr-slides-active');
        root.style.removeProperty('--cr-slide-top');
        root.style.removeProperty('--cr-slide-height');
      }
      setReady(media.matches);
    };
    applyMedia();
    media.addEventListener('change', applyMedia);
    window.addEventListener('scroll', onScroll, {
      passive: true
    });
    window.addEventListener('resize', onResize);
    window.addEventListener('keydown', onKeyDown);
    const header = document.getElementById('navbar');
    const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(onResize);
    if (header && observer) observer.observe(header);
    const hashIndex = SLIDES.findIndex(slide => `#${slide.id}` === window.location.hash);
    if (hashIndex >= 0) requestAnimationFrame(() => goTo(hashIndex));
    return () => {
      root.classList.remove('cr-slides-active');
      root.style.removeProperty('--cr-slide-top');
      root.style.removeProperty('--cr-slide-height');
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onResize);
      window.removeEventListener('keydown', onKeyDown);
      media.removeEventListener('change', applyMedia);
      observer?.disconnect();
      cancelAnimationFrame(frame);
    };
  }, []);
  return <nav className="cr-slide-dots" aria-label="Homepage sections" hidden={!ready}>
      {SLIDES.map((slide, index) => <button key={slide.id} type="button" aria-label={`${index + 1}. ${slide.label}`} aria-controls={slide.id} aria-current={active === index ? 'step' : undefined} onClick={() => goTo(index)}>
          <span className="cr-slide-dot-label">{slide.label}</span>
          <span className="cr-slide-dot" aria-hidden="true" />
        </button>)}
    </nav>;
};

<div className="cr-site cr-home">
  <HomeSlides />

  <section id="overview" className="cr-home-hero" aria-labelledby="cr-title">
    <div className="cr-home-pitch">
      <p className="cr-eyebrow">THE AGENT IS PROBABILISTIC. THE ACTION IS NOT.</p>
      <h1 id="cr-title"><span className="cr-mark">CTRLRun</span> stops AI agents from taking wrong, restricted, or malicious actions in your workflows<span className="cr-dot">.</span></h1>
      <p className="cr-lede">Every action is checked against your rules before it runs. Allowed actions go through. Sensitive ones wait for a person. Forbidden ones are blocked.</p>

      <div className="cr-actions">
        <a className="cr-button" href="/protect-my-agent" data-cr-event="protect_my_agent_clicked">Protect my agent <span aria-hidden="true">→</span></a>
        <a className="cr-button cr-github-badge" href="https://github.com/CTRLRun/ctrlrun" data-cr-event="github_clicked"><svg aria-hidden="true" focusable="false" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 .75a11.25 11.25 0 0 0-3.558 21.923c.563.104.77-.244.77-.542 0-.267-.01-.975-.015-1.913-3.13.68-3.79-1.508-3.79-1.508-.513-1.303-1.252-1.65-1.252-1.65-1.023-.7.077-.686.077-.686 1.132.08 1.727 1.162 1.727 1.162 1.006 1.724 2.64 1.226 3.283.938.102-.73.394-1.226.715-1.508-2.498-.284-5.124-1.25-5.124-5.563 0-1.228.44-2.233 1.162-3.02-.116-.285-.504-1.43.11-2.98 0 0 .945-.303 3.094 1.154a10.786 10.786 0 0 1 5.625 0c2.148-1.457 3.09-1.154 3.09-1.154.617 1.55.23 2.695.113 2.98.724.787 1.16 1.792 1.16 3.02 0 4.323-2.63 5.276-5.136 5.555.404.35.765 1.043.765 2.1 0 1.515-.014 2.737-.014 3.11 0 .3.203.65.774.54A11.252 11.252 0 0 0 12 .75Z" /></svg><span>GitHub</span><span aria-hidden="true">↗</span></a>
      </div>

      <p className="cr-hero-oneline"><span>Open source · one line, any action</span><code>{'@ctrlrun.protect("your.action")'}</code></p>
    </div>

    <div className="cr-example-wrap">
      <p className="cr-example-label">ONE EXAMPLE / THE MODEL HALLUCINATES AN AMOUNT</p>

      <div className="cr-failure-chain" aria-labelledby="cr-failure-title">
        <h2 id="cr-failure-title">The model guesses.<br />CTRLRun does not.</h2>

        <div className="cr-chain-setup">
          <p><span>The ticket says</span>refund \$500</p>
          <p><span>The agent asks for</span>\$5,000</p>
        </div>

        <div className="cr-chain">
          <div className="cr-chain-row">
            <span className="cr-chain-label">Without CTRLRun</span>

            <ol className="cr-chain-steps">
              <li>Nothing checks the amount</li><li>The call goes through</li><li className="cr-end cr-bad">\$4,500 too much</li>
            </ol>
          </div>

          <div className="cr-chain-row">
            <span className="cr-chain-label cr-good">With CTRLRun</span>

            <ol className="cr-chain-steps">
              <li>Your rule checks the amount</li><li>The call never leaves</li><li className="cr-end cr-good">\$0 wrongly paid</li>
            </ol>
          </div>
        </div>
      </div>
    </div>

    <div className="cr-any-agent">
      <h2 id="cr-any-agent-title">Works with agents you can and can't modify.</h2>
      <p>WhatsApp, Slack, Teams, Claude Code, Cursor, Codex, ChatGPT, OpenAI Agents. <b>Any AI agent you have.</b> If it acts through your systems, it is checked.</p>
      <a className="cr-any-agent-link" href="/docs/agents-you-cant-modify" data-cr-event="any_agent_clicked">How it works <span aria-hidden="true">→</span></a>
    </div>
  </section>

  <section className="cr-section cr-home-how" id="how-it-works" aria-labelledby="cr-how-title">
    <div className="cr-how-intro">
      <p className="cr-eyebrow">HOW CTRLRUN WORKS</p>
      <h2 id="cr-how-title">Let it run. Ask a human. Or stop it cold.</h2>
      <p className="cr-how-lede">CTRLRun stops an agent from taking an action your rules do not allow. Every action that leaves your agents, tools and workflows is normalized into one action, decided against your policy, held for a person where you require it, reserved so it cannot run twice, executed, resolved and recorded. An action with no rule is blocked, arguments changed after sign-off void the approval, and an outcome nobody knows is never retried on a guess.</p>
    </div>

    <HowDiagram />

    <p className="cr-how-after"><a className="cr-text-link" href="/execution-boundary" data-cr-event="try_clicked">Interactive walkthrough: follow one agent action through every check →</a></p>
  </section>

  <section className="cr-section cr-home-commercial" id="pro-and-enterprise" aria-labelledby="cr-commercial-title">
    <div className="cr-commercial">
      <div className="cr-commercial-head">
        <p className="cr-eyebrow">FREE, PRO, ENTERPRISE</p>
        <h2 id="cr-commercial-title">Free and open source: the boundary. Pro: the boundary, run for you. Enterprise: the boundary, shaped to you.</h2>
      </div>

      <div className="cr-tiers">
        <div className="cr-tier">
          <span className="cr-step">FREE · OPEN SOURCE</span>
          <h3>ctrlrun Open Source</h3>
          <p className="cr-tier-promise">Free. Run it yourself.</p>
          <p className="cr-tier-body">The boundary itself, at no cost. No account, no card, no call with us. Every rule that decides is code you can read, and every action leaves a receipt you keep. Free to use and free to change, under the Apache-2.0 licence.</p>
          <p className="cr-tier-who"><span>Who does the work</span> Your team, on your machines.</p>
          <a className="cr-button" href="/docs/get-started/quickstart" data-cr-event="open_source_install_clicked">Install it <span aria-hidden="true">→</span></a>
        </div>

        <div className="cr-tier">
          <span className="cr-step">IN DEVELOPMENT</span>
          <h3>ctrlrun Pro</h3>
          <p className="cr-tier-promise">Integrate, analyze, protect. One dashboard.</p>
          <p className="cr-tier-body">Connect your agents and workflows and see what each connection covers. Search every action, decision and outcome across your agents. Manage policies and approvals from one place, test a rule in observe mode, then turn enforcement on. Built on the open-source foundation, run by us.</p>
          <p className="cr-tier-who"><span>Who does the work</span> Your team, on our dashboard.</p>

          <CommercialTiers intent="pro-waitlist" />
        </div>

        <div className="cr-tier">
          <span className="cr-step">ENGAGEMENTS OPEN</span>
          <h3>ctrlrun Enterprise</h3>
          <p className="cr-tier-promise">The same product, shaped to your company.</p>
          <p className="cr-tier-body">Everything in Pro, with CTRLRun engineers who design, integrate and maintain the controls your business needs: custom policies and approval chains, connectors to your internal systems, your deployment options, the reports you ask for. Scoped to your requirements, delivered with your team.</p>
          <p className="cr-tier-who"><span>Who does the work</span> Our engineers, with your team.</p>

          <CommercialTiers intent="enterprise-contact" />
        </div>
      </div>
    </div>

    <div className="cr-footer" role="contentinfo"><span>Let agents act.<br /><strong>Keep the consequences yours to decide.</strong></span><div><a href="/docs" data-cr-event="documentation_clicked">Docs →</a><a href="https://github.com/CTRLRun/ctrlrun" data-cr-event="github_clicked">GitHub ↗</a><a href="mailto:contact@arpanghoshal.com?subject=CTRLRun" data-cr-event="contact_email_clicked">Contact ↗</a></div></div>
  </section>
</div>
