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

# The Orchestrator Role in the Livepeer Network

> What orchestrators are, how they fit into the Livepeer compute network, and how the role has evolved from video transcoding to AI inference.

export const CenteredContainer = ({children, maxWidth = "800px", padding = "0", preset = "default", width = "", minWidth = "", marginRight = "", marginBottom = "", textAlign = "", style = {}, className = "", ...rest}) => {
  const presets = {
    default: {},
    fitContent: {
      width: "fit-content",
      minWidth: "fit-content"
    },
    readable70: {
      width: "70%",
      minWidth: "fit-content"
    },
    readable80: {
      width: "80%",
      minWidth: "fit-content"
    },
    readable90: {
      width: "90%"
    },
    wide900: {
      maxWidth: "900px"
    }
  };
  const presetStyle = presets[preset] || presets.default;
  return <div className={className} style={{
    maxWidth: presetStyle.maxWidth || maxWidth,
    margin: "0 auto",
    padding: padding,
    ...presetStyle.width ? {
      width: presetStyle.width
    } : {},
    ...presetStyle.minWidth ? {
      minWidth: presetStyle.minWidth
    } : {},
    ...width ? {
      width
    } : {},
    ...minWidth ? {
      minWidth
    } : {},
    ...marginRight ? {
      marginRight
    } : {},
    ...marginBottom ? {
      marginBottom
    } : {},
    ...textAlign ? {
      textAlign
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

export const ScrollableDiagram = ({children, title = '', maxHeight = '500px', minWidth = '100%', showControls = false, className = '', style = {}, ...rest}) => {
  const buildDiagramKey = (currentTitle = '', currentClassName = '') => {
    const source = `${currentTitle}|${currentClassName}|scrollable-diagram`;
    let hash = 0;
    for (let index = 0; index < source.length; index += 1) {
      hash = hash * 31 + source.charCodeAt(index) >>> 0;
    }
    return `docs-diagram-${hash.toString(36)}`;
  };
  const diagramKey = buildDiagramKey(title, className);
  const zoomName = `${diagramKey}-zoom`;
  const zoomLevels = [{
    label: '75%',
    value: 0.75
  }, {
    label: '100%',
    value: 1
  }, {
    label: '125%',
    value: 1.25
  }, {
    label: '150%',
    value: 1.5
  }];
  const containerStyle = {
    overflow: 'auto',
    maxHeight,
    border: '1px solid var(--lp-color-border-default)',
    borderRadius: "8px",
    padding: "var(--lp-spacing-4)",
    background: 'var(--lp-color-bg-card)',
    position: 'relative'
  };
  return <div className={className} style={{
    position: 'relative',
    marginBottom: "var(--lp-spacing-4)",
    ...style
  }} {...rest}>
      {title && <p style={{
    textAlign: 'center',
    fontStyle: 'italic',
    color: 'var(--lp-color-text-secondary)',
    marginBottom: "var(--lp-spacing-2)",
    fontSize: '0.875rem'
  }}>
          {title}
        </p>}

      {showControls ? <style>{`
          [data-docs-diagram-key="${diagramKey}"] [data-docs-diagram-content] {
            transform: scale(1);
            transform-origin: top left;
            width: max-content;
          }
          ${zoomLevels.map(zoomLevel => `
          #${diagramKey}-${zoomLevel.label.replace('%', '')}:checked ~ [data-docs-diagram-shell] [data-docs-diagram-content] {
            transform: scale(${zoomLevel.value});
          }
          #${diagramKey}-${zoomLevel.label.replace('%', '')}:checked ~ [data-docs-diagram-controls] label[for="${diagramKey}-${zoomLevel.label.replace('%', '')}"] {
            background: var(--lp-color-accent);
            color: var(--lp-color-on-accent);
            border-color: var(--lp-color-accent);
          }`).join('\n')}
        `}</style> : null}

      {showControls ? zoomLevels.map(zoomLevel => {
    const inputId = `${diagramKey}-${zoomLevel.label.replace('%', '')}`;
    return <input key={inputId} id={inputId} type="radio" name={zoomName} defaultChecked={zoomLevel.value === 1} style={{
      position: 'absolute',
      opacity: 0,
      pointerEvents: 'none'
    }} />;
  }) : null}

      <div data-docs-diagram-key={diagramKey} data-docs-diagram-shell style={containerStyle}>
        <div data-docs-diagram-content style={{
    minWidth,
    transformOrigin: 'top left',
    width: 'max-content'
  }}>
          {children}
        </div>
      </div>

      {showControls ? <div data-docs-diagram-controls style={{
    display: 'flex',
    justifyContent: 'flex-end',
    alignItems: 'center',
    gap: "var(--lp-spacing-2)",
    marginTop: "var(--lp-spacing-2)",
    flexWrap: 'wrap'
  }}>
          <span style={{
    fontSize: "0.75rem",
    color: 'var(--lp-color-text-muted)',
    marginRight: 'auto'
  }}>
            Scroll to pan
          </span>
          {zoomLevels.map(zoomLevel => {
    const inputId = `${diagramKey}-${zoomLevel.label.replace('%', '')}`;
    return <label key={inputId} htmlFor={inputId} style={{
      background: 'transparent',
      color: 'var(--lp-color-text-secondary)',
      border: '1px solid var(--lp-color-border-default)',
      borderRadius: "4px",
      padding: '4px 10px',
      cursor: 'pointer',
      fontSize: "0.75rem",
      fontWeight: '600'
    }}>
                {zoomLevel.label}
              </label>;
  })}
        </div> : null}
    </div>;
};

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

export const TableCell = ({children, align = "left", header = false, style = {}, className = "", ...rest}) => {
  const Component = header ? "th" : "td";
  return <Component className={className} style={{
    padding: "0.75rem 1rem",
    textAlign: align,
    border: header ? "none" : "1px solid var(--lp-color-border-default)",
    ...style
  }} {...rest}>
      {children}
    </Component>;
};

export const TableRow = ({children, header = false, hover = false, style = {}, className = "", ...rest}) => {
  const rowId = `table-row-${Math.random().toString(36).substr(2, 9)}`;
  return <>
      {hover && <style>{`
          #${rowId}:hover {
            background-color: var(--lp-color-bg-card);
          }
        `}</style>}
      <tr id={rowId} className={className} style={{
    ...header && ({
      backgroundColor: "var(--lp-color-accent-strong)",
      color: "var(--lp-color-on-accent)",
      fontWeight: "bold"
    }),
    ...style
  }} {...rest}>
        {children}
      </tr>
    </>;
};

export const StyledTable = ({children, variant = "default", style = {}, className = "", ...rest}) => {
  const wrapperVariants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)",
      overflow: "hidden"
    },
    bordered: {
      border: "2px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-page)",
      overflow: "hidden"
    },
    minimal: {
      border: "none",
      backgroundColor: "transparent",
      overflow: "visible"
    }
  };
  return <div data-docs-styled-table-shell className={className} style={{
    width: "100%",
    padding: 0,
    margin: 0,
    ...wrapperVariants[variant],
    ...style
  }} {...rest}>
      <table data-docs-styled-table style={{
    width: "100%",
    borderCollapse: "collapse",
    borderSpacing: 0,
    margin: 0,
    backgroundColor: "transparent"
  }}>
        {children}
      </table>
    </div>;
};

