Object-oriented dialogue framework for Python.
FlowForge lets you build conversational bots using a declarative YAML DSL where each state is a business object — not an abstract node in a state machine, but a real concept from your domain: pricing, support, checkout, booking.
YAML defines the dialogue structure. Python handles the logic. The engine connects them.
Traditional chatbot frameworks think in terms of states and transitions — abstract nodes connected by arrows. FlowForge thinks in terms of objects and signals:
| Traditional | FlowForge |
|---|---|
| State node | Business object (pricing, support, order) |
| Responses | What the object says about itself |
run: actions |
What the object does when activated |
auto_transitions |
Signals this object listens for |
response_transitions |
Follow-up actions after the object has spoken |
This means your bot's structure mirrors your business domain. Adding a new topic = adding a new object. Each object is self-contained: it knows what to say, what to do, and where to go next.
pip install pyflowforgeCreate scenario.yaml:
scenario:
name: shop_bot
initial_state: greeting
fallback: llm
intents:
ask_price:
- "how much does it cost"
- "what is the price"
greeting:
- "hello"
- "hi"
states:
# Object: Greeting — entry point, knows how to welcome
greeting:
responses:
- "Hello! Ask about prices or say help."
auto_transitions:
- target: pricing
when:
- type: intent
value: ask_price
- target: help
when:
- type: regex
value: 'help|support'
# Object: Pricing — knows everything about prices
pricing:
run:
- action: get_price
responses:
- "Price: {price} USD."
response_transitions:
- target: checkout
when:
- type: regex
value: 'yes|sure|buy'
# Object: Help — knows how to assist
help:
responses:
- "I can help with pricing and orders."
auto_transitions:
- target: greeting
when:
- type: intent
value: '*'
# Object: Checkout — handles purchases
checkout:
responses:
- "Order confirmed!"Run:
from flowforge import Bot
bot = Bot.from_yaml("scenario.yaml")
@bot.action("get_price")
def get_price(ctx):
return {"price": 100}
bot.run() # interactive console REPLOr use programmatically:
response = bot.send("how much does it cost?")
print(response.text) # "Price: 100 USD."
print(response.state) # "pricing"FlowForge is the brain. The channel (Telegram, Discord, web) is just ears and mouth:
from telegram.ext import ApplicationBuilder, MessageHandler, filters
from flowforge import Bot
bot = Bot.from_yaml("scenario.yaml")
async def handle_message(update, context):
user_id = str(update.effective_user.id)
response = bot.send(update.message.text, session_id=user_id)
await update.message.reply_text(response.text)
app = ApplicationBuilder().token("TOKEN").build()
app.add_handler(MessageHandler(filters.TEXT, handle_message))
app.run_polling()- Object-oriented DSL — states are business objects, not abstract nodes
- Hybrid API — YAML for dialogue structure, Python for business logic
- Pluggable intent detection — TF-IDF out of the box, bring your own classifier
- LLM fallback — rule-based for known paths, LLM for everything else
- Knowledge base — attach a
knowledge.mdfile for LLM-powered Q&A - Persistent sessions — SQLite store included, plug in Redis/Postgres/anything
- Trigger types — regex, pattern matching, intent classification
- Session management — multiple independent conversations by session_id
- Actions — Python functions via
@bot.action(), Node.js via subprocess - Debugging —
verbose=Truefor step-by-step engine trace - Channel-agnostic —
bot.send(text) -> response, connect to anything - Zero heavy dependencies — only
pyyaml
Full DSL reference, Python API, and examples: docs/dsl.md
MIT