Cluster profile¶
The cluster hosting profile runs one persistent ameesh agent in a
Kubernetes pod. It is a minimal profile: the runner and its harness, nothing
else. Neither the gate with human receipts nor ameesh-approve is exposed; the
agent is declared in the canon with the capabilities read and propose only.
Files in the repository:
| File | Role |
|---|---|
Dockerfile, .dockerignore |
the runner image, without secrets, without a harness by default |
deploy/k8s/ |
example manifests (kustomize): StatefulSet, ConfigMap, Service without ports, NetworkPolicy, service account |
deploy/k8s/secrets.exemple.yaml |
the shape of the expected Secrets, never filled in, never applied as is |
deploy/sql/role-superviseur.sql |
read-only Postgres role for an external supervisor (state only) |
deploy/sql/role-superviseur-contenus.sql |
additional role that can read message bodies, prompts and notes, granted explicitly |
Architecture¶
canon repository (git) durable Postgres
Host = pod name, (outside the pod)
Agent, Placement ▲
│ read-only deploy key │ AMEESH_DSN + PGPASSWORD
┌─ pod ameesh-agent-0 ┼─────────────────────────────────────────┼─────────┐
│ init migrate ameesh migrate ──────────────────────────────►│ │
│ init canon git clone ; ameesh canon sync --fetch ───────►│ │
│ canon-fetch ─► canon/ (periodic git fetch), mounted READ-ONLY in runner │
│ runner agent-runner ── periodic canon sync ─────────►│ │
│ (tini, PID 1) └─ harness (claude | codex | dsh) │
│ HOME = persistent volume: sessions, state, threads, cwd│
└─────────────────────────────────────────────────────────────────────────┘
no inbound network (Service without ports, NetworkPolicy);
outbound: database, git, model provider API
- Identity. The pod name (
ameesh-agent-0) is the ameesh host (AMEESH_HOST, via the downward API). The canon declares aHostof that name and the agent'sPlacementon it; without them the agent is not claimable. Always one replica: two replicas would be two hosts. - Canon. Cloned by an init container with a read-only deploy key, then
fetched periodically by a sidecar. The clone is mounted read-only in the
runner container; the key is never mounted there.
canon_ref: origin/mainin the configuration fixes the trusted canonical branch. - State. The database holds leases, mailbox, registry and actions. The
persistent
homevolume holds harness sessions, ameesh's local state (including the readable threads) and the working directories. - Shutdown. tini forwards
SIGTERMto the runner, which stops the harness group, joins its turns and releases the lease. - Probe.
ameesh doctor --probeasreadinessProbe: database reachable, schema present, migrations up to date; read-only. NolivenessProbe.
What is guaranteed, and what is not¶
| Guaranteed in this profile | Not guaranteed |
|---|---|
| one agent per pod: its file system, processes and sessions are isolated from other agents, which the local profile (shared Unix user) does not offer | isolation in the database: the runner and its harness share ameesh's Postgres role; the agent can read and modify the state of other agents of the same schema |
| the canon is read-only for the agent; the deploy key is not mounted in its container | the agent can write to the database with ameesh's role; monotonicity and the claim predicate remain the only safeguards |
| read-only root file system, no Linux capabilities, non-root user, no Kubernetes API token | outbound network open in the example; no network sandbox or MCP proxy |
no inbound network: the gate and ameesh-approve are not exposed; an irreversible or costly action stays blocked ([receipt_required]), the safe behaviour |
no human approval is possible from this profile: ameesh-approve must be deployed out of the agents' reach, which this profile does not provide |
| an agent without a responsible human, misplaced, or whose canon is invalid is not claimed | the example does not check that the agent's capabilities are limited to read and propose: the reviewed Agent card says so |
Setting it up (operator's acts)¶
None of this is done by an agent or by the repository: creating a registry, a
database, Secrets and applying manifests are operator's acts (and any spending
is a costly action).
- Image.
docker build -t <registry>/ameesh-runner:<version> ., with--build-arg HARNESS_NPM=<package@version>for a harness distributed by npm, or a derived image for another one. Push it to your registry and set it inimages:ofkustomization.yaml. - Database. A durable Postgres (managed service, or a dedicated instance
with volume and backups). A role for ameesh that owns its schema. DSN
without password in
config.json; the password in theameesh-dbSecret. - Canon.
Host(name = pod name),Agent(capabilitiesread,propose) andPlacement(cwdunder/home/ameesh) cards, merged by pull request; a read-only deploy key,known_hostschecked out of band. - Secrets. The three Secrets of
secrets.exemple.yaml, created outside any repository. - Render, review, apply.
kubectl kustomize deploy/k8s, thenkubectl apply -k deploy/k8s. - Harness. On first start the home is empty: set up the harness hooks
(
agent-mail hook <harness>) and the working repository once, bykubectl execor a derived image. - Check.
kubectl logs ameesh-agent-0 -c runner(lease acquired),kubectl exec ameesh-agent-0 -c runner -- ameesh canon check,ameesh list,ameesh doctor --notify-test.
External read-only supervisor¶
A supervisor, possibly from another organisation, sees the state of the mesh, not the work itself, by default:
ameesh_superviseur: registry and overview view, mailbox metadata (sender, recipient, kind, status, dates), lots (title, state, assignee), thread index without excerpt, actions and attempts without arguments or notes, costs, canon state, migrations;ameesh_superviseur_contenus, granted explicitly in addition: message bodies, prompts, thread excerpts, action arguments and notes, lot descriptions and notes.
Neither role can write, nor read signatures, receipts, nonces, challenges,
public keys or authenticator ids. Each script runs in its own transaction,
audits the role's effective privileges (including through PUBLIC,
inherited and predefined roles, and default ACLs) and refuses, rolling
everything back, if the contract is not met. A supervisor role is member of no
other role. Re-run both scripts after every ameesh upgrade.
export PGOPTIONS='-c search_path=public'
psql "<admin DSN>" -v ON_ERROR_STOP=1 -f deploy/sql/role-superviseur.sql
psql "<admin DSN>" -v ON_ERROR_STOP=1 -f deploy/sql/role-superviseur-contenus.sql
Credentials of the harnesses¶
- API keys: in the
ameesh-harnessSecret, inherited by the harness; the hourly cap of ameesh and the provider's own limits apply. The harness (so the agent) can read them. - Subscriptions: using them on a server, without a human in front, shared
by an autonomous agent, must be checked against each provider's terms
before any deployment. The
Hostpolicy (credential_modes) can simply not admit them.
Backups, upgrades, rollback¶
- Database: the managed service's backups, or a daily
pg_dumpcopied outside the cluster, with a restore drill (ameesh doctor --probeon the restored copy). Take apg_dumpbefore every upgrade: migrations do not roll back. - Volume: volume snapshots or periodic copies (sessions and threads live there).
- Upgrade: new image tag (never reused),
kubectl apply -k; the new pod applies migrations, clones and syncs the canon, and resumes the agent on the same session. - Out of service:
kubectl scale statefulset/ameesh-agent --replicas=0, orameesh run stop <agent>.
Known limits¶
- No Postgres role per agent yet: all writes go through ameesh's role.
- Migrations run from the runner's init container with the runner's role (provisional): that role has DDL rights on the schema, and so does the harness. Planned: a distinct schema-owner role used only by an operator-run migration job.
- ameesh-approve in a cluster is outside this profile.
- Federations of several canon repositories are not covered by the example init container.