fast2flow
Overview
Section titled “Overview”fast2flow is a high-performance routing extension that routes incoming messages to the appropriate flow using deterministic token-based scoring (BM25) with optional LLM fallback.
Core concept: A user sends a message like “refund please” → fast2flow checks tenant-specific indexes → returns a routing directive (Dispatch, Respond, Deny, or Continue).
Key principles:
- Deterministic first — Token-based BM25 scoring for predictable, explainable routing
- Fail-open — Errors, timeouts, or missing indexes produce a
Continuedirective - Time-bounded — Hard timeout enforcement via
time_budget_ms - Policy-driven — Runtime behavior changes without code changes
Architecture
Section titled “Architecture”Incoming Message │ ▼┌──────────────────────────────────────────────────┐│ fast2flow Pipeline ││ ││ ┌────────────────────────────────────────────┐ ││ │ 1. Hook Filter │ ││ │ Allow/deny lists, respond rules, policy │ ││ └────────────────────────────────────────────┘ ││ │ ││ ┌────────────────────────────────────────────┐ ││ │ 2. Index Lookup │ ││ │ Load TF-IDF index for tenant scope │ ││ └────────────────────────────────────────────┘ ││ │ ││ ┌────────────────────────────────────────────┐ ││ │ 3. Deterministic Strategy (BM25) │ ││ │ Token scoring with title boosting (2x) │ ││ └────────────────────────────────────────────┘ ││ │ ││ ┌────────────────────────────────────────────┐ ││ │ 4. Confidence Gate │ ││ │ min_confidence threshold check │ ││ └────────────────────────────────────────────┘ ││ │ ││ ┌────────────────────────────────────────────┐ ││ │ 5. LLM Fallback (optional) │ ││ │ OpenAI or Ollama for ambiguous cases │ ││ └────────────────────────────────────────────┘ │└──────────────────────────────────────────────────┘ │ ▼Routing Directive (Dispatch / Respond / Deny / Continue)Routing Directives
Section titled “Routing Directives”Every routing decision produces one of four directives:
| Directive | Purpose | Fields |
|---|---|---|
dispatch | Route to a specific flow | target, confidence, reason |
respond | Return an immediate response | message |
deny | Block the request | reason |
continue | No decision — let the caller handle it | — |
// Dispatch to a flow{"type": "dispatch", "target": "support-pack:refund_request", "confidence": 0.92, "reason": "BM25 match"}
// Auto-respond without routing{"type": "respond", "message": "Use the self-service refund form at /refund."}
// Block the request{"type": "deny", "reason": "Denied by scope policy"}
// Pass through (fail-open default){"type": "continue"}Installation
Section titled “Installation”fast2flow is distributed as a .gtpack artifact via GHCR:
# Pull from GHCRoras pull ghcr.io/greentic-biz/providers/routing-hook/fast2flow.gtpack:latest
# Or reference a specific versionoras pull ghcr.io/greentic-biz/providers/routing-hook/fast2flow.gtpack:v0.4.6The pack registers a post_ingress hook that intercepts messages before they reach any flow.
WASM Components
Section titled “WASM Components”fast2flow ships three WASM components (targeting wasm32-wasip2):
| Component | Purpose | Operation |
|---|---|---|
| Indexer | Builds a searchable TF-IDF index from flow metadata | build, update |
| Matcher | Fast BM25-based intent matching against the index | match |
| Router | Orchestrates the full routing pipeline | route |
These components are coordinated by three flows defined in the pack:
# flows/index.ygtc — Runs at deploy time to build indexes# flows/match.ygtc — Runtime BM25 intent matching# flows/route.ygtc — Full routing pipeline with LLM fallbackBundle Workflow
Section titled “Bundle Workflow”fast2flow indexes flows from your bundle’s .ygtc files. The indexer scans your bundle directory, extracts metadata (title, description, tags), and builds a TF-IDF index with BM25 scoring.
Bundle Structure
Section titled “Bundle Structure”my-bundle/├── packs/│ ├── support-pack/│ │ └── flows/│ │ ├── refund.ygtc│ │ ├── shipping.ygtc│ │ └── faq.ygtc│ └── hr-pack/│ └── flows/│ ├── leave.ygtc│ └── booking.ygtcFlow Definition (.ygtc)
Section titled “Flow Definition (.ygtc)”Each flow file provides the metadata used for intent matching:
id: refund_requesttitle: Process Refund Requestdescription: Handle customer refund requests for orders and paymentstype: messagingtags: - refund - payment - billing - returnstart: collect_info
nodes: collect_info: templating.handlebars: text: "Please provide your order number for the refund." routing: - out: trueBuilding the Index
Section titled “Building the Index”Use the CLI to build an index from your bundle:
greentic-fast2flow bundle index \ --bundle ./my-bundle \ --output ./state/indexes \ --tenant demo \ --team default \ --verboseThis produces:
index.json— TF-IDF index with term frequencies and document frequenciesintents.md— Human-readable intent documentation
Validating a Bundle
Section titled “Validating a Bundle”greentic-fast2flow bundle validate --bundle ./my-bundlePolicy Configuration
Section titled “Policy Configuration”Policies control routing behavior at runtime without code changes. They are JSON files loaded from /mnt/registry/fast2flow-policy.json or a custom path.
Policy Structure
Section titled “Policy Structure”{ "stage_order": ["scope", "channel", "provider"], "default": { "min_confidence": 0.5, "llm_min_confidence": 0.5, "candidate_limit": 20 }, "scope_overrides": [], "channel_overrides": [], "provider_overrides": []}Policy Rules
Section titled “Policy Rules”All rule fields are optional — only specified fields are applied:
| Field | Type | Description |
|---|---|---|
min_confidence | f32 | Minimum BM25 score to dispatch (0.0–1.0) |
llm_min_confidence | f32 | Minimum LLM confidence to dispatch (0.0–1.0) |
candidate_limit | usize | Maximum candidates to evaluate |
allow_channels | string[] | Whitelist channels (null = allow all) |
deny_channels | string[] | Blacklist channels |
allow_providers | string[] | Whitelist providers (null = allow all) |
deny_providers | string[] | Blacklist providers |
allow_scopes | string[] | Whitelist scopes (null = allow all) |
deny_scopes | string[] | Blacklist scopes |
respond_rules | object[] | Auto-respond rules (keyword matching) |
Override Examples
Section titled “Override Examples”Overrides are applied in stage order (scope → channel → provider) with priority sorting within each stage.
Scope override — stricter confidence for a VIP tenant:
{ "id": "vip-tenant", "priority": 10, "scope": "tenant-vip", "rules": { "min_confidence": 0.8, "candidate_limit": 10 }}Channel override — auto-respond on email channel:
{ "id": "email-autorespond", "priority": 20, "channel": "email", "rules": { "respond_rules": [ { "needle": "refund", "message": "Refund requests via email take 3–5 business days. Use chat for instant support.", "mode": "contains" } ] }}Provider override — restrict to specific provider:
{ "id": "slack-only", "priority": 30, "provider": "slack", "rules": { "deny_providers": ["telegram"] }}Respond Rules
Section titled “Respond Rules”Auto-respond rules match text before the routing pipeline runs:
{ "needle": "business hours", "message": "Our business hours are Mon–Fri 9AM–5PM UTC.", "mode": "contains"}Supported modes: exact, contains (default), regex.
Policy Management CLI
Section titled “Policy Management CLI”# Print default policygreentic-fast2flow policy print-default
# Validate a policy filegreentic-fast2flow policy validate --file ./my-policy.jsonLLM Fallback
Section titled “LLM Fallback”When the deterministic BM25 strategy produces low confidence scores, fast2flow can fall back to an LLM for classification.
| Provider | Environment Variables |
|---|---|
| OpenAI | FAST2FLOW_OPENAI_API_KEY_PATH, FAST2FLOW_OPENAI_MODEL_PATH |
| Ollama | FAST2FLOW_OLLAMA_ENDPOINT_PATH, FAST2FLOW_OLLAMA_MODEL_PATH |
| Disabled | FAST2FLOW_LLM_PROVIDER=disabled (default) |
# Enable OpenAI fallbackFAST2FLOW_LLM_PROVIDER=openai \FAST2FLOW_OPENAI_API_KEY_PATH=/run/secrets/openai-key \greentic-fast2flow-routing-host < request.jsonCLI Reference
Section titled “CLI Reference”Bundle Commands
Section titled “Bundle Commands”# Build TF-IDF index from bundlegreentic-fast2flow bundle index \ --bundle ./my-bundle \ --output ./indexes \ --tenant demo \ --team default \ --generate-docs \ --verbose
# Validate bundle has indexable flowsgreentic-fast2flow bundle validate --bundle ./my-bundleIndex Commands
Section titled “Index Commands”# Build index from flow definitions JSONgreentic-fast2flow index build \ --scope tenant-a \ --flows flows.json \ --output /tmp/indexes
# Inspect a built indexgreentic-fast2flow index inspect \ --scope tenant-a \ --input /tmp/indexesRoute Commands
Section titled “Route Commands”# Simulate a routing decisiongreentic-fast2flow route simulate \ --scope tenant-a \ --text "I need a refund" \ --indexes-path /tmp/indexesPolicy Commands
Section titled “Policy Commands”# Print default policy templategreentic-fast2flow policy print-default
# Validate policy filegreentic-fast2flow policy validate --file policy.jsonEnvironment Variables
Section titled “Environment Variables”| Variable | Default | Description |
|---|---|---|
FAST2FLOW_LLM_PROVIDER | disabled | LLM provider: disabled, openai, ollama |
FAST2FLOW_POLICY_PATH | /mnt/registry/fast2flow-policy.json | Policy file path |
FAST2FLOW_TRACE_POLICY | — | Set to 1 to emit policy trace to stderr |
FAST2FLOW_MIN_CONFIDENCE | 0.5 | Default minimum confidence threshold |
FAST2FLOW_LLM_MIN_CONFIDENCE | 0.5 | Default LLM minimum confidence |
FAST2FLOW_CANDIDATE_LIMIT | 20 | Default max candidates |
Performance
Section titled “Performance”fast2flow is optimized for low-latency routing:
| Stage | Typical Latency |
|---|---|
| Hook filter (allow/deny) | < 0.1ms |
| BM25 index lookup | < 1ms |
| Policy resolution | < 0.1ms |
| LLM fallback (if enabled) | 200–500ms |
Best Practices
Section titled “Best Practices”- Write descriptive titles — Title words get 2x TF-IDF boost for better scoring
- Use specific tags — Tags are the primary signal for BM25 matching
- Set appropriate thresholds — Start with
min_confidence: 0.5and tune up - Use policies for overrides — Change behavior per scope/channel/provider without redeploying
- Monitor Continue rate — High
Continueoutput indicates gaps in your flow coverage - Keep LLM as fallback — Deterministic routing is faster and more predictable
Next Steps
Section titled “Next Steps”- Flows Guide — Learn about
.ygtcflow definitions - Packs Guide — Understand
.gtpackdistribution - Control Chains Reference — Hook registration and policies