Bub is a tiny agent runtime, composable with plugins.
Start with a working agent. Use plugins to change how it thinks, remembers, and connects.
from bub import hookimplfrom bub.envelope import content_of
class MyPlugin: @hookimpl def build_prompt(self, message, session_id, state): """Shape what the model sees this turn.""" context = state.get("context", "") return f"{context}\n{content_of(message)}"
@hookimpl async def run_model(self, prompt, session_id, state): """Swap the provider — any client, any API.""" reply = await my_client.complete( prompt, model=state.get("model") ) return reply.textInstall
Quick Start
Pick a preset, add plugins as needed. Done.
curl -fsSL https://bub.build/install.sh | bashpowershell -ExecutionPolicy ByPass -c "irm https://bub.build/install.ps1 | iex"Features
Every decision has a reason.
Bub was designed for real multi-agent collaboration from day one — not retrofitted for it.
Composable by Design
A small core with replaceable defaults. Every turn stage is a pluggy hook — use Python plugins to override any stage without forking the runtime.
Tape Context
Context is reconstructed from append-only tape records, not accumulated in session state. No lossy summaries, no phantom memory.
Channel-Agnostic
The same process_inbound() pipeline drives CLI, Telegram, and any channel you add. Hooks never know which surface they're on.
Batteries Included
CLI, chat, gateway, comma commands, and the default agent runtime all ship as ordinary plugins. Useful on day one, replaceable when you need control.
Operator Equivalence
Humans and agents share the same operator model: same boundaries, same evidence trails, same handoff semantics. No special cases.
Plugin System
Python entry-points under group="bub". Later-registered plugins run first and override earlier ones. No framework privilege.
Architecture
Hooks define every turn stage.
Every stage in a Bub turn is a pluggy hook. The built-in implementation is just another plugin.
Override any stage by registering your own. Later plugins take priority. No forking, no framework privilege.
| time | op | key | payload | |
|---|---|---|---|---|
| 14:32:01 | user_msg | e_101 | "explain hooks" | |
| 14:32:02 | build_prompt | e_102 | system + 12 msgs | |
| 14:32:04 | model_reply | e_103 | "Hooks are pluggy…" | |
| 14:32:04 | tool_call | e_104 | read_docs("hooks") | |
| 14:32:05 | tool_result | e_105 | {ok: true, lines: 47} | |
| handoff phase → correction, owner: agent | ||||
| 14:32:06 | correction | e_106 | ← e_103 supersedes e_103 | |
| 14:32:07 | model_reply | e_107 | "Updated: Hooks use pluggy…" | |
| 14:32:08 | save_state | e_108 | tape flushed ✓ | |
Context model
Tape: a unified fact model.
Context isn't accumulated in session state. It's reconstructed from an append-only tape — a sequence of immutable facts. Entries record what happened; anchors mark phase boundaries and carry structured state.
Corrections append new facts that supersede old ones — never overwrite. Views are assembled from anchors forward, not inherited wholesale. Every decision is auditable, replayable, and forkable.
Python SDK
Build your agent with the SDK.
Bub now provides an SDK that integrates with your existing services.
-
Define your own tools
Use Python functions to bring your own logic and extend what the Agent can do.
-
Customize with events
Add logic at key moments to adapt how the Agent runs.
-
Keep memory in Tape
Persist conversations and work with history branches.
import republicfrom bub.core import Agentfrom bub.core.events import ToolCallStartedfrom bub.core.tools import tool
@tooldef get_weather(city: str) -> str: """Get the current weather for a city.""" return f"{city}: 22°C, sunny"
agent = Agent(tools=[get_weather], system_prompt="Be concise.")
@agent.events.on(ToolCallStarted)def log_tool_call(event: ToolCallStarted) -> None: print(f"Calling {event.call.tool}: {event.call.arguments}")
async with republic.get_model("openai:gpt-5-mini") as model: async with agent.run("Weather in Paris?", model=model, tape="demo") as stream: async for event in stream: if event.kind == "text": print(event.data["delta"], end="", flush=True)Community
What people are saying.
使用 bub 作为一个 build block 构建你自己的 agent 产品、服务你的业务,而不是学习复杂的概念然后无从下手。
PsiACE
@repsiace
再强烈推荐一遍 LLM 时代难得的这么优雅的代码了
yihong
@yihong0618
我一直想要有一个类似于 Cloud Code 一样的通用 Agent 框架,但我一直有点懒得自己开始去做这件事情。然后看到了 bub,感觉完美符合了心中所想的一个 Agent 框架。
earayu
@earayu
bub是属于短小精悍,里面有很多思考精神,值得学习
卡比卡比
@jakevin7
使用 bub 作为一个 build block 构建你自己的 agent 产品、服务你的业务,而不是学习复杂的概念然后无从下手。
PsiACE
@repsiace
再强烈推荐一遍 LLM 时代难得的这么优雅的代码了
yihong
@yihong0618
我一直想要有一个类似于 Cloud Code 一样的通用 Agent 框架,但我一直有点懒得自己开始去做这件事情。然后看到了 bub,感觉完美符合了心中所想的一个 Agent 框架。
earayu
@earayu
bub是属于短小精悍,里面有很多思考精神,值得学习
卡比卡比
@jakevin7