althing-chamber: add althing-agent-runner as third compose service
Phase 2 daemon added to the althing-chamber stack per forseti's request
(vh/althing@5cd088a..ad1d025). Polls floor_grants WHERE consumed_at IS
NULL AND agents.driver='worldtree', claims via atomic UPDATE, calls
Worldtree's conversation API, posts the response back through the bus
as a broadcast.
Shape matches the existing forseti daemon:
- Same ${ALTHING_IMAGE} (the binary is already in [project.scripts]
as of ad1d025)
- command: ["althing-agent-runner"]
- Same shared SQLite bind-mount at /app/data
- No port, no healthcheck (CLI doesn't expose one; same liveness
story as forseti)
Safe to enable preemptively per forseti — when no driver=worldtree
handles are declared in config, the runner sleeps at
poll_interval_seconds. Multi-instance safe via the atomic claim
primitive (no flock needed).
Compose top comment, README "Services in this stack" table, playbook
header + verify steps all extended to reflect the three-service
shape. Will land on ana-docker on vh/althing's next push (compose
deployed via the elway playbook's upload step; image already carries
the binary).
This commit is contained in:
@@ -2,11 +2,12 @@
|
||||
# Docker host following the PFI /opt/docker/ convention (ana-docker by
|
||||
# default, but the playbook works against any host with Docker in place).
|
||||
#
|
||||
# Brings up TWO compose services from a single image:
|
||||
# althing-chamber — FastAPI/HTMX web UI, port 7881 host → 8000 container
|
||||
# althing-forseti — moderator daemon, no port
|
||||
# Brings up THREE compose services from a single image:
|
||||
# althing-chamber — FastAPI/HTMX web UI, port 7881 host → 8000 container
|
||||
# althing-forseti — moderator daemon, no port
|
||||
# althing-agent-runner — Phase 2 worldtree-driver dispatcher, no port
|
||||
#
|
||||
# Both processes share the SQLite store via the same bind-mount under
|
||||
# All three processes share the SQLite store via the same bind-mount under
|
||||
# /opt/docker/conf/althing-chamber/data. eventbus.bridge_from_db is the
|
||||
# cross-process glue.
|
||||
#
|
||||
@@ -134,3 +135,7 @@ verify:
|
||||
- name: forseti container running
|
||||
shell: docker ps --filter name=^/althing-forseti$ --format '{{.Status}}' | grep -q '^Up'
|
||||
changed_when: "false"
|
||||
|
||||
- name: agent-runner container running
|
||||
shell: docker ps --filter name=^/althing-agent-runner$ --format '{{.Status}}' | grep -q '^Up'
|
||||
changed_when: "false"
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
# althing-chamber
|
||||
|
||||
Web UI + moderator daemon for the althing inter-agent message bus.
|
||||
Two services share a single SQLite store via a bind-mount; the chamber
|
||||
serves FastAPI/HTMX, the forseti daemon runs the moderation + curation
|
||||
loops. Cross-process glue is `eventbus.bridge_from_db` polling the same
|
||||
DB both processes write.
|
||||
Web UI + moderator daemon + agent-runner for the althing inter-agent
|
||||
message bus. Three services share a single SQLite store via a
|
||||
bind-mount; the chamber serves FastAPI/HTMX, the forseti daemon runs
|
||||
the moderation + curation loops, and the agent-runner daemon claims
|
||||
floor grants for worldtree-driver agents and dispatches them to
|
||||
Worldtree's conversation API. Cross-process glue is
|
||||
`eventbus.bridge_from_db` polling the same DB all three processes
|
||||
write.
|
||||
|
||||
**Server:** ana-docker
|
||||
**URL:** `http://10.250.50.70:7881` (configurable via `.env`)
|
||||
@@ -18,10 +21,16 @@ by the deploy playbook. Not pulled from a registry.
|
||||
|---|---|---|---|
|
||||
| `althing-chamber` | FastAPI/HTMX web UI; SSE subscribers; `/health` endpoint | host 7881 → container 8000 | `python urllib /health` |
|
||||
| `althing-forseti` | Moderator + curator daemon; writes events that chamber's bridge picks up | — (no HTTP) | none (process-up signal only) |
|
||||
| `althing-agent-runner` | Phase 2: claims worldtree-driver floor grants and dispatches to Worldtree's conversation API | — (no HTTP) | none (process-up signal only) |
|
||||
|
||||
Both use the same `${ALTHING_IMAGE}`; the `command:` line in compose picks
|
||||
which entrypoint (`althing-chamber` vs `althing-forseti`) runs in each
|
||||
container.
|
||||
All three use the same `${ALTHING_IMAGE}`; the `command:` line in compose
|
||||
picks which entrypoint (`althing-chamber` / `althing-forseti` /
|
||||
`althing-agent-runner`) runs in each container.
|
||||
|
||||
The agent-runner is safe to enable preemptively — when no
|
||||
`driver=worldtree` handles are declared in config, it polls
|
||||
`floor_grants` and sleeps when the query returns empty. Multi-instance
|
||||
safe via the atomic `UPDATE … WHERE consumed_at IS NULL` claim primitive.
|
||||
|
||||
## Deploy
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# althing-chamber + forseti — web UI + moderator daemon for the althing
|
||||
# inter-agent message bus.
|
||||
# althing-chamber + forseti + agent-runner — web UI + moderator daemon +
|
||||
# Worldtree-driver agent-runner for the althing inter-agent message bus.
|
||||
#
|
||||
# Two services share the althing SQLite store via a single bind-mount:
|
||||
# althing-chamber — FastAPI/HTMX app (port 7881 host → 8000 container)
|
||||
# althing-forseti — moderator daemon (no port; cross-process glue via the DB)
|
||||
# Three services share the althing SQLite store via a single bind-mount:
|
||||
# althing-chamber — FastAPI/HTMX app (port 7881 host → 8000 container)
|
||||
# althing-forseti — moderator daemon (no port; cross-process glue via the DB)
|
||||
# althing-agent-runner — Phase 2 daemon: claims worldtree-driver grants and
|
||||
# dispatches to Worldtree's conversation API (no port)
|
||||
#
|
||||
# eventbus.bridge_from_db is load-bearing — forseti's DB commits reach
|
||||
# chamber's SSE subscribers via the bridge, not via shared memory or IPC.
|
||||
@@ -74,3 +76,22 @@ services:
|
||||
# No healthcheck — the forseti CLI doesn't expose one. Liveness signal
|
||||
# for ops is "container hasn't exited" + chamber-side observation that
|
||||
# bridge_from_db events are flowing.
|
||||
|
||||
althing-agent-runner:
|
||||
image: ${ALTHING_IMAGE}
|
||||
container_name: althing-agent-runner
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- ALTHING_ROOT=/app/data
|
||||
- ALTHING_DB=/app/data/althing.db
|
||||
volumes:
|
||||
- ${ALTHING_DATA_DIR}:/app/data
|
||||
command: ["althing-agent-runner"]
|
||||
# Phase 2 daemon (added 2026-05-16). Polls floor_grants WHERE
|
||||
# consumed_at IS NULL AND agents.driver='worldtree', claims via
|
||||
# atomic UPDATE, calls Worldtree's conversation API, posts the
|
||||
# agent's response back through the bus as a broadcast. Harmless
|
||||
# when no driver=worldtree handles are declared — runner sleeps
|
||||
# at poll_interval_seconds. Multi-instance safe via claim_grant's
|
||||
# atomic UPDATE; no flock required. Same lack-of-healthcheck story
|
||||
# as forseti (CLI doesn't expose one).
|
||||
|
||||
Reference in New Issue
Block a user