Skip to content

BubuStack Examples

Here we demonstrate BubuStack's workflow patterns, from a zero-dependency hello-world to full voice AI agents with realtime transport.

Every example includes a runnable walkthrough. When an example reuses shared infrastructure, its README calls that dependency out explicitly.

Design Philosophy

BubuStack follows the Unix philosophy: do one thing and do it well, and write programs to work together.

UnixBubuStackPrinciple
ProgramEngramDoes one thing well — transcribe audio, call an LLM, send a webhook
Pipeline (|)StoryComposes Engrams into a DAG, wiring outputs to inputs
stdin/stdoutStep outputsJSON flows between steps; each step reads its inputs and writes its output
Shell scriptStoryRunA concrete execution of the pipeline with specific inputs
cron / inotifyImpulseTriggers a pipeline on schedule, webhook, or Kubernetes event

An Engram that fetches HTTP knows nothing about AI summarization. A summarizer Engram knows nothing about Discord. The Story composes them — just as curl | jq | notify-send composes programs that each do one thing.

This means every component is independently testable, replaceable, and reusable. Swap Discord for Slack by changing one Engram ref. Replace OpenAI with Anthropic by pointing a step at a different Engram. The pipeline doesn't care.

Prerequisites

  • Kubernetes cluster (Kind works fine)
  • BubuStack operator (bobrapet) installed with CRDs
  • kubectl configured for your cluster
  • EngramTemplates and ImpulseTemplates deployed (see each example's prerequisites)

Examples that mention storage refs, materialization, or automatic payload offloading also require the shared S3-compatible storage setup from the Bobrapet quickstart. In this repo that usually means the SeaweedFS/S3 bootstrap with the bubu-default bucket.

That requirement is not limited to step outputs. Examples that submit large trigger payloads through StoryTrigger also rely on the same shared storage, because Bobrapet offloads oversized StoryRun.spec.inputs before creating the run.

Batch Examples

Batch pipelines run to completion — steps execute, produce output, and terminate.

ExampleDescriptionKey Patterns
Hello WorldZero-dependency quickstart — no API keys neededParallel steps, DAG ordering, output aggregation
Scheduled Health CheckCron-triggered parallel health checks with failure tolerance and AI summaryCron impulse, allowFailure, fan-out/fan-in
Multi-Model ConsensusSame question to 4 AI models (OpenAI + Anthropic), judge synthesizesCross-provider fan-out, http-request with custom auth
Map-Reduce SummarizerFetch and summarize multiple articles using map-reducemap-reduce-adapter, sub-stories, child StoryRuns
Content Digest (Simple)Single-feed RSS to AI newsletter to DiscordSequential pipeline, cron, MCP adapter, materialize
Content Digest (Advanced)Multi-feed map-reduce into a combined Discord newsletterMap-reduce + MCP, ConfigMap-driven feeds
GitHub PR ReviewWebhook-triggered AI code review that posts PR commentsGitHub webhook impulse, MCP adapter
Materialize DemoForced storage offloading and automatic data hydrationmaxInlineSize: 0, storage refs, materialize pod
Pod Crash NotifierK8s event watcher detects pod failures, AI analyzes, Discord alertsKubernetes impulse, CEL filter, event-driven batch

Realtime Examples

Realtime pipelines stay running — steps process data continuously through transport bindings.

ExampleDescriptionKey Patterns
LiveKit ChatRealtime room chat via LiveKit with AI responsesLiveKit webhook, bobravoz-grpc transport, room chat
LiveKit Live TranslationRealtime English-to-French speech translation in the same LiveKit roomVAD, STT, translation-only LLM, TTS, fixed session greeting
LiveKit Voice AssistantFull voice pipeline: VAD, STT, LLM, TTS, conversation memory11 realtime steps, 3 mux lanes, multi-path DAG

Watch the realtime examples demo: YouTube.

The LiveKit examples use dedicated namespaces: livekit-voice, livekit-chat, and livekit-translation. They follow the same split as the batch examples: bootstrap.yaml for namespace, TLS, and example-specific cluster-scoped resources, and secrets.yaml for credentials. Each realtime example is self-contained and should not depend on another example's bootstrap.

Across the repo, examples prefer controller-managed runner identities. Use the built-in Engram and Impulse RBAC extensions for namespaced extra access. If an example needs out-of-band cluster-scoped RBAC, it should use an explicit ServiceAccount and bind that identity directly. Published examples should not depend on implicit managed runner naming conventions in external RBAC objects. If an Engram pulls prompt or stdio config from a ConfigMap via $bubuConfigMapRef, it must also declare a named configmaps/get rule under spec.overrides.rbac.rules.

Directory Structure

examples/
batch/
hello-world/
scheduled-health-check/
multi-model-consensus/
map-reduce-summarizer/
content-digest-simple/
content-digest-advanced/
github-pr-review/
materialize-demo/
pod-crash-notifier/
realtime/
livekit-chat/
livekit-translation/
livekit-voice/

Each example directory contains:

  • README.md — What it demonstrates, architecture diagram, quick start, and CRD-level explanation
  • bootstrap.yaml — Namespace, TLS/RBAC, and any cluster-scoped resources
  • engrams.yaml — Engram definitions referencing EngramTemplates
  • story.yaml — Story DAG definition (some examples contain multiple Stories for sub-story patterns)
  • storyrun.yaml or impulse.yaml — Manual trigger or event-driven trigger
  • secrets.yaml or secrets.yaml.example — Credentials manifests or templates, when an example needs external secrets
  • prompts.yaml, stdio.yaml, feeds.yaml — ConfigMaps for prompts, MCP server config, or input data (when applicable)

CRDs Used

These examples exercise the following BubuStack Custom Resources:

CRDScopePurpose
StoryNamespacedWorkflow definition (DAG of steps)
StoryRunNamespacedConcrete execution of a Story
StepRunNamespacedSingle step execution within a StoryRun
EngramNamespacedConfigured instance of an EngramTemplate
EngramTemplateClusterReusable component definition
ImpulseNamespacedEvent-driven trigger
ImpulseTemplateClusterReusable trigger definition
TransportClusterRealtime transport configuration
TransportBindingNamespacedNamespaced binding connecting a step to a Transport for streaming

Execution mode: Stories declare spec.pattern: batch or spec.pattern: realtime to select their execution mode. Batch stories create Jobs; realtime stories create Deployments with streaming transport.

Suggested Learning Path

  1. Hello World — Understand Stories, StoryRuns, and parallel DAG execution
  2. Scheduled Health Check — Add cron triggers and failure tolerance
  3. Multi-Model Consensus — Fan-out to multiple AI providers
  4. Map-Reduce Summarizer — Dynamic fan-out with child StoryRuns
  5. Content Digest (Simple) — End-to-end pipeline with external integrations
  6. Materialize Demo — Storage-aware payloads and automatic hydration
  7. Pod Crash Notifier — Kubernetes-native event-driven batch workflows
  8. LiveKit Live Translation — Translation-only voice pipeline in a LiveKit room
  9. LiveKit Voice Assistant — Full realtime pipeline with transport

Contributing

See CONTRIBUTING.md for guidelines on adding or improving examples.

📄 License

Copyright 2025 BubuStack.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

Runnable BubuStack example workflows and walkthroughs, from simple batch Stories to full realtime LiveKit voice pipelines.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors