ai
Framework-aware AI tooling for Wagoe applications. Unlike a generic assistant, it knows Wagoe’s conventions: FC/IS, ports, kebab↔snake naming, Malli schemas, and HoneySQL syntax.
Features
-
NL Scaffolding - parse a natural language description into a scaffolding spec
-
Error Explainer (experimental) - explain a stack trace with Wagoe-specific context
-
Test Generator (experimental) - generate a complete test namespace for a source file
-
SQL Copilot (experimental) - translate a description into HoneySQL format
-
Documentation Wizard - generate AGENTS.md, OpenAPI YAML, or README
The test generator shows the model the public API and the Malli schemas of every namespace the source requires, plus its module’s schema namespace. Before writing, it lints the answer and checks each fixture tagged ^{:schema s} against s, reading the file without evaluating it; a fixture whose value is not literal data is reported as not checked. A failing answer goes back to the model once; if it still fails, nothing is written unless you pass --force.
--run also loads the answer and runs its tests, in a separate JVM that keeps only PATH, HOME, LANG and WAG_ENV from your environment, and every test must pass. This runs code the model wrote before anyone has read it. The child is not a sandbox: it can read your files and reach the network.
|
Warning
|
The error explainer, test generator and SQL copilot are experimental for 1.0: their answers can be confidently wrong, so review them before use. bb ai explain prints the error’s own WGE code and Fix: text before the model’s summary.
|
CLI commands
# NL scaffolding (interactive confirm)
bb scaffold ai "product module with name, price, stock"
# NL scaffolding (non-interactive)
bb scaffold ai "product module with name, price, stock" --yes
# Explain a stack trace (experimental)
bb ai explain --file stacktrace.txt
# Generate test namespace (experimental)
bb ai gen-tests libs/user/src/wagoe/user/core/validation.clj
# Generate HoneySQL from description (experimental)
bb ai sql "find active users with orders in the last 7 days"
# Generate documentation
bb ai docs --module libs/user --type agents
bb ai docs --module libs/user --type openapi
bb ai docs --module libs/user --type readme
bb ai sql shows the model the tables and columns your migrations create (migrations/, resources/migrations/ and the libraries' own), tables your description names first. Tables a library creates in code are listed by name only. An answer that names a table or column outside that schema is sent back once and then refused, and with no tables found it refuses rather than guess. The query is never run.
Prerequisites per provider
The config a provider needs is written by bb setup --ai-provider <name>;
what the provider needs outside the config is this table. The project boots
without any of it — the first AI call is what fails.
| Provider | Before the first call answers |
|---|---|
|
Install Ollama (https://ollama.com/download), pull the configured model
( |
|
Create a key at https://console.anthropic.com/settings/keys and export
|
|
Create a key at https://platform.openai.com/api-keys and export
|
|
Create a token at https://replicate.com/account/api-tokens and export
|
bb doctor --ci names a missing key for the hosted providers. It does not
probe whether Ollama is running.
Provider strategy
:provider is required; the service refuses to start without one. Ollama
keeps data on the machine. A :fallback provider answers when the primary
fails:
;; Offline-first (Ollama, no API key)
:wagoe/ai-service
{:provider :ollama
:model "qwen2.5-coder:7b"
:base-url "http://localhost:11434"}
;; Anthropic
:wagoe/ai-service
{:provider :anthropic
:model "claude-haiku-4-5-20251001"
:api-key #env ANTHROPIC_API_KEY}
;; Ollama primary + Anthropic fallback
:wagoe/ai-service
{:provider :ollama
:model "qwen2.5-coder:7b"
:base-url "http://localhost:11434"
:fallback {:provider :anthropic
:api-key #env ANTHROPIC_API_KEY}}
The bb ai commands use :wagoe/ai-service from the active config when it
names a provider other than :no-op. Otherwise the first variable set picks:
ANTHROPIC_API_KEY → OPENAI_BASE_URL (an OpenAI-compatible endpoint) →
OPENAI_API_KEY → REPLICATE_API_TOKEN → OLLAMA_URL, then Ollama on
localhost:11434. AI_MODEL overrides the model.
Key namespaces
| Namespace | Layer | Responsibility |
|---|---|---|
|
shared |
|
|
core |
Pure prompt builders for all 5 features |
|
core |
Pure context extractors (module names, stack traces, function signatures) |
|
core |
Pure response parsers (JSON, module spec, SQL, test code) |
|
shell |
Ollama HTTP adapter |
|
shell |
Anthropic API adapter |
|
shell |
OpenAI API adapter |
|
shell |
Replicate API adapter |
|
shell |
Test stub |
|
shell |
Public API: |
|
shell |
REPL helpers: |
REPL usage
(require '[wagoe.ai.shell.repl :as ai])
;; Bind a service
(ai/set-service! (integrant.repl.state/system :wagoe/ai-service))
;; Use helpers
(ai/explain "ClassNotFoundException: wagoe.user.core.user")
(ai/sql "find all users who logged in today")
(ai/gen-tests "libs/user/src/wagoe/user/core/validation.clj")
Testing
clojure -M:test :ai