Conversational context assembly for LLM interactions. CommBus injects keyword-triggered entries into prompts while respecting token budgets, providing intelligent context management for your AI applications.
- Keyword Matching - Wildcard patterns (
auth*), phrases ("two words"), word boundaries, and semantic similarity - Token Budget Management - Priority-based greedy fitting with intelligent section allocation
- Template Engine - Mustache support (BbMustache/ExMustache) with YAML frontmatter parsing
- Prompt Catalog - Persistent_term caching with FileSystem watching for hot reloading
- Storage Adapters - In-memory and Ecto, with a behaviour for custom adapters
- Methodologies - YAML-based curated prompt packs for reusable workflows
- Protocol Pipeline - ALF-based assembly with llm_core integration
- Mix Tasks - CLI utilities for entry inspection, budget simulation, and testing
- Telemetry Integration - Built-in observability for assembly operations
Add comm_bus to your list of dependencies in mix.exs:
def deps do
[
{:comm_bus, git: "https://github.com/fosferon/comm_bus.git"}
]
endNote: CommBus is not yet published on Hex. Use the git dependency for now.
alias CommBus.{Assembler, Conversation, Entry, Message}
# Define conversation
conversation = %Conversation{
messages: [
%Message{role: :user, content: "Need help with authentication."}
]
}
# Define context entries
entries = [
# Constant entry - always included
%Entry{
id: "system-rules",
mode: :constant,
section: :system,
token_count: 15,
content: "You are a helpful assistant. Be concise and accurate.",
priority: 100
},
# Triggered entry - only when keywords match
%Entry{
id: "auth-context",
mode: :triggered,
keywords: ["auth*", "login", "session"],
section: :pre_history,
token_count: 50,
content: "Authentication system uses JWT tokens with 24h expiration...",
priority: 80
}
]
# Assemble with budget
result = Assembler.assemble_prompt(
conversation,
entries,
budget: %{
total: 1000,
sections: %{
system: 100,
pre_history: 300,
history: 400,
post_history: 200
}
}
)
# Result contains sectioned messages ready for LLM
IO.inspect(result.messages)
IO.inspect(result.token_usage)Methodologies are curated prompt packs for common workflows:
# Load methodology entries
entries = CommBus.Methodologies.entries_for("bug_triage")
# Or load specific entry
entries = CommBus.Methodologies.entries_for("bug_triage#severity-check")
# Combine with custom entries
all_entries = entries ++ [
%Entry{id: "project-context", mode: :constant, content: "Project: MyApp..."}
]
# Assemble as usual
Assembler.assemble_prompt(conversation, all_entries)# Configure in config/config.exs
config :comm_bus,
storage: CommBus.Storage.EctoAdapter,
repo: MyApp.Repo
# Use in application
{:ok, conversation} = CommBus.Storage.get_conversation(conv_id)
{:ok, entries} = CommBus.Storage.list_entries(filters: [enabled: true])
result = Assembler.assemble_prompt(conversation, entries)alias CommBus.Protocol.LlmCoreAdapter
# 1. Assemble context
packet = Assembler.assemble_prompt(conversation, entries)
# 2. Convert to llm_core format
{:ok, llm_messages} = LlmCoreAdapter.to_provider_messages(packet)
# 3. Send to LLM via llm_core
{:ok, response} = LlmCore.complete(
llm_messages,
model: "gpt-4",
provider: :openai
)CommBus provides several CLI utilities for development and testing.
View entries from any storage adapter:
# List all entries from InMemory storage
mix comm_bus.entries --store InMemory
# Filter by mode
mix comm_bus.entries --store InMemory --mode triggered
# Filter by enabled state
mix comm_bus.entries --store InMemory --enabled trueSimulate token budget allocation:
mix comm_bus.budget \
--conversation test/fixtures/conversations/basic.yml \
--entries test/fixtures/entries/sample.yml \
--total 1000Full end-to-end assembly simulation:
mix comm_bus.simulate \
--conversation test/fixtures/conversations/basic.yml \
--entries test/fixtures/entries/sample.yml \
--budget 2000Compare BbMustache vs ExMustache rendering:
mix comm_bus.compare_enginesSynchronize golden template fixtures:
mix comm_bus.sync_fixturesCommBus includes a methodology system for reusable prompt packs.
bug_triage- Structured bug analysis and prioritization frameworkroot_cause- Root cause analysis methodology
# Get all entries from a methodology
entries = CommBus.Methodologies.entries_for("bug_triage")
# Get specific entry by fragment identifier
entries = CommBus.Methodologies.entries_for("bug_triage#step-1")
# Load multiple methodologies
entries = CommBus.Methodologies.entries_for([
"bug_triage",
"root_cause#analysis"
])
# List available methodologies
methodologies = CommBus.Methodologies.list()Place YAML files in config/comm_bus/methodologies/:
name: "API Development"
description: "Context entries for API development workflows"
slug: "api-dev"
tags: ["api", "rest", "development"]
entries:
- id: "rest-principles"
content: |
REST API Design Principles:
- Use HTTP methods correctly (GET, POST, PUT, DELETE)
- Resource-based URLs
- Stateless communication
keywords: ["api", "rest", "endpoint"]
section: pre_history
mode: triggered
priority: 80
weight: 1.0
- id: "error-handling"
content: "Always return appropriate HTTP status codes..."
keywords: ["error", "status", "response"]
section: pre_history
mode: triggered
priority: 70# config/config.exs
config :comm_bus,
# Template engine (BbMustache is default)
template_engine: CommBus.Template.Engine.BbMustache,
# Tokenizer implementation
tokenizer: CommBus.Tokenizer.Simple,
# Prompt directory
prompt_root: Path.expand("config/comm_bus/prompts", File.cwd!()),
# Methodology directory
methodology_root: Path.expand("config/comm_bus/methodologies", File.cwd!()),
# Storage adapter
storage: CommBus.Storage.InMemoryconfig :comm_bus,
storage: CommBus.Storage.InMemoryconfig :comm_bus,
storage: CommBus.Storage.EctoAdapter,
repo: MyApp.RepoYou can implement custom storage adapters by adopting the CommBus.Storage behaviour.
┌─────────────────┐
│ Application │
└────────┬────────┘
│
▼
┌─────────────────┐ ┌──────────────┐
│ CommBus │────▶│ Storage │
│ Assembler │ │ Adapter │
└────────┬────────┘ └──────────────┘
│
▼
┌─────────────────┐
│ Matcher │ ─── Keyword matching
└─────────────────┘
┌─────────────────┐
│ Budget │ ─── Token fitting
└─────────────────┘
┌─────────────────┐
│ Protocol │ ─── llm_core adapter
└────────┬────────┘
│
▼
┌─────────────────┐
│ LLM Provider │
└─────────────────┘
- Assembler - Orchestrates prompt assembly with keyword matching and budget fitting
- Matcher - Detects keyword triggers in conversation messages
- Budget - Fits entries within token constraints using priority-based selection
- Budget.Planner - Allocates tokens across sections (system, pre_history, history, post_history)
- Tokenizer - Counts tokens (pluggable implementation)
- Template.Engine - Renders Mustache templates with variable substitution
- Prompts - Manages prompt catalog with caching and file watching
- Protocol.Pipeline - ALF-based pipeline for assembly workflow
- Storage - Persistence layer with multiple adapter implementations
Injectable context with metadata:
%CommBus.Entry{
id: "unique-id",
content: "Context information...",
keywords: ["keyword1", "key*", "\"exact phrase\""],
section: :pre_history, # :system | :pre_history | :history | :post_history
mode: :triggered, # :constant | :triggered
priority: 80, # Higher = more important
weight: 1.0, # Multiplier for token budget
token_count: 50,
metadata: %{}
}OpenAI-compatible message format:
%CommBus.Message{
role: :user, # :system | :user | :assistant | :tool
content: "Message text...",
token_count: 10,
metadata: %{}
}Session state with message history:
%CommBus.Conversation{
id: "conv-123",
messages: [%Message{}, ...],
depth: 3, # Number of exchanges
metadata: %{}
}Assembly output ready for LLM:
%CommBus.Protocol.Packet{
messages: [%Message{}, ...], # Sectioned and assembled
sections: %{ # Messages grouped by section
system: [...],
pre_history: [...],
history: [...],
post_history: [...]
},
included_entries: [...], # Entries that fit in budget
excluded_entries: [...], # Entries that didn't fit
token_usage: %{ # Token accounting
total: 950,
by_section: %{...}
}
}# Run all tests
mix test
# Run with coverage
mix test --cover
# Run specific test file
mix test test/comm_bus/assembler_test.exs
# Run Mix task tests
mix test test/mix/tasks/
# Compare template engines
mix comm_bus.compare_engines
# Sync golden fixtures
mix comm_bus.sync_fixturesGenerate and view documentation locally:
mix docs
open doc/index.html- llm_core - LLM provider abstraction (sits below CommBus)
MIT — see LICENSE.