kbs 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/deploy-github-pages.yml +52 -0
  3. data/CHANGELOG.md +68 -2
  4. data/README.md +291 -362
  5. data/docs/advanced/custom-persistence.md +775 -0
  6. data/docs/advanced/debugging.md +726 -0
  7. data/docs/advanced/index.md +8 -0
  8. data/docs/advanced/performance.md +865 -0
  9. data/docs/advanced/testing.md +827 -0
  10. data/docs/api/blackboard.md +1157 -0
  11. data/docs/api/engine.md +1047 -0
  12. data/docs/api/facts.md +1212 -0
  13. data/docs/api/index.md +12 -0
  14. data/docs/api/rules.md +1104 -0
  15. data/docs/architecture/blackboard.md +544 -0
  16. data/docs/architecture/index.md +277 -0
  17. data/docs/architecture/network-structure.md +343 -0
  18. data/docs/architecture/rete-algorithm.md +737 -0
  19. data/docs/assets/css/custom.css +83 -0
  20. data/docs/assets/images/blackboard-architecture.svg +136 -0
  21. data/docs/assets/images/compiled-network.svg +101 -0
  22. data/docs/assets/images/fact-assertion-flow.svg +117 -0
  23. data/docs/assets/images/fact-rule-relationship.svg +65 -0
  24. data/docs/assets/images/fact-structure.svg +42 -0
  25. data/docs/assets/images/inference-cycle.svg +47 -0
  26. data/docs/assets/images/kb-components.svg +43 -0
  27. data/docs/assets/images/kbs.jpg +0 -0
  28. data/docs/assets/images/pattern-matching-trace.svg +136 -0
  29. data/docs/assets/images/rete-network-layers.svg +96 -0
  30. data/docs/assets/images/rule-structure.svg +44 -0
  31. data/docs/assets/images/system-layers.svg +69 -0
  32. data/docs/assets/images/trading-signal-network.svg +139 -0
  33. data/docs/assets/js/mathjax.js +17 -0
  34. data/docs/examples/index.md +223 -0
  35. data/docs/guides/blackboard-memory.md +589 -0
  36. data/docs/guides/dsl.md +1321 -0
  37. data/docs/guides/facts.md +652 -0
  38. data/docs/guides/getting-started.md +385 -0
  39. data/docs/guides/index.md +23 -0
  40. data/docs/guides/negation.md +529 -0
  41. data/docs/guides/pattern-matching.md +561 -0
  42. data/docs/guides/persistence.md +451 -0
  43. data/docs/guides/variable-binding.md +491 -0
  44. data/docs/guides/writing-rules.md +914 -0
  45. data/docs/index.md +155 -0
  46. data/docs/installation.md +156 -0
  47. data/docs/quick-start.md +221 -0
  48. data/docs/what-is-a-fact.md +694 -0
  49. data/docs/what-is-a-knowledge-base.md +350 -0
  50. data/docs/what-is-a-rule.md +833 -0
  51. data/examples/.gitignore +1 -0
  52. data/examples/README.md +2 -2
  53. data/examples/advanced_example.rb +2 -2
  54. data/examples/advanced_example_dsl.rb +224 -0
  55. data/examples/ai_enhanced_kbs.rb +1 -1
  56. data/examples/ai_enhanced_kbs_dsl.rb +538 -0
  57. data/examples/blackboard_demo_dsl.rb +50 -0
  58. data/examples/car_diagnostic.rb +1 -1
  59. data/examples/car_diagnostic_dsl.rb +54 -0
  60. data/examples/concurrent_inference_demo.rb +5 -6
  61. data/examples/concurrent_inference_demo_dsl.rb +362 -0
  62. data/examples/csv_trading_system.rb +1 -1
  63. data/examples/csv_trading_system_dsl.rb +525 -0
  64. data/examples/iot_demo_using_dsl.rb +1 -1
  65. data/examples/portfolio_rebalancing_system.rb +2 -2
  66. data/examples/portfolio_rebalancing_system_dsl.rb +613 -0
  67. data/examples/redis_trading_demo_dsl.rb +177 -0
  68. data/examples/rule_source_demo.rb +123 -0
  69. data/examples/run_all.rb +50 -0
  70. data/examples/run_all_dsl.rb +49 -0
  71. data/examples/stock_trading_advanced.rb +1 -1
  72. data/examples/stock_trading_advanced_dsl.rb +404 -0
  73. data/examples/temp_dsl.txt +9392 -0
  74. data/examples/timestamped_trading.rb +1 -1
  75. data/examples/timestamped_trading_dsl.rb +258 -0
  76. data/examples/trading_demo.rb +1 -1
  77. data/examples/trading_demo_dsl.rb +322 -0
  78. data/examples/working_demo.rb +1 -1
  79. data/examples/working_demo_dsl.rb +160 -0
  80. data/lib/kbs/blackboard/engine.rb +3 -3
  81. data/lib/kbs/blackboard/fact.rb +1 -1
  82. data/lib/kbs/condition.rb +1 -1
  83. data/lib/kbs/decompiler.rb +204 -0
  84. data/lib/kbs/dsl/knowledge_base.rb +101 -2
  85. data/lib/kbs/dsl/variable.rb +1 -1
  86. data/lib/kbs/dsl.rb +3 -1
  87. data/lib/kbs/{rete_engine.rb → engine.rb} +42 -1
  88. data/lib/kbs/fact.rb +1 -1
  89. data/lib/kbs/version.rb +1 -1
  90. data/lib/kbs.rb +15 -13
  91. data/mkdocs.yml +181 -0
  92. metadata +74 -9
  93. data/examples/stock_trading_system.rb.bak +0 -563
