---
title: "Native SSH for Comma agents · Comma Blog"
description: "The agent stays in the harness and reaches your machines over SSH, by public address, through Tailcat, or through your own tailnet."
url: https://comma.surf/en-gb/blog/native-ssh
language: en-GB
---

[Back to blog](https://comma.surf/en-gb/blog)

19 October 2026

# Native SSH for Comma agents

[Get started](https://app.comma.surf/) [Read the docs](https://comma.surf/en-gb/docs/salix/agent-runtimes)

Your home server has stopped finishing its nightly backup. The logs are on the server, the server is behind your router, and you want [Comma](https://comma.surf/en-gb/) to find out what happened, not give you a list of commands to copy back and forth. Comma’s agents can now work on that machine over SSH, without installing another AI agent on it.

## The agent lives outside the sandbox

Most cloud agents run inside their sandbox: a container or VM that holds the model loop, the tools and the files, and stays on for as long as the agent does. Salix, the distributed harness behind Comma, splits these apart. The agent loop runs in the harness, outside any sandbox, at more than 100 agents per CPU core. A cloud VM or a device is a place where commands run, used only when the work needs a computer.

So to work on your server, the agent does not move there. It calls native SSH tools from the harness:

- `ssh.open`, `ssh.write`, `ssh.read` and `ssh.screen` for an interactive terminal, including full-screen programs;
- `ssh.exec` for one command, with stdout, stderr and the exit status kept separate;
- `ssh.list_files`, `ssh.download` and `ssh.upload` for files, over SFTP;
- `ssh.close` and `ssh.list` for the connection lifecycle.

The agent authenticates with a **Group SSH key**: one key per workspace, shared by its agents. `ssh.public_key` returns it, and you add it to `~/.ssh/authorized_keys` on the machine, as you would for any other SSH client.

The harness can reach your machine in three ways.

## 1. A public address

If the machine already has a reachable SSH server, the agent connects to its IP address or DNS name:

json

```
{ "tool": "ssh.open", "params": { "host": "203.0.113.10", "user": "deploy" } }
```

## 2. Tailcat, for a machine with no public address

A laptop or a home server behind NAT often has no address that the harness can dial. [Tailcat](https://github.com/tailscale/tailcat) connects it without an inbound port, a VPN or an account. It runs on the machine, makes outbound connections only, and prints an address that starts with `tc`.

Tailcat can also be the SSH server. Run it with the Group public key:

sh

```
tailcat serve --ssh-authorized-keys='ssh-ed25519 AAAA...' ssh
```

This gives a login shell, command execution and SFTP as the account that runs Tailcat. It needs no `sshd` and does not change your SSH configuration. If the machine already runs OpenSSH, use `tailcat serve 22` instead, and OpenSSH handles the login. Then send the address to the agent:

json

```
{ "tool": "ssh.open", "params": { "tailcat": "tc...", "user": "deploy" } }
```

## 3. Your own Tailscale network

If your machines are already in a tailnet, the workspace can join it. Connect it in the Comma app settings, or ask the agent to. A tailnet admin opens a login link and approves the node. The node uses the tag `tag:comma-agent` by default, so your tailnet policy decides exactly which devices and ports it can reach, for example only port 22 on the home server.

The agent lists devices with `tailnet.peers` and connects by MagicDNS name or Tailscale address:

json

```
{
  "tool": "ssh.open",
  "params": { "host": "nas.tail1234.ts.net", "via_tailnet": true, "user": "deploy" }
}
```

## Trust and lifetime

On every path, the first connection to a host records its host key. A later connection that presents a different key is refused with `host_key_mismatch` and both fingerprints, and the agent asks you before it removes the old key with `ssh.known_hosts.remove`.

An SSH connection belongs to one agent session. It closes after 30 minutes without use and does not survive an agent restart or a platform deploy, so long work belongs in `tmux` or `screen` on the remote machine. Commands are bounded: `ssh.exec` times out after 60 seconds by default and 600 at most, and a timeout is reported, never retried automatically.

For the backup, you might ask: “Read the logs and check disk space, but do not delete files or change the configuration. Tell me what you find first.”

[Back to blog](https://comma.surf/en-gb/blog)

## Try Comma, Now.

[Get started](https://app.comma.surf/)
