A modular framework for agentic Bayesian optimization.
Docs · Blog · Install · Plugins · Experiments · Contributing
Full documentation, including guides and a plugin reference, is at richardcsuwandi.github.io/plugbo.
Bayesian optimization (BO) uses a probabilistic surrogate to choose each evaluation, but its overall search strategy is usually fixed in advance. Agentic BO places an LLM agent at the center of the loop: it reviews trial data, surrogate diagnostics, and natural-language context, then decides how to search next. As evidence accumulates, the agent can query or override backend suggestions and revise the surrogate, acquisition function, search bounds, objectives, or constraints [1].
Meta's Agentic Bayesian Optimization through Surrogate-Augmented Autoresearch
instantiates that idea as Sara, an LLM agent, calling lenz, a BoTorch backend that
owns the trial log and posterior computation [1] [6].
PlugBO keeps that agent and backend, then turns the backend into a plugin surface:
surrogate, region, prior, and sampler are slots. Existing and new BO modules
wrap as lenz verbs the agent can enable, inspect, or override. The arrangement is
analogous to MCP: Sara is the host, with
only bash and read, and lenz is the shared tool surface. A BO method
registers extra verbs there the way an MCP server registers tools, so the agent
stays fixed while the surrogate, region, prior, or sampler can be swapped in as
a plugin.
Note: PlugBO is not an official implementation of Meta's agentic BO paper [1]. What is new here is the plugin protocol, together with new experiments and results.
The technical blog post covers the implementation, experimental setup, and results in more detail.
- Provides a modular and easily extensible interface for composing BO methods. The surrogate, region, prior, and sampler are slots on a shared BoTorch backend.
- Places an LLM agent in a live BO loop. The agent can inspect trials, query the posterior, and reconfigure slots mid-run, while BoTorch retains the trial log and posterior.
- Supports future BO development as tools on a shared interface analogous
to MCP. A method registers extra
lenzverbs the way an MCP server registers tools, so the agent stays fixed while new modules can be plugged in.
Not on PyPI. Two ways to install from source (Python 3.10+):
Editable install
git clone https://github.com/richardcsuwandi/plugbo.git
cd plugbo
pip install -e .That pulls torch, gpytorch, botorch, and LLM clients (anthropic,
openai). Copy .env.example to .env if you will call an LLM.
Dev install (tests, plus the LoRA HPO emulator extra)
pip install -e ".[dev]" # tests
pip install -e ".[bolt]" # LoRA HPO emulator (BoLT)Sara, lenz, and the BO methods are the same kind of piece: modules on one
control plane. Sara is the host (bash and read). lenz is the tool surface.
Existing and new BO modules occupy slots on that
surface. The current version of PlugBO supports the following BO modules:
| Module | Role | Default | Occupant | Commands |
|---|---|---|---|---|
sara |
search agent | — | — | sara run |
lenz |
trial log, posterior, acquisition | BoTorch loop | — | create, suggest, submit, incumbent |
| Surrogate | GP | fixed Matérn | CAKE [2] | set-surrogate, evolve-kernels, kernel-population |
| Region | search bounds | box | TuRBO [3] | set-region, set-bounds, turbo status |
| Prior | belief | none | πBO [4] | set-belief |
| Sampler | candidates | BoTorch | LLAMBO [5] | set-sampler, llambo sample |
Occupying a slot is a set-* verb. Plugins may add more verbs. Method state
lives in state.json under plugins, not on the live shelf. Reconfiguring
never discards trials. lenz plugins lists installed modules.
Vanilla loop (no LLM):
lenz create --state ./state.json \
--space '{"x1":{"kind":"range","lower":-5,"upper":10},"x2":{"kind":"range","lower":0,"upper":15}}' \
--objectives '{"y":"minimize"}' \
--acqf noisy_logei
lenz suggest --state ./state.json
lenz submit --state ./state.json --config '{"x1":1.0,"x2":2.0}' --metrics '{"y":12.3}'
lenz incumbent --state ./state.jsonAgent in the loop:
sara run \
--provider anthropic --model claude-opus-5 \
--context examples/branin/context.md \
--eval "python3 examples/branin/eval.py" \
--budget 30 \
--workdir ./results/logs/branin-1--context is problem markdown, --eval is a command that takes one config
JSON. --no-lenz drops the backend: Sara proposes configs and calls
./oracle herself.
--provider |
Notes |
|---|---|
anthropic |
ANTHROPIC_API_KEY |
openai |
OPENAI_API_KEY |
openai-compatible |
Requires --base-url |
ollama |
http://localhost:11434/v1 by default |
Occupy a slot, with or without the agent:
lenz set-surrogate --state ./state.json --surrogate cake
lenz set-region --state ./state.json --policy turbo
lenz set-belief --state ./state.json --prior '{"x":{"dist":"normal","mu":0.3,"sigma":0.1}}'
lenz set-sampler --state ./state.json --sampler llambolenz create --state ./state.json \
--space '{"x1":{"kind":"range","lower":-5,"upper":10},"x2":{"kind":"range","lower":0,"upper":15}}' \
--objectives '{"y":"minimize"}' \
--surrogate cake --budget 30CAKE and LLAMBO inherit Sara's provider and model. Pass --kernel-llm-* or
--sampler-llm-* only to use a different model. TuRBO and πBO do not call an
LLM. CAKE evolves a GP kernel population inside lenz during
observe/submit [2]; that trace is not part of Sara's conversation.
Command reference: sara/prompts/LENZ_REF.md. To add a method, implement
LenzPlugin in lenz/plugins/, ship a {name}.md prompt beside it, and
register it in registry.py. See CONTRIBUTING.md.
Textbook functions such as Hartmann and Ackley have published optima that an LLM can recall. The synthetic harness therefore uses an anti-memorization sandbox: renamed parameters, a unit cube, and a shifted optimum. Scoring uses a hidden answer key outside the sandbox. List functions:
python3 -c "from benchmarks.functions import REGISTRY; print(sorted(REGISTRY))"./scripts/run_synthetic.sh hartmann6
./scripts/run_synthetic.sh hartmann6 --disclosure revealed
./scripts/run_synthetic.sh hartmann6 --disclosure revealed-shift
./scripts/run_synthetic.sh hartmann6 --backend sara-lenz --disclosure all
./scripts/run_synthetic.sh hartmann6 --warmup 7--disclosure controls how much identity the agent sees:
blind(default): renamed parameters, unit cube, shifted optimum, generic problem text. This is the search comparison, not a retrieval test.revealed-shift: real name and bounds, same shift as the blind run. Search is still required.revealed: the textbook problem, unshifted. The headline metric is whether evaluation 1 is already the known optimum.all: run the three levels. Needs a single--backend.
--backend is a comma list (vanilla, cake, turbo, sara-lenz,
sara-lenz-cake, sara-only), or all for vanilla + sara-lenz +
sara-lenz-cake. Every backend uses the same seeded Sobol warm-start,
defaulting to d+1 evaluations when a seed is set. Pass --warmup N to
override it for all selected backends.
gp_sample<dim> is a no-prior control (a fresh GP sample path, not in
REGISTRY). Run it the same way as hartmann6.
The mixed-type experiment is LoRA hyperparameter optimization on
BoLT (Black-box Optimization for LLM Tasks) [7]. There is no
textbook optimum to recall. The oracle is a deterministic emulator of
expensive LLM fine-tuning runs. The search space is always revealed (seven
mixed continuous, integer, and categorical variables). --context only
changes the story the agent reads, not the space:
domain(default): real LoRA/Qwen names and a short task description.generic: names, types, and bounds only. No domain prose.misleading: false LoRA folklore (dropout near 0.05,lora_target = 0, few layers) presented as known-good defaults.
pip install -e '.[bolt]'
./scripts/run_bolt.sh
./scripts/run_bolt.sh --backend vanilla,cake
./scripts/run_bolt.sh --context genericProvider and model come from .env or PROVIDER / MODEL. Completed and
in-flight legs are skipped. Plots land in compare.html next to the run, or
open plugbo-viz.
plugbo-viz is a local UI over run logs. Open a run to read the trial
table, the agent trace, tool-use over the run, and (when CAKE is on)
the kernel population. Search the sidebar, tick several runs to overlay
them, or switch to Experiments to put every condition in a group on one
regret chart.
plugbo-viz
plugbo-viz --root ./results/logs --port 9000You can also run python3 -m viz.merged_server to see a single merged regret
chart for all conditions, or open plugbo-viz to compare multiple runs.
pip install -e ".[dev]"
pytest -m "not slow"
./scripts/smoke_plugins.shOptional smoke flags and what they cover are in
CONTRIBUTING.md. The script header is the source of truth
for --live, --baseline, and any later flags.
Bug reports, new BO plugins, and benchmarks are welcome.
- CONTRIBUTING.md: setup, plugin protocol, adding a function
- Issues: bugs and proposals
- Code of Conduct
Please open an issue before a new slot, a large dependency, or a new experiment backend.
If you use PlugBO in your research, please cite:
@software{plugbo,
title = {PlugBO: A modular framework for agentic Bayesian optimization},
author = {Richard Cornelius Suwandi},
year = {2026},
publisher = {GitHub},
url = {https://github.com/richardcsuwandi/plugbo}
}MIT. See LICENSE. Contributions are under the same license.
-
Brunzema, P., Tiao, L., Le, N., De Angeli, K., Xuan, Y., Gligorijevic, D. Agentic Bayesian Optimization through Surrogate-Augmented Autoresearch. arXiv:2608.00316, 2026. Paper No official code (this repo is an independent re-implementation).
-
Suwandi, R. C., Yin, F., Wang, J., Li, R., Chang, T.-H., Theodoridis, S. Adaptive Kernel Design for Bayesian Optimization Is a Piece of CAKE with LLMs. NeurIPS 2025. Paper Code
-
Eriksson, D., Pearce, M., Gardner, J., Turner, R. D., Poloczek, M. Scalable Global Optimization via Local Bayesian Optimization. NeurIPS 2019. Paper Code
-
Hvarfner, C., Stoll, D., Souza, A., Lindauer, M., Hutter, F., Nardi, L. πBO: Augmenting Acquisition Functions with User Beliefs for Bayesian Optimization. ICLR 2022. Paper Code
-
Liu, T., Astorga, N., Seedat, N., van der Schaar, M. Large Language Models to Enhance Bayesian Optimization. ICLR 2024. Paper Code
-
Balandat, M., Karrer, B., Jiang, D. R., Daulton, S., Letham, B., Wilson, A. G., Bakshy, E. BoTorch: A Framework for Efficient Monte-Carlo Bayesian Optimization. NeurIPS 2020. Paper Code
-
Chew, R. W. T., Chen, Z., Hemachandra, A., Low, B. K. H. BoLT: A Benchmark to Democratize Black-box Optimization Research for Expensive LLM Tasks. arXiv:2605.17000, 2026. Paper Code