@@ -0,0 +1,544 @@
1
+ # Blackboard Architecture
2
+
3
+ The Blackboard pattern is a powerful approach to multi-agent problem-solving where independent knowledge sources collaborate through a shared workspace.
4
+
5
+ ## Overview
6
+
7
+ ![Blackboard Architecture](../assets/images/blackboard-architecture.svg)
8
+
9
+ *Blackboard system with multiple agents reading and writing to shared persistent memory with pluggable storage backends.*
10
+
11
+ ## Core Concept
12
+
13
+ The blackboard architecture consists of three main components:
14
+
15
+ 1. **Blackboard (Memory)**: Central shared workspace for facts
16
+ 2. **Knowledge Sources (Agents)**: Independent experts that read and write facts
17
+ 3. **Control Component**: Coordinates agent execution (often via rules)
18
+
19
+ Agents operate asynchronously, triggered by changes to the blackboard state. Each agent:
20
+ - Reads relevant facts from the blackboard
21
+ - Performs reasoning or computation
22
+ - Writes conclusions back to the blackboard
23
+ - Triggers other agents via fact changes
24
+
25
+ ## KBS Implementation
26
+
27
+ ### Blackboard::Memory
28
+
29
+ The central workspace that replaces `WorkingMemory` with persistence:
30
+
31
+ ```ruby
32
+ require 'kbs/blackboard'
33
+
34
+ # Create blackboard with SQLite backend
35
+ memory = KBS::Blackboard::Memory.new(db_path: 'knowledge_base.db')
36
+
37
+ # Add facts (persisted automatically)
38
+ fact = memory.add_fact(:stock, {
39
+ symbol: "AAPL",
40
+ price: 150.50,
41
+ timestamp: Time.now
42
+ })
43
+ # => #<KBS::Blackboard::Fact uuid="abc-123" ...>
44
+
45
+ # Query facts
46
+ stocks = memory.facts_of_type(:stock)
47
+ # => [#<KBS::Blackboard::Fact ...>, ...]
48
+
49
+ # Facts survive process restart
50
+ memory2 = KBS::Blackboard::Memory.new(db_path: 'knowledge_base.db')
51
+ memory2.facts_of_type(:stock)
52
+ # => Still there!
53
+ ```
54
+
55
+ **Implementation**: `lib/kbs/blackboard/memory.rb`
56
+
57
+ ### Blackboard::Engine
58
+
59
+ RETE engine with persistent blackboard memory:
60
+
61
+ ```ruby
62
+ # Create engine with blackboard
63
+ engine = KBS::Blackboard::Engine.new(db_path: 'trading.db')
64
+
65
+ # Define rules using DSL (persisted in the database)
66
+ kb = KBS.knowledge_base(engine: engine) do
67
+ rule "buy_signal" do
68
+ on :stock, symbol: :sym?, price: :price?
69
+ on :threshold, symbol: :sym?, max: :max?
70
+
71
+ perform do |facts, bindings|
72
+ if bindings[:price?] < bindings[:max?]
73
+ # Write new fact to blackboard
74
+ fact :order,
75
+ symbol: bindings[:sym?],
76
+ action: "BUY",
77
+ price: bindings[:price?]
78
+ end
79
+ end
80
+ end
81
+
82
+ # Facts trigger rules, which create new facts
83
+ fact :stock, symbol: "AAPL", price: 145.0
84
+ fact :threshold, symbol: "AAPL", max: 150.0
85
+ run
86
+ # => Creates :order fact in blackboard
87
+ end
88
+ ```
89
+
90
+ **Implementation**: `lib/kbs/blackboard/engine.rb`
91
+
92
+ ### Message Queue
93
+
94
+ Priority-based communication between agents:
95
+
96
+ ```ruby
97
+ memory = KBS::Blackboard::Memory.new(db_path: 'system.db')
98
+ queue = memory.message_queue
99
+
100
+ # Agent 1: Post high-priority message
101
+ queue.post("risk_analysis", {
102
+ alert: "High volatility detected",
103
+ severity: "critical"
104
+ }, priority: 10)
105
+
106
+ # Agent 2: Read and process messages
107
+ messages = queue.read("risk_analysis", limit: 5)
108
+ messages.each do |msg|
109
+ puts "Processing: #{msg[:data][:alert]}"
110
+ queue.acknowledge(msg[:id])
111
+ end
112
+
113
+ # Unacknowledged messages remain in queue
114
+ pending = queue.pending("risk_analysis")
115
+ ```
116
+
117
+ **Implementation**: `lib/kbs/blackboard/message_queue.rb`
118
+
119
+ ### Audit Log
120
+
121
+ Complete history of all changes for compliance and debugging:
122
+
123
+ ```ruby
124
+ memory = KBS::Blackboard::Memory.new(db_path: 'audit.db')
125
+ audit = memory.audit_log
126
+
127
+ # All fact changes are logged automatically
128
+ fact = memory.add_fact(:stock, symbol: "AAPL", price: 150)
129
+ memory.update_fact(fact.id, price: 155)
130
+ memory.remove_fact(fact)
131
+
132
+ # Query audit trail
133
+ history = audit.fact_history(fact.id)
134
+ # => [
135
+ # { action: "created", timestamp: ..., data: {price: 150} },
136
+ # { action: "updated", timestamp: ..., data: {price: 155} },
137
+ # { action: "deleted", timestamp: ... }
138
+ # ]
139
+
140
+ # See what rules fired
141
+ rule_log = audit.rules_fired(limit: 10)
142
+ # => [
143
+ # { rule_name: "buy_signal", timestamp: ..., facts: [...] },
144
+ # ...
145
+ # ]
146
+
147
+ # Recent changes across all facts
148
+ recent = audit.recent_changes(limit: 20)
149
+ ```
150
+
151
+ **Implementation**: `lib/kbs/blackboard/audit_log.rb`
152
+
153
+ ## Persistence Backends
154
+
155
+ ### SQLite Store (Default)
156
+
157
+ Best for: Single-process applications, development, small-to-medium data.
158
+
159
+ ```ruby
160
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
161
+ ```
162
+
163
+ **Pros:**
164
+ - ✅ Zero configuration (no server needed)
165
+ - ✅ ACID transactions
166
+ - ✅ Durable across restarts
167
+ - ✅ Simple backup (copy .db file)
168
+ - ✅ Full-text search capabilities
169
+
170
+ **Cons:**
171
+ - ⚠️ Slower than Redis (still fast for most use cases)
172
+ - ⚠️ Single-writer limitation
173
+ - ⚠️ Not distributed
174
+
175
+ **Schema:**
176
+ ```sql
177
+ CREATE TABLE facts (
178
+ id TEXT PRIMARY KEY,
179
+ fact_type TEXT NOT NULL,
180
+ attributes TEXT NOT NULL, -- JSON
181
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
182
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
183
+ );
184
+
185
+ CREATE TABLE audit_log (
186
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
187
+ fact_id TEXT,
188
+ action TEXT NOT NULL,
189
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
190
+ data TEXT -- JSON
191
+ );
192
+
193
+ CREATE TABLE messages (
194
+ id TEXT PRIMARY KEY,
195
+ topic TEXT NOT NULL,
196
+ priority INTEGER DEFAULT 0,
197
+ data TEXT NOT NULL, -- JSON
198
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
199
+ acknowledged BOOLEAN DEFAULT 0
200
+ );
201
+ ```
202
+
203
+ **Implementation**: `lib/kbs/blackboard/persistence/sqlite_store.rb`
204
+
205
+ ### Redis Store
206
+
207
+ Best for: High-throughput applications, distributed systems, real-time trading.
208
+
209
+ ```ruby
210
+ store = KBS::Blackboard::Persistence::RedisStore.new(
211
+ url: 'redis://localhost:6379/0'
212
+ )
213
+ engine = KBS::Blackboard::Engine.new(store: store)
214
+ ```
215
+
216
+ **Pros:**
217
+ - ✅ **100x faster** than SQLite for reads/writes
218
+ - ✅ Supports distributed agents (multiple processes, machines)
219
+ - ✅ Built-in pub/sub for real-time notifications
220
+ - ✅ Atomic operations
221
+ - ✅ TTL support for ephemeral facts
222
+
223
+ **Cons:**
224
+ - ⚠️ Requires Redis server
225
+ - ⚠️ Volatile by default (enable RDB/AOF for durability)
226
+ - ⚠️ More complex deployment
227
+
228
+ **Data Structures:**
229
+ ```
230
+ # Facts stored as Redis hashes
231
+ fact:{uuid} → { type: "stock", symbol: "AAPL", price: 150 }
232
+
233
+ # Indexes for efficient queries
234
+ facts:type:stock → Set of fact UUIDs
235
+ facts:active → Set of all active fact UUIDs
236
+
237
+ # Messages as sorted sets (by priority)
238
+ messages:risk_alerts → ZSet[(msg1, priority), (msg2, priority), ...]
239
+
240
+ # Audit as lists
241
+ fact_history:{uuid} → List of change records
242
+ rules_fired:all → List of rule executions
243
+ ```
244
+
245
+ **Implementation**: `lib/kbs/blackboard/persistence/redis_store.rb`
246
+
247
+ ### Hybrid Store
248
+
249
+ Best for: Production systems needing speed + durability + audit.
250
+
251
+ ```ruby
252
+ store = KBS::Blackboard::Persistence::HybridStore.new(
253
+ redis_url: 'redis://localhost:6379/0',
254
+ db_path: 'audit.db'
255
+ )
256
+ engine = KBS::Blackboard::Engine.new(store: store)
257
+ ```
258
+
259
+ **Strategy:**
260
+ - **Redis**: Facts and messages (fast access)
261
+ - **SQLite**: Audit log (durable history)
262
+
263
+ **Pros:**
264
+ - ✅ Fast fact operations (Redis)
265
+ - ✅ Durable audit trail (SQLite)
266
+ - ✅ Best of both worlds
267
+
268
+ **Cons:**
269
+ - ⚠️ Requires both Redis and SQLite
270
+ - ⚠️ Slightly more complex
271
+
272
+ **Implementation**: `lib/kbs/blackboard/persistence/hybrid_store.rb`
273
+
274
+ ## Multi-Agent Example
275
+
276
+ Trading system with four specialized agents:
277
+
278
+ ```ruby
279
+ # Shared blackboard
280
+ engine = KBS::Blackboard::Engine.new(db_path: 'trading.db')
281
+
282
+ kb = KBS.knowledge_base(engine: engine) do
283
+ # Agent 1: Market Data Collector
284
+ rule "collect_data", priority: 5 do
285
+ on :market_open, status: true
286
+ without :stock_data, symbol: :sym?
287
+
288
+ perform do |facts, bindings|
289
+ price = fetch_current_price(bindings[:sym?])
290
+ fact :stock_data,
291
+ symbol: bindings[:sym?],
292
+ price: price,
293
+ timestamp: Time.now
294
+ end
295
+ end
296
+
297
+ # Agent 2: Signal Generator
298
+ rule "generate_signals", priority: 10 do
299
+ on :stock_data, symbol: :sym?, price: :price?
300
+ on :sma_data, symbol: :sym?, sma: :sma?
301
+
302
+ perform do |facts, bindings|
303
+ if bindings[:price?] > bindings[:sma?]
304
+ fact :signal,
305
+ symbol: bindings[:sym?],
306
+ direction: "BUY",
307
+ strength: (bindings[:price?] / bindings[:sma?]) - 1.0
308
+ end
309
+ end
310
+ end
311
+
312
+ # Agent 3: Risk Manager
313
+ rule "check_risk", priority: 20 do
314
+ on :signal, symbol: :sym?, direction: :dir?
315
+ on :portfolio, symbol: :sym?, position: :pos?
316
+
317
+ perform do |facts, bindings|
318
+ if bindings[:pos?] > 1000 && bindings[:dir?] == "BUY"
319
+ fact :risk_alert,
320
+ symbol: bindings[:sym?],
321
+ reason: "Position limit exceeded"
322
+ else
323
+ fact :approved_signal,
324
+ symbol: bindings[:sym?],
325
+ direction: bindings[:dir?]
326
+ end
327
+ end
328
+ end
329
+
330
+ # Agent 4: Order Executor
331
+ rule "execute_orders", priority: 30 do
332
+ on :approved_signal, symbol: :sym?, direction: :dir?
333
+ without :risk_alert, symbol: :sym?
334
+
335
+ perform do |facts, bindings|
336
+ execute_trade(bindings[:sym?], bindings[:dir?])
337
+ fact :execution,
338
+ symbol: bindings[:sym?],
339
+ direction: bindings[:dir?],
340
+ timestamp: Time.now
341
+ end
342
+ end
343
+
344
+ # Trigger the system
345
+ fact :market_open, status: true
346
+ fact :portfolio, symbol: "AAPL", position: 500
347
+
348
+ # Agents collaborate through blackboard
349
+ run
350
+ end
351
+ ```
352
+
353
+ ## Transactions
354
+
355
+ Ensure atomic multi-fact updates:
356
+
357
+ ```ruby
358
+ memory = KBS::Blackboard::Memory.new(db_path: 'trades.db')
359
+
360
+ memory.transaction do
361
+ # All or nothing
362
+ order = memory.add_fact(:order, {
363
+ symbol: "AAPL",
364
+ action: "BUY",
365
+ quantity: 100
366
+ })
367
+
368
+ execution = memory.add_fact(:execution, {
369
+ order_id: order.id,
370
+ price: 150.50,
371
+ timestamp: Time.now
372
+ })
373
+
374
+ memory.update_fact(order.id, status: "filled")
375
+
376
+ # If any operation fails, entire transaction rolls back
377
+ end
378
+ ```
379
+
380
+ **Nested transactions** are supported via reference counting.
381
+
382
+ ## Best Practices
383
+
384
+ ### 1. Agent Specialization
385
+ Each agent should focus on one aspect of the problem:
386
+ - ✅ Data collection
387
+ - ✅ Signal generation
388
+ - ✅ Risk assessment
389
+ - ✅ Execution
390
+
391
+ ### 2. Priority-Based Execution
392
+ Use rule priorities to ensure correct agent ordering:
393
+ ```ruby
394
+ data_collector: priority: 5
395
+ signal_generator: priority: 10
396
+ risk_manager: priority: 20
397
+ executor: priority: 30
398
+ ```
399
+
400
+ ### 3. Fact Versioning
401
+ Include timestamps for temporal reasoning:
402
+ ```ruby
403
+ engine.add_fact(:price, {
404
+ symbol: "AAPL",
405
+ value: 150,
406
+ timestamp: Time.now,
407
+ source: "market_data_feed"
408
+ })
409
+ ```
410
+
411
+ ### 4. Message Acknowledgment
412
+ Always acknowledge processed messages:
413
+ ```ruby
414
+ messages = queue.read("alerts", limit: 10)
415
+ messages.each do |msg|
416
+ process_alert(msg[:data])
417
+ queue.acknowledge(msg[:id]) # Important!
418
+ end
419
+ ```
420
+
421
+ ### 5. Audit Everything
422
+ Use audit log for debugging and compliance:
423
+ ```ruby
424
+ # When something goes wrong, trace back
425
+ audit = memory.audit_log
426
+ changes = audit.recent_changes(limit: 100)
427
+ changes.each do |change|
428
+ puts "#{change[:timestamp]}: #{change[:action]} on #{change[:fact_type]}"
429
+ end
430
+ ```
431
+
432
+ ## Performance Tuning
433
+
434
+ ### Choose the Right Backend
435
+
436
+ | Backend | Use Case | Performance | Durability |
437
+ |---------|----------|-------------|------------|
438
+ | SQLite | Development, single-process | Good | Excellent |
439
+ | Redis | High-frequency trading, distributed | Excellent | Good (with AOF) |
440
+ | Hybrid | Production systems | Excellent | Excellent |
441
+
442
+ ### Batch Operations
443
+
444
+ ```ruby
445
+ # Bad: Individual adds (slow)
446
+ 1000.times do |i|
447
+ memory.add_fact(:reading, sensor: i, value: rand)
448
+ end
449
+
450
+ # Good: Transaction batch (fast)
451
+ memory.transaction do
452
+ 1000.times do |i|
453
+ memory.add_fact(:reading, sensor: i, value: rand)
454
+ end
455
+ end
456
+ ```
457
+
458
+ ### Index Strategy (SQLite)
459
+
460
+ ```sql
461
+ -- Add indexes for frequent queries
462
+ CREATE INDEX idx_facts_type ON facts(fact_type);
463
+ CREATE INDEX idx_facts_created ON facts(created_at);
464
+ CREATE INDEX idx_messages_topic ON messages(topic, priority);
465
+ ```
466
+
467
+ ### Redis Memory Management
468
+
469
+ ```ruby
470
+ # Set TTL for ephemeral facts
471
+ store = KBS::Blackboard::Persistence::RedisStore.new(
472
+ url: 'redis://localhost:6379/0',
473
+ ttl: 3600 # Facts expire after 1 hour
474
+ )
475
+ ```
476
+
477
+ ## Advanced Patterns
478
+
479
+ ### Opportunistic Triggering
480
+
481
+ Agents activate when their preconditions are met:
482
+
483
+ ```ruby
484
+ # Trigger fires only when specific fact exists
485
+ kb = KBS.knowledge_base(engine: engine) do
486
+ rule "on_critical_alert" do
487
+ on :alert, severity: "critical"
488
+
489
+ perform do |facts, bindings|
490
+ notify_team(facts[0])
491
+ end
492
+ end
493
+ end
494
+ ```
495
+
496
+ ### Blackboard Focus
497
+
498
+ Limit agent attention to relevant facts:
499
+
500
+ ```ruby
501
+ # Agent only sees recent stock data
502
+ kb = KBS.knowledge_base(engine: engine) do
503
+ rule "analyze_recent" do
504
+ on :stock_data,
505
+ symbol: :sym?,
506
+ timestamp: :ts?,
507
+ predicate: lambda { |f| Time.now - f[:timestamp] < 300 } # Last 5 minutes
508
+
509
+ perform do |facts, bindings|
510
+ # Process recent data only
511
+ end
512
+ end
513
+ end
514
+ ```
515
+
516
+ ### Conflict Resolution
517
+
518
+ When multiple agents could act, use priorities:
519
+
520
+ ```ruby
521
+ kb = KBS.knowledge_base(engine: engine) do
522
+ # High priority: Stop-loss overrides everything
523
+ rule "stop_loss", priority: 100 do
524
+ # ...
525
+ end
526
+
527
+ # Medium priority: Risk management
528
+ rule "risk_check", priority: 50 do
529
+ # ...
530
+ end
531
+
532
+ # Low priority: Normal trading signals
533
+ rule "buy", priority: 10 do
534
+ # ...
535
+ end
536
+ end
537
+ ```
538
+
539
+ ## Next Steps
540
+
541
+ - **[Network Structure](network-structure.md)** - How blackboard integrates with RETE
542
+ - **[Persistence Guide](../guides/persistence.md)** - Choosing and configuring backends
543
+ - **[Blackboard Examples](../examples/index.md#advanced-features)** - Complete working systems
544
+ - **[Custom Persistence](../advanced/custom-persistence.md)** - Build your own backend