Vis

Running a gateway

Run a gateway when you want the Vis app, your scripts and other clients to share one agent service. The gateway owns sessions and runs tools on its machine; clients send requests and follow progress. You can run it in your terminal or keep it running under a service manager.

Install the runtime

On the machine that will run the agent, install the native release:

curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash

The installer places vis-agent and its companion runtime files under ~/.local/bin. Put that directory on PATH, then check vis-agent --version. Native releases do not require Java; the Python SDK package alone is not an engine installation. See Runtime distributions for supported platforms, release tracks and updates.

Run Vis interactively once as the account that will own the service. Configure a provider and model, complete any sign-in and try a task in the intended project. The service needs that account's configuration, credentials, writable state directory and access to the project. Connecting from a laptop does not transfer the laptop's files or credentials to the server.

Start a local gateway

Choose an unused port and start the gateway in a terminal:

vis-agent gateway start --host 127.0.0.1 --port 7890 --require-token

This runs in the foreground until you stop it; leave the terminal open. In another terminal, run vis-agent gateway status, then connect your Python or JVM program to http://127.0.0.1:7890. If a gateway is already running, check its status and port before starting another; do not stop a shared gateway just to try an example.

--require-token enables authentication even on loopback. The default token file is ~/.vis/gateway.token and is restricted to its owner; --token-file selects another location. Treat this token as access to an agent that can run tools. Keep it out of source control, logs, screenshots and command arguments. The CLI can use the local token automatically; an SDK client needs its documented connection settings.

An automatically started gateway can exit when it has no clients or active work. Explicit gateway start is different: it stays running without clients, which is the mode to use under a supervisor.

Connect from another machine

For a remote client, use a trusted VPN, an SSH tunnel or HTTPS with a trusted certificate. Do not send bearer tokens over plain HTTP on an untrusted network. Keep the gateway bound to loopback when a tunnel or reverse proxy provides the remote entry point.

For example, forward a local port to a gateway on your server:

ssh -N -L 7891:127.0.0.1:7890 visgw@gateway.example.com

Keep that tunnel open and point the SDK at http://127.0.0.1:7891. Authentication is still required. For HTTPS, use an origin such as https://gateway.example.com with no path prefix if you use the Python SDK. Your proxy must forward authorization headers and let server-sent events stream without buffering or short idle timeouts.

Supply the token through your application's secret configuration. Pairing links and QR codes also contain connection credentials: generate or view them only in a private terminal, and do not use them as public examples. See remote app connections for pairing the Vis app.

Keep it running on Linux

A service manager should own a foreground gateway, not a Python program that repeatedly calls LocalEngine. LocalEngine is for a private child process with temporary session history, not a persistent HTTP service.

The following systemd example uses an account named visgw. Before enabling it, create that account, install Vis for it, prepare /srv/vis-project and complete provider setup as that account. The account must own its state directory and have only the project permissions it needs. Adapt paths to your machine; installing a unit alone does not prepare these prerequisites.

Save the unit as /etc/systemd/system/vis-gateway.service:

[Unit]
Description=Vis agent gateway
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=visgw
Group=visgw
WorkingDirectory=/srv/vis-project
Environment=HOME=/home/visgw
Environment=PATH=/home/visgw/.local/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/home/visgw/.local/bin/vis-agent gateway start --host 127.0.0.1 --port 7890 --require-token
Restart=on-failure
RestartSec=5
TimeoutStopSec=60
UMask=0077

[Install]
WantedBy=multi-user.target

Enable it only when you are ready to start a persistent service:

sudo systemctl daemon-reload
sudo systemctl enable --now vis-gateway.service
sudo systemctl status vis-gateway.service
sudo journalctl -u vis-gateway.service -n 50 --no-pager

You should see an active service and a listening gateway, not a repeating restart loop. Run vis-agent gateway status as the service account to inspect the same local gateway. Avoid exporting VIS_GATEWAY_URL or VIS_GATEWAY_TOKEN into the service: those select a remote target for clients, not the listener's address.

Keep the complete native bundle together. Its launcher sets up the Python sidecar; copying only vis-agent-native can leave a process that starts but cannot run Python tools. A custom launcher must preserve the bundle layout and runtime environment. Prefer the supplied wrapper unless you maintain and test that setup yourself.

Operate a small server

Use prebuilt native releases on a small VPS; compile native images on a larger builder for the target operating system and architecture. A native engine does not eliminate the memory used by Python workers, extensions or commands the agent starts. Begin with modest concurrency and monitor memory under your real workload; see resource limits.

The service account's ~/.vis holds persistent configuration and history. Protect its backups and leave room for databases, attachments, logs and project builds. Do not store it in a replaceable release directory. VIS_HOME controls launcher installation state; it does not relocate all engine configuration. Use a separate OS account for a separate service's home and credentials.

Before an update, review the update behavior and check for active work. vis-agent update --keep-gateway leaves the running gateway alone; the new runtime is used after a planned restart. Restarting a service can interrupt requests and tools, so do it in a maintenance window, not on every client connection.

Troubleshoot a connection

Symptom Check
Connection refused Service state, listener port, tunnel and firewall
Authentication fails The token belongs to this gateway and is passed to the client; never print it to debug
Client reports an incompatible protocol Update the SDK and gateway to compatible versions
Requests work but progress stalls Proxy SSE buffering, idle timeouts and the client's transport timeout
Python tools fail after a manual install The launcher, Python sidecar, file permissions and service environment
A session cannot find the project The path exists and is accessible on the gateway machine

Stopping a shared gateway affects every client. vis-agent gateway stop --if-idle requests an idle-only stop; vis-agent gateway stop can interrupt active work. For a supervised service, use the service manager for an intentional stop so its restart policy does not undo your action.

Collect evidence when work stops progressing

Vis saves a JSON report before the gateway watchdog cancels a stalled turn or gives up on a cancellation. A running local CLI client can also capture JVM threads when the gateway stops answering.

Reports live under ~/.vis/logs/YYYY-MM-DD/gateway-hang-<id>/, using the UTC capture date. See Hang reports for contents, collection limits and client-side paths, and retention for cleanup rules. Review the files before sharing them.

See also