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.