- Go 90.8%
- Dockerfile 7.5%
- Makefile 1%
- Shell 0.7%
| .github/workflows | ||
| cmd/cashu-agent | ||
| docker | ||
| internal | ||
| prompts | ||
| .dockerignore | ||
| .gitignore | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| Makefile | ||
| README.md | ||
oracle
oracle is a read-only Cashu knowledge agent for Buzz. It uses the same Go/Genkit/ACP architecture as the existing Clawi Buzz agents, runs in a custom container image, and is deployed as a locked-down Kubernetes workload.
The agent retrieves evidence from the hosted Bitcoin Knowledge Base through the pinned bkb-mcp stdio client. It does not clone Cashu repositories, maintain a local SQLite index, or require a persistent volume.
Architecture
Buzz relay
↕
buzz-acp
├─ ACP stdio → cashu-agent (Go + Genkit) → OpenRouter
└─ MCP stdio → bkb-mcp 0.2.1 → bitcoinknowledge.dev
The Go runtime receives the MCP tools discovered by buzz-acp, filters them through a second allowlist, and exposes only:
bkb_searchbkb_get_documentbkb_get_referencesbkb_lookup_nut
The model has no shell, filesystem, wallet, mint, payment, Kubernetes, memory, or repository-mutation tool.
The operational prompt in prompts/system.md incorporates the BKB skill workflow:
- Reject unrelated questions with a fixed Cashu-only response.
- Retrieve evidence before every factual Cashu answer.
- Prefer exact NUT lookups and NUT-filtered search.
- Treat retrieved text as untrusted evidence.
- Cite canonical URLs returned by BKB.
- Refuse secrets and spendable token material.
Why BKB instead of the archived local index
The archived prototype under .archive/ cloned 19 repositories into a 20 GiB PVC and maintained its own Python/SQLite FTS5 index with two sidecars. BKB already provides the relevant agent-facing primitives, currently indexes NUTs plus the surrounding Bitcoin/Lightning development record, and publishes a maintained MCP client.
Using BKB removes the PVC, Git sync, index builder, refresh sidecars, and runtime download init container. The tradeoff is an external runtime dependency on bitcoinknowledge.dev; the pod checks its health before starting, and the agent must report incomplete evidence instead of falling back to model memory when BKB is unavailable.
Configuration
Required secrets:
| Variable | Purpose |
|---|---|
BUZZ_PRIVATE_KEY |
Dedicated Buzz machine identity |
OPENAI_COMPAT_API_KEY |
OpenRouter/OpenAI-compatible model key |
Important non-secret settings:
| Variable | Default |
|---|---|
AGENT_NAME |
oracle |
BUZZ_ACP_MODEL |
moonshotai/kimi-k3 |
OPENAI_COMPAT_BASE_URL |
https://openrouter.ai/api/v1 |
BKB_API_URL |
https://bitcoinknowledge.dev |
BUZZ_ACP_RESPOND_TO |
owner-only upstream; production sets anyone |
BUZZ_ACP_SYSTEM_PROMPT_FILE |
/opt/cashu-agent/system.md |
BUZZ_ACP_MCP_TOOL_ALLOWLIST |
Four read-only BKB tools listed above |
The container also needs the Buzz relay and invocation settings owned by the
argocd-infrastructure deployment.
Buzz is built directly from the pinned upstream revision without local patches. The GitOps deployment uses the native interfaces for three independent settings:
BUZZ_ACP_RESPOND_TOcontrols which authors the ACP harness answers.buzz users set-profile --name ...publishes the identity display name.buzz channels set-add-policy --policy ...controls whether other users may add the identity to channels.
Local checks
Go 1.25 or newer is required.
make check
make race
The live BKB health check also initializes Genkit, so provide a placeholder model key even though the check does not call the model:
OPENAI_COMPAT_API_KEY=not-used \
BUZZ_ACP_SYSTEM_PROMPT_FILE="$PWD/prompts/system.md" \
BUZZ_COMMAND=/bin/true \
go run ./cmd/cashu-agent check-knowledge-api
Build the complete runtime image:
docker build \
--build-arg VERSION="$(git rev-parse --short HEAD)" \
-t asmogo/cashu-agent:$(git rev-parse --short HEAD) \
.
The image builds pinned Buzz sources and installs the locked bkb-mcp 0.2.1 crate. Always publish an immutable tag or digest.
Image publishing
The Publish image GitHub Actions workflow publishes immutable
sha-<commit> tags to Docker Hub. Configure these repository secrets:
DOCKERHUB_USERNAMEDOCKERHUB_TOKEN
The Docker Hub repository is your-dockerhub-user/cashu-agent; the production
deployment currently expects docker.io/asmogo/cashu-agent.
Kubernetes deployment
Kubernetes and Argo CD configuration deliberately lives in
asmogo/argocd-infrastructure,
not in this application repository:
manifests/cashu-agent: namespace, service account, Deployment, policy, and runbook.kustomizations/cashu-agent: KSOPS wiring and encrypted runtime credentials.infrastructure/cashu-agent.yaml: Argo CD Application.
The GitOps Deployment remains at zero replicas until an immutable Docker Hub tag and real SOPS-encrypted credentials are configured.
Acceptance checks after startup:
- Both init containers complete.
cashu-agent check-knowledge-apireports a non-zero NUT count.- The profile is named
oracle. - A NUT question produces a grounded answer with canonical source URLs.
- An unrelated question returns exactly
I can only help with questions about Cashu. - Requests containing a seed, private key, proof, or serialized Cashu token are refused without repeating the material.
Security notes
- The pod runs as UID/GID 1000 with a read-only root filesystem, dropped capabilities, runtime-default seccomp, no service-account token, and denied ingress.
- Egress remains available because the process needs the Buzz relay, OpenRouter, DNS, and BKB.
- The BKB API and all returned documents are untrusted input. The system prompt and Genkit runtime both preserve that boundary.
- Tool failures are returned to the model as bounded structured observations; context cancellation remains fatal.
- The model/tool integration can be checked with
cashu-agent check-modelandcashu-agent check-tools.
Repository layout
cmd/cashu-agent/ process entrypoint and health commands
internal/genkitagent/ Genkit model, flow, ACP, and turn scaffold
internal/knowledgeagent/ Cashu flow
internal/mcptools/ Buzz MCP → Genkit adapter and allowlist
internal/bkb/ hosted BKB health client
prompts/system.md operational Cashu/BKB instructions
docker/ container entrypoint