Back to blog

Native SSH for Comma agents

Get startedRead the docs

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

Try Comma, Now.

Get started