A Bayesian decision-making DSL (Julia) and the tools built on it: an AI gateway that learns to route LLM requests, a domain-agnostic agent library, and research environments for testing the theory.
Everything reduces to three axioms: beliefs are probability measures, rational action maximises expected utility, learning is conditioning on evidence. Three types (Space, Measure, Kernel), axiom-constrained functions, and nothing else.
credence-pi is an OpenClaw plugin plus a local daemon that learns your agent's behaviour from your approvals and governs its tool calls — ask / proceed / block, decided by expected utility. Measured on real OpenClaw sessions:
- exact-repeat wasted calls blocked at precision 1.0 / recall 1.0 on held-out sessions (0.7% of all calls, nothing else touched);
- an injected exfiltration surfaced as a confirmation at 0.94 precision, interrupting 1.2% of safe sessions;
- local-first: an append-only observation log on your machine, and no raw data leaves it.
# the brain
docker run -p 8787:8787 -v ~/.credence-pi:/root/.credence-pi ghcr.io/gfrmin/credence-pi-daemon
# the body
openclaw plugins install @gfrmin/credence-pi-openclaw
openclaw plugins enable credence-piThe label, plainly: research-stage. Waste-blocking is enforced (the proven part). Safety governance ships in confirm mode — nothing of yours is blocked silently, and each answer calibrates the belief. It lives at the tool boundary, so it is blind to harmful output, and the harm it can see there tops out at about three in ten of unsafe trajectories on the benchmark. Background: the announcement, the architecture and the discipline that kept it honest, and what the brain learned, and why a regex can't.
credence-proxy is a drop-in OpenAI-compatible gateway that learns which model works best for each type of query:
| Metric | Always Sonnet | Credence routing | Change |
|---|---|---|---|
| Quality (0-10) | 6.56 | 7.80 | +1.24 |
| Avg latency | 8.4s | 4.0s | -52% |
| Avg cost/request | $0.024 | $0.001 | -96% |
docker run -p 8377:8377 \
-e ANTHROPIC_API_KEY=sk-ant-... \
-e OPENAI_API_KEY=sk-... \
-v credence-data:/data \
credence-proxyPoint any OpenAI-compatible client at http://localhost:8377/v1. The proxy picks the best model, streams the response, and updates its beliefs from the outcome.
Add a custom provider to ~/.openclaw-dev/openclaw.json:
{
"models": {
"mode": "merge",
"providers": {
"credence": {
"baseUrl": "http://localhost:8377/v1",
"apiKey": "not-needed",
"api": "openai-completions",
"models": [{"id": "auto", "name": "Credence (auto-routed)"}]
}
}
},
"agents": {
"defaults": {
"model": {"primary": "credence/auto"}
}
}
}See credence-proxy docs for all endpoints, search routing, monitoring, and configuration.
The DSL has three primitives — no more, no less:
(belief h1 h2 ...) ;; weighted hypotheses (probability measure)
(update <belief> <obs> <lik>) ;; Bayesian conditioning (the only learning mechanism)
(decide <belief> <acts> <util>) ;; expected utility maximisation (the only decision mechanism)Requires Julia >= 1.9 (stdlib only, no packages).
julia -e 'push!(LOAD_PATH, "src"); using Credence; run_dsl(read("examples/coin.bdsl", String))'(let prior (belief 0.1 0.3 0.5 0.7 0.9)
(let lik (lambda (theta obs)
(if (= obs 1) (log theta) (log (- 1.0 theta))))
(let posterior (update (update prior 1 lik) 0 lik)
(decide posterior (list 1 0)
(lambda (theta action)
(if (= action 1)
(if (> theta 0.5) 1.0 -1.0)
(if (< theta 0.5) 1.0 -1.0)))))))julia test/test_core.jl # Core DSL (42 tests)
julia test/test_flat_mixture.jl # Flat mixture conditioning
julia test/test_program_space.jl # Tier 2: enumeration, compilation, perturbation
julia test/test_grid_world.jl # Tier 3: full agent + regime changesrc/ DSL core: parser, evaluator, ontology (Space, Measure, Kernel)
src/program_space/ Program-space inference (grammars, enumeration, perturbation)
examples/ DSL examples (coin, agent, grid)
apps/ Everything built on top of the DSL (three sub-layers)
julia/ brain-side — in-process DSL callers
grid_world/ Research environment
email_agent/ Email triage with JMAP
qa_benchmark/ QA benchmark harness
pomdp_agent/ POMDP agent (Thompson MCTS, state abstraction)
skin/ JSON-RPC translation layer (opaque Measure handles)
python/ body — user-facing surfaces (uv workspace)
credence_bindings/ Python bindings via juliacall
credence_agents/ Domain-agnostic Bayesian agent library
credence_router/ credence-proxy: AI gateway for LLM/search routing
bayesian_if/ Interactive Fiction agent
| Component | README | What it does |
|---|---|---|
| credence-proxy | README | LLM/search routing gateway |
| credence-agents | README | Bayesian agent library + benchmark |
| bayesian-if | README | Interactive Fiction agent |
| POMDP agent | CLAUDE.md | Planning under uncertainty (Jericho IF) |
# Python packages (all four, via uv workspace)
uv sync
# Run Python tests
PYTHON_JULIACALL_HANDLE_SIGNALS=yes uv run pytest apps/python/
# Run credence-proxy from source
PYTHON_JULIACALL_HANDLE_SIGNALS=yes credence-router serveThree types (frozen) Space, Measure, Kernel
Axiom-constrained functions condition, expect, push, density
Standard library optimise, value, voi, model, problem
Program-space inference grammars, enumeration, compilation
Domain applications grid world, email, RSS, QA benchmark
Python ecosystem bindings → agents → router, bayesian-if
All Bayesian inference runs in the Julia DSL. Python handles host concerns: API calls, tool queries, persistence. The DSL is pure — no side effects, no IO, no mutation.
- Cox (1946) — probability from consistency
- Savage (1954) — utility + probability from preferences
- Jaynes (2003) — Probability Theory: The Logic of Science
- McCarthy (1960) — why S-expressions
AGPL-3.0