export const LinkArrow = ({href, label, description, newline = true, borderColor, className = '', style = {}, ...rest}) => {
  const linkArrowStyle = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: "var(--lp-spacing-1)",
    width: 'fit-content',
    ...borderColor && ({
      borderColor
    })
  };
  return <span className={className} style={style} {...rest}>
      {newline && <br />}
      <span style={linkArrowStyle}>
        <a href={href} target="_blank" rel="noopener noreferrer">
          {label}
        </a>
        <Icon icon="arrow-up-right" size={14} color="var(--lp-color-accent)" />
      </span>
      {description && description}
      {description && <div style={{
    height: "var(--lp-spacing-3)"
  }} />}
    </span>;
};

<CenteredContainer maxWidth="90%" minWidth="fit-content">
  <AccordionGroup>
    <Accordion title="From a Cloud Background?" icon="cloud">
      Running an Orchestrator feels like operating a managed GPU service in a decentralised market.

      Livepeer Gateways select your node based on price, capability,
      and stake weight. You advertise what you can run and at what price; the network sends you jobs.

      <ScrollableDiagram title="Orchestrator as Managed GPU Node">
        ```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
        %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
        flowchart LR
            subgraph Cloud["Cloud Analogy"]
                A["Cloud Provider<br/>• Allocates compute<br/>• Sets capacity<br/>• Charges per job"]
            end

            subgraph Livepeer["Livepeer Network"]
                B["Orchestrator Node<br/>• Advertises GPU capacity<br/>• Sets own price<br/>• Earns ETH per job"]
            end

            subgraph WorkSrc["Work Sources"]
                C["Gateways<br/>• Route jobs by price + capability<br/>• Pay per segment or pixel"]
            end

            WorkSrc -->|Job + payment ticket| Livepeer
            Livepeer -->|Result| WorkSrc

            classDef default fill:#1a1a1a,color:#fff,stroke:#2d9a67,stroke-width:2px
        ```
      </ScrollableDiagram>
    </Accordion>

    <Accordion title="From an Ethereum Background?" icon="coin">
      Running an Orchestrator is closer to being a validator on a proof-of-stake chain than to running a simple
      Ethereum node - but the work is compute instead of consensus.

      You stake LPT to signal commitment and earn the right to enter the **Active Set** (the top 100 eligible
      Orchestrators by total stake). From there, you earn ETH service fees for every job you process, plus LPT
      inflation rewards for calling rewards each round. Slash risk comes from performance failures and protocol behaviour.

      <ScrollableDiagram title="Orchestrator vs Ethereum Validator">
        ```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
        %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
        flowchart LR
            subgraph ETH["Ethereum Validator"]
                A["Stake ETH<br/>→ Participate in consensus<br/>→ Earn block rewards"]
            end
            subgraph LP["Livepeer Orchestrator"]
                B["Stake LPT<br/>→ Enter active set<br/>→ Process compute jobs<br/>→ Earn ETH fees + LPT rewards"]
            end

            classDef default fill:#1a1a1a,color:#fff,stroke:#2d9a67,stroke-width:2px
        ```
      </ScrollableDiagram>
    </Accordion>

    <Accordion title="Neither? Here's the clearest mental model." icon="microchip">
      Think of an Orchestrator as a **GPU-for-hire on a decentralised marketplace**.

      You connect your GPU to the network, tell it what jobs you can run and at what price, and the network sends
      you work from applications that need video transcoded or AI models run. You earn ETH for each completed job
      and LPT rewards for participating in the protocol each round.

      <ScrollableDiagram title="Orchestrator as GPU Marketplace Node">
        ```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
        %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
        flowchart LR
            subgraph You["You (Operator)"]
                A["GPU Hardware<br/>• Advertise capabilities<br/>• Set price<br/>• Stay online"]
            end
            subgraph Net["The Network"]
                B["Livepeer Protocol<br/>• Matches jobs to nodes<br/>• Processes payments<br/>• Distributes rewards"]
            end
            subgraph Earn["You Earn"]
                C["ETH fees (per job)<br/>+ LPT rewards (per round)"]
            end

            You -->|Stake LPT + register| Net
            Net -->|Jobs + ETH tickets| You
            You -->|Completed work| Net
            Net --> Earn

            classDef default fill:#1a1a1a,color:#fff,stroke:#2d9a67,stroke-width:2px
        ```
      </ScrollableDiagram>
    </Accordion>
  </AccordionGroup>
