Repository navigation #
Bub 0.6.0 is the first stable release of the 0.6 line. It splits Bub into an embeddable agent kernel, bub.core, and the full app, bub[app]. It also moves model access to Republic and turns the agent loop into events that plugins and SDK users share. This note covers everything since 0.5.1. If you tested the 0.6.0 alphas, the changes after 0.6.0a3 are listed in Since 0.6.0a3.
Highlights #
pip install bub installs only the agent kernel
bub.core installs and imports without the rest of Bub. Its only dependencies are republic, pydantic, loguru and typing-extensions. The CLI, gateway, channels, plugin system and TUI prompts are in the app extra:
pip install "bub[app]" # full Bub: CLI, gateway, channels, plugins
pip install bub # kernel only, for embedding bub.core.Agent
If you run bub without the extra, it lists the missing packages and tells you how to install them. The Docker image, install.sh / install.ps1 and bub install already install bub[app].
An event-driven core Agent
bub.core.Agent runs the agent loop over a tape store and reports every step on an EventBus: RunStarted / RunFinished, LLMCallStarted / LLMCallFinished, ToolCallStarted / ToolCallFinished, StepFinished, MessagesPending, ChatFinished. It also accepts:
- Republic built-in tools (
WebSearch,WebFetch,CodeExecution,ImageGeneration,NativeTool) alongside ordinary tools. The provider runs them server-side. max_tool_concurrency=to limit how many tool calls from one response run at once.
The system prompt and tools are now prepared once per run, so the request prefix stays stable across the steps of a turn and prompt caching works better. The system prompt is recorded on the tape only when it changes.
Reuse Bub plugins with any core Agent
bub.hooks.agent.AgentPlugins connects plugin agent-loop hooks (before/after_llm_call, before/after_tool_call, continue_prompt, provide_steering_inbox, system_prompt, tape store/context/sidecar, load_state, provide_environment, and the new provide_tools) to any bub.core.Agent:
plugins = AgentPlugins() # builtin + installed plugins
agent = Agent(model=model, **plugins.components())
plugins.attach(agent)
BubAgent uses the same adapter, so plugins behave the same in both.
Code mode as a reusable component
Code mode lives in bub.core.codemode. Any core agent can use it without the app extra. Code can call Republic models and pass media attachments.
from bub.core.codemode import CodeMode
code_mode = CodeMode([search, fetch], models="openai:gpt-5")
agent = Agent(model=model, tools=[code_mode.run_code], system_prompt=["You are ...", code_mode.prompt])
Models and accounts through Republic
Built-in model requests use Republic for provider authentication, message encoding and streaming. Reasoning and provider data survive tape reload and replay.
- ChatGPT plan access:
codex:<model>withbub login codex(supports--device-auth).openai:<model>uses API credentials. - Named endpoints keep separate credentials. Provider-specific request fields go in
extra_body.
CLI improvements
bubwithout a command startsbub chat.bub --version/-V, andbub pluginsshows each loaded plugin's distribution and version.,modelcompletion lists the models each configured provider offers.,model <provider>:narrows the list to one provider.- Token speed is measured from the first streamed chunk. Usage events now report
elapsed_seconds,ttft_secondsandtotal_seconds. - Bub reports its status to the terminal with OSC 7501. The sequences are not written when output is redirected.
Docker images on GHCR
Each release publishes a multi-arch image: ghcr.io/bubbuild/bub:0.6.0, :0.6 and :latest. See Deploy the app.
New docs
The docs at bub.build are reorganized into SDK (bub.core) and app ( bub[app]) guides, in English and Chinese.
Fixes #
- Context size errors such as
exceed_context_size_errornow start the automatic handoff instead of failing the turn. - Models no longer call
tool_describeagain for deferred tools they have already loaded.tool_describelists them underalready_loaded. - The "reply via channel" instruction is added only to turns run by the channel manager, so
bub acpand directprocess_inbound()turns no longer look for a Telegram token. - A failed tool call is reported in
tool_resultsas aBubError, so consumers such as the ACP server can mark it failed. - The
bub chatprompt no longer redraws itself forever. - Fuzzy and non-ASCII tape search works again, and multi-byte UTF-8 characters split across shell output chunks are preserved.
- Tool calls recorded in Chat Completions format by older tapes replay correctly.
- Security updates for
aiohttp,multidict,urllib3,certifianduv.
Upgrade notes #
- Install the
appextra wherever you use the CLI, gateway, channels or plugins:pip install "bub[app]"/uv add "bub[app]".pip install -U bubalone leaves thebubcommand without its dependencies. - Module moves.
bub.tape,bub.tools,bub.storeandbub.sidecarsare now inbub.core.*. The old names still import as aliases, and so doLlmCallRequest/LlmCallResult/LlmCallDecision, so most 0.5.x plugins work unchanged. Code mode internals moved without aliases:bub.builtin.codemode.code_runner→bub.core.codemode.runner,bub.builtin.codemode.republic_bridge→bub.core.codemode.republic_bridge,LocalEnvironment/LocalProcess→bub.environment. - Event renames:
BeforeLlmCall→LLMCallStarted,AfterLlmCall→LLMCallFinished,BeforeToolCall→ToolCallStarted,AfterToolCall→ToolCallFinished,ChatCompleted→ChatFinished. Hook names are unchanged. - Tools.
@toolno longer registers tools globally, andbub.core.tools.REGISTRYis no longer filled. Plugins should provide tools with the newprovide_toolshook. Tools that an entry-point plugin creates with@toolat import time are still collected, with aDeprecationWarning. To look up tools, use an agent'stoolsorframework.get_tools(). - Agent overrides.
Agent.pending_messages,has_pending_messagesandcontinue_promptare gone. Handle theMessagesPendingevent and setStepFinished.next_promptinstead. - Failed tool results. Failed entries in
ToolExecution.tool_resultsand intool_resultsevent data are nowBubErrorinstances, not dicts. The tape still records them as dicts. Failed results are no longer spilled. - Models. For ChatGPT plan access, switch to
codex:<model>and runbub login codex. Pass provider options through to Republic, and put provider-specific fields inextra_body. - Smaller changes:
.envmoved frombub.frameworktobub.configure.run_onceis an async generator. The kernel'sFileTapeStorematches by substring; the builtin plugin still provides fuzzy search throughbub.builtin.store.FuzzyFileTapeStore.
Since 0.6.0a3 #
The breaking changes in this list are AgentPlugins / provide_tools (#371) and BubError tool results (#385). The other changes are Republic-based models and bub login codex (#349), OSC 7501 status (#345), per-run prompt and tool preparation (#376), the new CLI options and ,model completion (#377, #380, #381, bub → bub chat), the token speed fix (#386), the channel prompt fix (#384), the deferred tools fix (#387), the context size fix (#388), security updates (#374, #378) and the docs overhaul (#375).
Changes #
🚨 Breaking Changes
- Extract an event-driven core agent into bub.core - by @frostming in#356
(67407) - Install only bub.core by default and streamline the agent kernel - by @frostming in#361
(1a583) - Make code mode a reusable core component - by @frostming in#367
(52d2f) - Reuse plugin agent-loop hooks with core Agent through events - by @frostming andKimi in#371
(3a78b)
🚀 Features
- Expose republic models and media attachments in code mode - by @frostming andKimi in#351
(a826e) - Accept republic built-in tools in core Agent - by @frostming in#358
(56ae0) - Add max_tool_concurrency to core Agent - by @frostming in#366
(8963b) - Add OSC 7501 program status - by @PsiACE and@frostming in#345
(9348e) - Only record system prompt if it changes - by @frostming
(7608e) - Prepare the system prompt and tools once per run - by @frostming andKimi in#376
(65876) - List provider models for ,model completion and model options - by @frostming andKimi in#381
(15805) - cli :
- Add bub --version - by @frostming andKimi in#377
(5abc2) - Add bub plugins to show plugin versions - by @frostming andKimi in#380
(71d7d) - Set default command to 'chat' when no command is provided - by @frostming
(c2049)
- Add bub --version - by @frostming andKimi in#377
- Add bub --version - by
- website :
🐞 Bug Fixes
- Preserve UTF-8 across shell output chunks - by @yunyv in#360
(0bb39) - Restore fuzzy and Unicode tape search - by @yunyv in#365
(db418) - Carry failed tool calls as BubError in tool_results - by @frostming andKimi in#385
(e1fd3) - Let the channel manager inject the reply-via-channel prompt - by @frostming andKimi in#384
(fd877) - Stop the model from re deferred tools - by @frostming andKimi in#387
(a3f62) - Recognize context size errors for automatic handoff - by @PsiACE in#388
(ad057) - ci :
- cli :
- Stop the chat prompt from redrawing itself forever - by @frostming andKimi in#379
(e5df5) - Measure token speed from the first chunk and trim the toolbar - by @frostming in#386
(c1494)
- Stop the chat prompt from redrawing itself forever - by @frostming andKimi in#379
- Stop the chat prompt from redrawing itself forever - by
- deps :
- Patch aiohttp, multidict and urllib3 security advisories - in #374
(a93f5) - Patch certifi and uv security advisories - by @frostming andKimi in#378
(c1713)
- Patch aiohttp, multidict and urllib3 security advisories - in #374
- Patch aiohttp, multidict and urllib3 security advisories - in