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