Skip to content

Quick start

One host, one agent, one person who can reach it in a browser.

This page starts where Install ends: agentctl is on the host and has not changed anything yet.

1. Initialize the host

sudo agentctl init        # scaffold the GitOps repo at /opt/agentctl
sudo agentctl provision   # group, slices, directories, backup, host crons

init creates /opt/agentctl, the git repo that declares the fleet. provision makes the host able to run agents.

2. Stand up the cockpit

Every agent's owner talks to it in the cockpit — a browser workspace carrying a chat stream, the agent's files, its sessions and its scheduled runs. Two host services put the cockpit on the network: a router that agents connect to, and a login proxy that browsers reach.

Both read their configuration from the encrypted secret store, so write that first.

sudo agentctl secret set WEBVIEW_HMAC_KEY    --value "$(openssl rand -hex 32)"
sudo agentctl secret set WEBVIEW_AUTH_DRIVER --value basic
sudo agentctl secret set WEBVIEW_BASIC_USERS --value 'bob@example.com:<password>'

The basic driver is the fastest way to a working login: agentctl serves the form itself. The oidc driver signs people in against Entra, Google or any other issuer instead — see Cockpit login.

Then install both services:

sudo agentctl webview-gateway install   # the router agents connect to     :8735
sudo agentctl webview-login install     # the login page browsers reach    :8736

For ports, binds and the full trust chain, see The webview gateway.

3. Put HTTPS in front

The login proxy's session cookie is Secure, and there is no flag that relaxes it — a cockpit reached over plain HTTP cannot hold a session at all. So TLS comes before the first login.

agentctl can terminate it for you. Point a DNS record at this host, name it, and apply:

sudo agentctl host caddy domain set agents.example.com
sudo agentctl apply

apply installs Caddy on the gateway host and renders its config: HTTP/2, the compression exclusions the cockpit's four SSE streams need, X-Request-Id forwarding, and — since no certificate is in the secret store — automatic HTTPS, where Caddy obtains and renews the certificate itself. Ports 80 and 443 have to be reachable from the internet for that.

Prefer your own reverse proxy, or already have one owning 443? Point it at :8736 and reproduce the proxy requirements. Either way DNS is yours.

Both paths, the domain registry and supplying your own certificate: TLS and Caddy.

4. Add an agent

sudo agentctl agents add bob \
  --channel webview --user-email bob@example.com \
  --runtime pi --api-key <key> --provider groq

bob is now a Linux user on this host with its own home, its own systemd units and its own ~/workspace.

--user-email is the routing key. Whoever signs in as bob@example.com gets bob's cockpit and only bob's — so it has to match an entry in WEBVIEW_BASIC_USERS.

--runtime pi runs pi, a model-agnostic harness that boots on a provider API key. --provider groq names which provider the key belongs to; anthropic, openai and openrouter work the same way.

Tip

webview and pi are the defaults, so both flags can be omitted. They are written out here so it is clear what you are running.

Confirm the host agrees:

agentctl status                    # host readiness + fleet overview
agentctl webview-gateway status    # unit health and the user_email → agent ledger

5. Open the cockpit

Point a browser at the domain from step 3:

https://agents.example.com/

Sign in as bob@example.com. The login proxy verifies the password and passes the signed-in address to the cockpit, which scopes the session to bob.

You land on bob's transcript, with a composer pinned below it and bob's ~/workspace file tree in the left sidebar. Send a message. bob answers on the first turn — the API key from step 4 is all the pi runtime needs, so there is nothing further to authorize.

If the login succeeds and the page is then empty, that address maps to no agent: check the ledger printed by webview-gateway status against your --user-email.

What you built

/opt/agentctl is the source of truth. It holds:

Path Contents
agents.yaml fleet-level config
agents.d/ per-agent shards
mcp/ skills/ agents/ hooks/ extensions/ tools/ overlays
secrets.d/ sops-encrypted per-owner secret store

It is an ordinary git repo: push it, clone it on another host, run agentctl apply there. The age identity that decrypts the secret store stays on the host and is never committed.

No agent is an admin agent unless you ask for one. Add --admin to drive the fleet through that agent instead of from a shell; without it, sudo agentctl … as root is the operator path. Reaching a host's root shell does not depend on it either way — every host holds its own connection to the fleet gateway, so agentctl host shell <host> works on a host with no agents on it at all.

Next
First run in the cockpit the login page and every surface of the UI
Onboarding a new person the walk-through the agent runs itself
Install as a PWA putting the cockpit on a laptop and a phone
Runtimes: claude and pi what differs between the two harnesses
Channels reaching an agent on Telegram, Teams or Slack as well
Multi-host fleet making a second host a secrets recipient

Prefer an agent on a Claude subscription login instead of an API key? Add --runtime claude and see First run in the cockpit.