</CenteredContainer>

<CenteredContainer maxWidth="900px">
  ```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
  %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
  timeline
      2017-2020 : Transcoder era
                 : Video-only workloads
                 : RTMP + HLS pipeline
                 : LPT staking model launched
      2021-2023 : Orchestrator model
                 : O-T split introduced
                 : Delegator ecosystem grows
                 : Active set of top-100 established
      Q3 2024   : AI subnet launches
                 : Batch inference pipelines
                 : AIServiceRegistry contract
                 : GPU demand diversifies
      Today     : Unified Orchestrator role
                 : Video + AI + Cascade
                 : BYOC container support
                 : Dual-workload operation
  ```
</CenteredContainer>

<CustomDivider />

## Technical Role

An Orchestrator is the **compute supply layer** of the Livepeer Network. It accepts jobs from Gateways,
routes them to GPU workers, executes the work, and returns results. Orchestrators perform the actual
processing - transcoding video frames, running AI inference pipelines, executing BYOC containers.

Core responsibilities:

* **Job execution** - receive segments or inference requests from Gateways and route them to GPU workers
* **Capability advertisement** - broadcast supported pipelines, models, GPU types, and price per unit
* **Payment receipt** - collect probabilistic micropayment tickets per segment or pixel from Gateways
* **Reward calling** - trigger the protocol reward mechanism each round to claim LPT inflation rewards
* **Worker management** - coordinate transcoder workers (video) and AI runners (inference)

See <LinkArrow href="/v2/orchestrators/concepts/capabilities" label="Orchestrator Capabilities" newline={false} /> for the full set of workloads Orchestrators can execute.

<CustomDivider />

## Network Role

Orchestrators are the **supply side** of the Livepeer marketplace. Where Gateways aggregate application
demand, Orchestrators provide the GPU compute that fulfils it.

* **Active Set participation** - only the top 100 Orchestrators by total bonded stake are eligible to receive
  work in any given round
* **Staking and security** - LPT staked to an Orchestrator signals economic commitment; Delegators extend
  this stake in exchange for a share of earnings
* **Governance** - Orchestrators participate in protocol governance via LPT voting weight
* **Capability discovery** - Orchestrators register capabilities and prices on-chain so Gateways can find them
  via the ServiceRegistry contract on Arbitrum

```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
flowchart LR
    A["Delegators"] -->|"Bond LPT<br/>(earn cut of rewards)"| B["Orchestrator"]
    B -->|"Process jobs"| C["Gateways"]
    C -->|"ETH payment tickets"| B
    B -->|"Call rewards"| D["Protocol<br/>(LPT rewards)"]

    classDef default fill:#1a1a1a,color:#fff,stroke:#2d9a67,stroke-width:2px
```

