Run it on your machine¶
This page takes a clone of the repository to the service on localhost:9000, the interface on
localhost:3000, and one public issue to read. It takes a few minutes, most of it the first build.
What you need¶
JDK 21, sbt, Docker, Node.js 24, just and
the ankka CLI 0.12.0. ankka's libraries come
from Maven Central; nothing of the platform has to be installed to run the service on a laptop.
An Anthropic API key is needed for a conversation: every turn asks the model for a reply and a proposal, and so does a representative's request for research. Everything else on this page, and most of Your first issue, runs without one.
Start what stands in for a cluster¶
just up extracts the reasoning service's database schema from its image, then starts four
containers: Postgres for Voice, Postgres for the reasoning service, the reasoning service, and
Keycloak with a realm of three staff users.
git clone https://github.com/thinkmorestupidless/voice
cd voice
just up
Container voice-postgres-1 Healthy
Container voice-reasoning-postgres-1 Healthy
Container voice-reasoning-1 Started
Container voice-keycloak-1 Started
The reasoning image, ghcr.io/thinkmorestupidless/ankka-reasoning:0.1.1, cannot be pulled
anonymously. When the pull fails, just reasoning-image builds it from a checkout of ankka-reasoning
beside this one, at that tag.
Keycloak listens on 8180, not its usual 8080, because a local ankka installation's ingress holds
8080. The realm voice-staff holds the users representative, reviewer, operator and seed,
each with the role of its name (seed has all three); their passwords are in
compose/keycloak/voice-staff.json and are not secrets, because the realm exists only on a laptop.
Start the service¶
just run copies .env.local.example to .env.local the first time, generates the two keys it
needs into it, and starts voice on 9000.
just run
.env.local is ignored by git. It holds ANKKA_SECRET_KEY, which the secret store encrypts
participant keys under, and VOICE_SESSION_KEY, which session tokens are signed with. Both are kept
between runs, so sealed fields stay readable; delete the file and every participant's records become
unreadable, which is what erasure does on purpose. Add ANTHROPIC_API_KEY= to it for conversations.
Every variable is on Configuration.
The service is up when a public route answers:
curl -s 'localhost:9000/public/issues'
[]
Load the seed pack¶
just seed loads seed/school-transport/ through Voice's staff routes as a reviewer, and Voice
writes the questions, sources, evidence and claims to the reasoning service. It needs a staff token
with the reviewer role, which the local realm's seed user gives:
export SEED_STAFF_TOKEN=$(curl -s -d grant_type=password -d client_id=voice-staff \
-d username=seed -d password=local-seed \
localhost:8180/realms/voice-staff/protocol/openid-connect/token | jq -r .access_token)
just seed
issue iss-01M57PJHFPN27YMK6J1TD0T2NG: 2 questions, 7 evidence, 3 claims
The issue id is minted on your machine and differs from this one. Six pieces of evidence are accepted; the seventh is a correction the pack leaves as a candidate for a reviewer to accept. The issue is public at once:
curl -s 'localhost:9000/public/issues?q=bus' | jq '.[].title'
"Rural school bus withdrawal"
Open the interface¶
just web
This runs ankka local web in web/, which starts the app's server on 3000 behind the same
proxy a cluster runs, with /api mounted to voice at localhost:9000. Open
http://localhost:3000/ and search for the issue; its page shows the two questions, the evidence
with its scope, authority and limitations, and the two options. http://localhost:3000/me starts a
participant's session with the invite code pilot; http://localhost:3000/staff takes a staff
token from the realm. The interface has every page.
Stop it¶
just down
This removes the containers and their volumes. The next just up starts empty, and just seed
loads the pack again.