Package a Bub application
Build on the Bub app when you want its configuration, plugins, and message routing in your product. You can host BubFramework in an existing process or ship a command that starts it.
This path uses the application dependencies in Install Bub. For a program that directly composes an Agent and its components, follow Build your own agent.
Embed the application
Section titled “Embed the application”Use BubFramework.process_inbound to run the application’s full turn: resolve the session, load state, prepare the prompt, execute, save state, render, and dispatch.
import asyncio
from bub import BubFramework
from bub.envelope import content_of
async def main() -> None:
framework = BubFramework()
framework.load_hooks()
async with framework.running():
result = await framework.process_inbound({
"session_id": "embedded:demo",
"channel": "embedded",
"chat_id": "demo",
"content": "Describe what you can help with.",
})
for outbound in result.outbounds:
print(content_of(outbound))
asyncio.run(main())
Configure a model before running this example. load_hooks() loads builtin hooks and installed plugin entry points. The sample prints returned envelopes; a connected channel or plugin can also dispatch them.
Keep framework.running() open for the service’s lifetime. It acquires hook-provided resources and runs the cleanup supplied by their context managers on exit. Enter it before creating an agent that needs the framework’s store, and avoid overlapping scopes on one framework instance.
process_inbound returns a completed TurnResult. With stream_output=True, it consumes the stream through the bound channel router before returning that result. The host owns concurrent message scheduling and any per-session locking it requires.
Reuse plugins in your own service
Section titled “Reuse plugins in your own service”A host can use plugin-provided tools, stores, or hooks while keeping its own API and stream handling. Follow Reuse plugins in your agent to connect those capabilities to core.Agent.
BubAgent also carries the application’s prompts and channel delivery conventions. Choose it when you want those application behaviors, and provide the corresponding output handling in your host.
Ship your own command
Section titled “Ship your own command”A package can expose Bub’s command entry point under its own name:
# src/my_bub/cli.py
def main() -> None:
from bub.__main__ import main as bub_main
bub_main()
[project.scripts]
my-bub = "my_bub.cli:main"
Users can then run my-bub chat or my-bub gateway. Set a product-specific working directory before calling Bub if your application requires one; the framework takes its initial workspace from the current directory.
Declare bub[app]>=0.6.0 as the application dependency. When upgrading an existing distribution, follow Upgrade to 0.6.0.
Bundle plugins and skills
Section titled “Bundle plugins and skills”One wheel can provide several entry points:
[project.entry-points."bub"]
models = "my_bub.models"
channels = "my_bub.channels:ChannelPlugin"
[tool.hatch.build.targets.wheel]
packages = ["src/my_bub", "src/skills"]
Each target follows the plugin registration rules. Include task instructions using the skills package layout.
Before release, install the built wheel into a separate environment. Run the command, confirm the plugin report, load a packaged skill, and exercise a representative conversation. For a hosted application, also check shutdown while a stream or background tool is active.