<Note>
  Orchestrators interact with the **BondingManager**, **RoundsManager**, **TicketBroker**, and
  **ServiceRegistry** contracts on Arbitrum. Gateways interact only with TicketBroker and ServiceRegistry.
  This protocol depth is what distinguishes the Orchestrator role from the Gateway role.
</Note>

<CustomDivider />

## Deployment Types

Orchestrators run in five common configurations. Choose the setup that matches your hardware scale,
workload mix, and operating model.

<StyledTable variant="bordered">
  <thead>
    <TableRow header>
      <TableCell header>Setup type</TableCell>
      <TableCell header>What it means</TableCell>
      <TableCell header>Best for</TableCell>
    </TableRow>
  </thead>

  <tbody>
    <TableRow>
      <TableCell>**Solo operator**</TableCell>
      <TableCell>One Orchestrator process on one machine; handles both routing and GPU work</TableCell>
      <TableCell>Single GPU operators getting started</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**O-T split**</TableCell>
      <TableCell>Orchestrator and Transcoder run as separate processes, optionally on separate machines</TableCell>
      <TableCell>Multi-GPU operators optimising for throughput</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**Pool worker**</TableCell>
      <TableCell>GPU hardware registered under a pool Orchestrator; the pool handles staking and on-chain management</TableCell>
      <TableCell>Operators who want to earn without managing LPT staking</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**Pool operator**</TableCell>
      <TableCell>Operates the Orchestrator node; accepts registered workers who contribute GPUs under the pool's stake</TableCell>
      <TableCell>Operators building multi-node infrastructure businesses</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**Siphon setup**</TableCell>
      <TableCell>A lightweight Orchestrator that routes jobs to an upstream Orchestrator while maintaining a separate on-chain identity</TableCell>
      <TableCell>Advanced operators with existing infrastructure or managed services</TableCell>
    </TableRow>
  </tbody>
</StyledTable>

See the <LinkArrow href="/v2/orchestrators/navigator" label="Navigator" newline={false} /> to find the right setup path for your goals and hardware.

<CustomDivider />

## Who Should Operate One

Orchestrators are infrastructure operators, not application builders. The role requires sustained uptime,
GPU hardware investment, and protocol participation (LPT staking or pool membership).

<AccordionGroup>
  <Accordion title="The Miner - Can I earn from my GPU?" icon="microchip">
    Existing GPU operators can direct spare capacity at video transcoding or AI inference and earn ETH for the work.

    Start with the <LinkArrow href="/v2/orchestrators/concepts/incentive-model" label="Incentive Model" newline={false} /> to understand what earnings look like for your hardware tier.
  </Accordion>

  <Accordion title="The Easy Earner - Simplest path?" icon="bolt">
    Joining an existing pool is the fastest path when you want to participate without managing LPT staking or
    on-chain activation. Bring GPU hardware; the pool handles the rest.

    See <LinkArrow href="/v2/orchestrators/guides/deployment-details/join-a-pool" label="Join a Pool" newline={false} /> for options.
  </Accordion>

  <Accordion title="The Pro Operator - Adding AI to an existing setup?" icon="server">
    Operators who already run video transcoding can add AI inference workloads from the same node.
    New capabilities are advertised automatically once configured.

    See <LinkArrow href="/v2/orchestrators/concepts/capabilities" label="Orchestrator Capabilities" newline={false} /> for the workload overview.
  </Accordion>

  <Accordion title="The Business - Building at scale?" icon="building">
    Commercial Orchestrators serving application workloads (Daydream, Livepeer Studio, other products)
    operate differently from solo GPU miners. The incentives, pricing strategy, and operational
    requirements differ significantly.

    See <LinkArrow href="/v2/orchestrators/concepts/incentive-model" label="Incentive Model" newline={false} /> for the revenue model breakdown.
  </Accordion>
</AccordionGroup>

<CustomDivider />

## Related Pages

<CardGroup cols={2}>
  <Card title="Orchestrator Capabilities" icon="gears" href="/v2/orchestrators/concepts/capabilities" arrow horizontal>
    Workload types, execution boundaries, and Gateway selection signals.
  </Card>

  <Card title="Orchestrator Architecture" icon="diagram-project" href="/v2/orchestrators/concepts/architecture" arrow horizontal>
    How Orchestrators connect to Gateways, the protocol layer, and GPU workers.
  </Card>

  <Card title="Incentive Model" icon="coins" href="/v2/orchestrators/concepts/incentive-model" arrow horizontal>
    Revenue streams, cost structure, and why operating an Orchestrator earns.
  </Card>

  <Card title="Navigator" icon="compass" href="/v2/orchestrators/navigator" arrow horizontal>
    Find the right setup path for your hardware, goals, and experience level.
  </Card>
</CardGroup>
