# How Jenkins Manages Distributed Builds with Computer, Node, and JnlpSlaveAgentProtocol

> Learn how Jenkins manages distributed builds using Computer, Node, and JnlpSlaveAgentProtocol to connect agents and distribute workloads efficiently for faster CI/CD.

- Repository: [Jenkins/jenkins](https://github.com/jenkinsci/jenkins)
- Tags: internals
- Published: 2026-07-28

---

**Jenkins distributes builds across remote machines by representing each agent as a `Computer` instance and establishing a bi-directional remoting channel through the JNLP Slave-Agent Protocol.**

Jenkins enables scalable continuous integration by delegating build workloads from the master to remote agents. In the jenkinsci/jenkins core codebase, this master-agent architecture is implemented through the interaction of `Node`, `Computer`, and JNLP launcher classes. Understanding how Jenkins distributed builds function at the source level helps administrators diagnose connectivity failures, secure agent secrets, and optimize executor allocation.

## The Relationship Between Node, Slave, and Computer

When an administrator adds an agent in the Jenkins UI or via the REST API, Jenkins persists a `hudson.model.Slave` record that stores static configuration such as labels, remote filesystem root, and launch method. At runtime, Jenkins creates a corresponding `Computer` subclass—typically `hudson.slaves.SlaveComputer` defined in [`core/src/main/java/hudson/slaves/SlaveComputer.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/slaves/SlaveComputer.java)—to represent the live execution environment. The abstract base class `hudson.model.Computer` in [`core/src/main/java/hudson/model/Computer.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/model/Computer.java) defines executor management and channel state, while `hudson.model.ComputerSet` in [`core/src/main/java/hudson/model/ComputerSet.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/model/ComputerSet.java) aggregates every `Computer` for the scheduler and UI.

## How JnlpSlaveAgentProtocol4 Establishes the Master-Agent Channel

The actual communication channel is provided by the JNLP Slave-Agent Protocol. On the master side, the modern implementation lives in `jenkins.slaves.JnlpSlaveAgentProtocol4` at [`core/src/main/java/jenkins/slaves/JnlpSlaveAgentProtocol4.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/jenkins/slaves/JnlpSlaveAgentProtocol4.java). This class implements the default **JNLP4-connect** protocol, which superseded the legacy `jenkins.slaves.JnlpSlaveAgentProtocol` (JNLP1) now removed in recent Jenkins versions.

When an agent is configured to use JNLP, the master advertises a URL such as `http://<master>/computer/<node>/jenkins-agent.jnlp`. The file is generated by `jenkins.slaves.EncryptedSlaveAgentJnlpFile` in [`core/src/main/java/jenkins/slaves/EncryptedSlaveAgentJnlpFile.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/jenkins/slaves/EncryptedSlaveAgentJnlpFile.java) and contains the master’s public key, the per-node agent secret, and the classpath jars required by the agent process. The helper class `jenkins.slaves.DefaultJnlpSlaveReceiver` in [`core/src/main/java/jenkins/slaves/DefaultJnlpSlaveReceiver.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/jenkins/slaves/DefaultJnlpSlaveReceiver.java) validates the inbound connection and instantiates the remoting `Channel` once the agent authenticates.

## Inside JNLPLauncher: Launching the Agent Process

The `hudson.slaves.JNLPLauncher` class in [`core/src/main/java/hudson/slaves/JNLPLauncher.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/slaves/JNLPLauncher.java) orchestrates the agent startup. Its `launch(SlaveComputer c, TaskListener listener)` method resolves the inbound URL, downloads the required jars, and constructs the command line that starts the agent JVM.

```java
// Simplified flow in JNLPLauncher
public class JNLPLauncher extends ComputerLauncher {
    @Override public void launch(SlaveComputer c, TaskListener listener) throws IOException, InterruptedException {
        // 1. Resolve inbound URL (custom or default)
        URL inbound = getInboundAgentUrl(c);
        // 2. Download agent.jar (or use already‑installed copy)
        // 3. Start the Java process:
        //    java -jar agent.jar -jnlpUrl <inbound> -secret <secret>
        // 4. Attach the socket to the master’s Channel (remoting)
    }
}

```

After the remote JVM starts, it opens a TCP socket back to the master. On the master side, `SlaveComputer` accepts this socket and wraps it in a `hudson.remoting.Channel`, enabling remote procedure calls for build execution and log streaming.

## The Remoting Channel and Executor Allocation

Once the socket is established, `SlaveComputer` creates the `Channel` that serves as the pipeline for all master-agent communication. The master’s `Queue` then assigns `Executor` objects to the `Computer`, dispatching build steps remotely over the channel. Because the channel is bi-directional, the master can stream console output, copy artifacts, and execute shell steps while the agent reports status back to the master.

## Security, Secrets, and WebSocket Transport

Security for Jenkins distributed builds relies on a per-node **agent secret** embedded in the JNLP file and passed as the `-secret` argument. Administrators may also enforce SSL/TLS on the Jenkins master to encrypt traffic in transit.

Since Jenkins 2.263, agents can optionally upgrade the connection to a WebSocket channel, which simplifies firewall traversal by using standard HTTP ports. When launching with the `-webSocket` flag, the agent requests this upgrade, which the master honors when `JNLPLauncher.DescriptorImpl.isWebSocketSupported()` returns `true`. This transport reduces latency in environments that restrict raw TCP outbound connections.

## Programmatic and Command-Line Agent Management

Administrators can provision JNLP agents via Groovy scripts or command-line tools.

To create a node programmatically:

```groovy
import hudson.model.Node
import hudson.slaves.DumbSlave
import hudson.slaves.JNLPLauncher
import hudson.slaves.RetentionStrategy

def name = "remote‑linux"
def remoteFS = "/home/jenkins"
def numExecutors = 2
def mode = Node.Mode.NORMAL
def labels = "linux"

def launcher = new JNLPLauncher()               // defaults to JNLP4‑connect
def retention = RetentionStrategy.NOOP         // keep it always online

def slave = new DumbSlave(name, null, remoteFS,
                          numExecutors.toString(),
                          mode, labels,
                          launcher, retention,
                          Collections.emptyList())

Jenkins.instance.addNode(slave)
println "Node '${name}' added – start the agent with:\njava -jar agent.jar -jnlpUrl http://<master>/computer/${name}/jenkins-agent.jnlp -secret <secret>"

```

To launch the agent manually from the command line:

```bash

# 1. Download the agent jar from the master

curl -O http://jenkins.example.com/jnlpJars/agent.jar

# 2. Start the agent, letting it fetch the JNLP URL automatically

java -jar agent.jar -jnlpUrl http://jenkins.example.com/computer/my‑node/jenkins-agent.jnlp -secret <agent‑secret>

```

To use the WebSocket transport:

```bash
java -jar agent.jar -jnlpUrl http://jenkins.example.com/computer/my‑node/jenkins-agent.jnlp \
                    -webSocket -secret <agent‑secret>

```

## Summary

- **`Node`/`Slave`** stores static agent configuration, while **`Computer`**/`SlaveComputer` manages the live runtime state and executors.
- **`JnlpSlaveAgentProtocol4`** provides the default modern protocol for master-agent communication, replacing the legacy JNLP1 implementation.
- **`JNLPLauncher.launch()`** constructs the agent command line, downloads required jars, and initiates the connection back to the master.
- **`SlaveComputer`** wraps the inbound socket in a remoting `Channel` that the Jenkins `Queue` uses to dispatch builds and stream logs.
- **Security** is enforced via a per-node secret and optional SSL/TLS; **WebSocket mode** (available since Jenkins 2.263) can improve connectivity through restrictive firewalls.

## Frequently Asked Questions

### What is the difference between a Node and a Computer in Jenkins?

A `Node`—concretely `hudson.model.Slave`—represents the static definition of an agent, including its labels, remote root directory, and launch method. A `Computer`—concretely `hudson.slaves.SlaveComputer`—is the runtime counterpart that tracks whether the agent is online, how many executors are idle, and holds the active remoting `Channel`.

### How does JNLPLauncher differ from SSH-based launchers?

`JNLPLauncher` requires the agent to initiate the connection back to the master by requesting the JNLP file and opening a TCP socket. In contrast, SSH launchers such as `hudson.plugins.sshslaves.SSHLauncher` push the agent start command from the master to the remote host over SSH. JNLP is preferable when agents reside behind NAT or firewalls that block inbound SSH.

### What JNLP protocol version does Jenkins use by default?

Modern Jenkins versions default to **JNLP4-connect**, implemented in `jenkins.slaves.JnlpSlaveAgentProtocol4`. The legacy `jenkins.slaves.JnlpSlaveAgentProtocol` (JNLP1) has been removed from recent releases.

### Can a JNLP agent reconnect automatically if the network drops?

Yes. `JNLPLauncher` and the underlying remoting engine support automatic reconnection. If the TCP or WebSocket channel drops, the agent process can retry the connection using the same JNLP URL and secret until the master responds, minimizing manual intervention for transient network failures.