Bub is a tiny runtime for agents that live alongside people.
~200 lines of core code. Hooks reshape every turn stage. Tapes record every decision. Channels adapt to any surface â CLI, Telegram, or your own.
import bub
@bub.hookimpl
def build_prompt(session, tape):
"""Reconstruct context from tape records."""
messages = [{"role": "system", "content": session.system}]
for record in tape.entries:
messages.append({
"role": record.role,
"content": record.content,
})
return messages
@bub.hookimpl
def run_model(messages, config):
"""Call the LLM â override to swap providers."""
return litellm.completion(
model=config.model,
messages=messages,
) Features
Every decision has a reason.
Bub was designed for real multi-agent collaboration from day one â not retrofitted for it.
Hook-First
~200-line core. Every turn stage is a pluggy hook. Builtins are just default plugins â 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.
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