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,589 @@
1
+ # Blackboard Memory
2
+
3
+ The blackboard pattern enables multiple agents to collaborate through a shared persistent workspace. This guide covers using KBS's blackboard memory for multi-agent systems, audit trails, and persistent knowledge bases.
4
+
5
+ ## What is Blackboard Memory?
6
+
7
+ The blackboard architecture consists of three components:
8
+
9
+ 1. **Blackboard** (`KBS::Blackboard::Memory`) - Central shared workspace
10
+ 2. **Knowledge Sources** (Agents) - Independent specialists that read/write facts
11
+ 3. **Control** (Rules + Priority) - Determines which agent acts when
12
+
13
+ ![Blackboard Architecture](../assets/images/blackboard-architecture.svg)
14
+
15
+ *KBS uses the blackboard pattern for persistent, multi-agent reasoning with complete audit trails.*
16
+
17
+ ## Basic Usage
18
+
19
+ ### Creating a Blackboard Engine
20
+
21
+ ```ruby
22
+ require 'kbs'
23
+
24
+ # With SQLite (default)
25
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
26
+
27
+ kb = KBS.knowledge_base(engine: engine) do
28
+ # Facts persist across restarts
29
+ fact :sensor, id: "bedroom", temp: 28
30
+ end
31
+
32
+ kb.close
33
+
34
+ # Next run
35
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
36
+ kb = KBS.knowledge_base(engine: engine)
37
+ puts kb.engine.facts.size # => 1
38
+ ```
39
+
40
+ ### Blackboard vs Regular Engine
41
+
42
+ ```ruby
43
+ # Regular engine (transient)
44
+ kb_regular = KBS.knowledge_base do
45
+ fact :foo, bar: 1
46
+ end
47
+ # Lost on exit
48
+
49
+ # Blackboard engine (persistent)
50
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
51
+ kb_blackboard = KBS.knowledge_base(engine: engine) do
52
+ fact :foo, bar: 1
53
+ end
54
+ kb_blackboard.close
55
+ # Persisted to database
56
+ ```
57
+
58
+ ## Persistent Facts
59
+
60
+ ### Fact Lifecycle
61
+
62
+ ```ruby
63
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
64
+
65
+ # Create fact
66
+ fact = engine.add_fact(:sensor, id: "bedroom", temp: 28)
67
+
68
+ # Fact has UUID
69
+ puts fact.id # => "550e8400-e29b-41d4-a716-446655440000"
70
+
71
+ # Update fact
72
+ engine.update_fact(fact.id, temp: 30)
73
+
74
+ # Query fact history
75
+ history = engine.fact_history(fact.id)
76
+ history.each do |entry|
77
+ puts "#{entry[:timestamp]}: #{entry[:operation]} - #{entry[:attributes]}"
78
+ end
79
+
80
+ # Delete fact
81
+ engine.delete_fact(fact.id)
82
+ ```
83
+
84
+ ### Fact Attributes
85
+
86
+ Blackboard facts support the same interface as regular facts:
87
+
88
+ ```ruby
89
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
90
+ fact = engine.add_fact(:stock, symbol: "AAPL", price: 150)
91
+
92
+ # Access
93
+ fact.type # => :stock
94
+ fact[:symbol] # => "AAPL"
95
+ fact.attributes # => { symbol: "AAPL", price: 150 }
96
+ fact.id # => UUID string
97
+
98
+ # Metadata
99
+ fact.created_at # => Time object
100
+ fact.updated_at # => Time object
101
+ ```
102
+
103
+ ## Message Queue
104
+
105
+ The blackboard includes a priority-based message queue for agent communication:
106
+
107
+ ### Sending Messages
108
+
109
+ ```ruby
110
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
111
+
112
+ # Add message to queue
113
+ engine.send_message(:alerts, "High temperature detected", priority: 10)
114
+ engine.send_message(:alerts, "Critical failure", priority: 100) # Higher priority
115
+ ```
116
+
117
+ ### Receiving Messages
118
+
119
+ ```ruby
120
+ # Pop highest priority message
121
+ msg = engine.pop_message(:alerts)
122
+ puts msg[:content] # => "Critical failure"
123
+ puts msg[:priority] # => 100
124
+
125
+ # Process all messages
126
+ while (msg = engine.pop_message(:alerts))
127
+ process_alert(msg[:content])
128
+ end
129
+ ```
130
+
131
+ ### Message Topics
132
+
133
+ Organize messages by topic:
134
+
135
+ ```ruby
136
+ # Different topics for different concerns
137
+ engine.send_message(:sensor_alerts, "Temp spike", priority: 50)
138
+ engine.send_message(:system_events, "Startup complete", priority: 10)
139
+ engine.send_message(:user_notifications, "Welcome!", priority: 1)
140
+
141
+ # Agents process their own topics
142
+ sensor_agent_msg = engine.pop_message(:sensor_alerts)
143
+ system_msg = engine.pop_message(:system_events)
144
+ user_msg = engine.pop_message(:user_notifications)
145
+ ```
146
+
147
+ ## Audit Trail
148
+
149
+ Blackboard automatically logs all changes:
150
+
151
+ ### Fact Audit Log
152
+
153
+ ```ruby
154
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
155
+
156
+ # Add fact
157
+ fact = engine.add_fact(:order, id: 1, status: "pending")
158
+
159
+ # Update fact
160
+ engine.update_fact(fact.id, status: "processing")
161
+
162
+ # Delete fact
163
+ engine.delete_fact(fact.id)
164
+
165
+ # Query audit trail
166
+ history = engine.fact_history(fact.id)
167
+ history.each do |entry|
168
+ puts "#{entry[:timestamp]}: #{entry[:operation]}"
169
+ puts " Attributes: #{entry[:attributes]}"
170
+ end
171
+
172
+ # Output:
173
+ # 2025-01-15 10:00:00: add
174
+ # Attributes: {id: 1, status: "pending"}
175
+ # 2025-01-15 10:01:00: update
176
+ # Attributes: {id: 1, status: "processing"}
177
+ # 2025-01-15 10:02:00: delete
178
+ # Attributes: {id: 1, status: "processing"}
179
+ ```
180
+
181
+ ### Rule Firing Log
182
+
183
+ ```ruby
184
+ # Enable rule firing audit
185
+ engine = KBS::Blackboard::Engine.new(
186
+ db_path: 'kb.db',
187
+ audit_rules: true
188
+ )
189
+
190
+ kb = KBS.knowledge_base(engine: engine) do
191
+ rule "my_rule" do
192
+ on :trigger, {}
193
+ perform { }
194
+ end
195
+
196
+ fact :trigger, {}
197
+ run
198
+ end
199
+
200
+ # Query rule firings
201
+ firings = engine.rule_firings(rule_name: "my_rule")
202
+ firings.each do |firing|
203
+ puts "Rule '#{firing[:rule_name]}' fired at #{firing[:timestamp]}"
204
+ puts " Facts: #{firing[:fact_ids]}"
205
+ puts " Bindings: #{firing[:bindings]}"
206
+ end
207
+ ```
208
+
209
+ ## Multi-Agent Systems
210
+
211
+ ### Agent Pattern
212
+
213
+ ```ruby
214
+ class Agent
215
+ def initialize(name, engine)
216
+ @name = name
217
+ @engine = engine
218
+ end
219
+
220
+ def observe
221
+ # Read facts from blackboard
222
+ @engine.facts.select { |f| relevant?(f) }
223
+ end
224
+
225
+ def decide(observations)
226
+ # Apply agent's expertise
227
+ # Return action or nil
228
+ end
229
+
230
+ def act(action)
231
+ # Write facts to blackboard
232
+ # Send messages to other agents
233
+ end
234
+
235
+ def run
236
+ observations = observe
237
+ action = decide(observations)
238
+ act(action) if action
239
+ end
240
+ end
241
+ ```
242
+
243
+ ### Example: Trading System
244
+
245
+ ```ruby
246
+ class MarketDataAgent < Agent
247
+ def run
248
+ # Fetch market data
249
+ data = fetch_market_data()
250
+
251
+ # Post to blackboard
252
+ @engine.add_fact(:market_data, {
253
+ symbol: data[:symbol],
254
+ price: data[:price],
255
+ volume: data[:volume],
256
+ timestamp: Time.now
257
+ })
258
+ end
259
+ end
260
+
261
+ class TradingAgent < Agent
262
+ def run
263
+ # Observe market data
264
+ market_facts = @engine.facts.select { |f| f.type == :market_data }
265
+
266
+ market_facts.each do |fact|
267
+ # Apply trading strategy
268
+ if buy_signal?(fact)
269
+ @engine.add_fact(:order, {
270
+ symbol: fact[:symbol],
271
+ type: "buy",
272
+ quantity: calculate_quantity(fact),
273
+ price: fact[:price]
274
+ })
275
+
276
+ @engine.send_message(:execution, "New buy order", priority: 50)
277
+ end
278
+ end
279
+ end
280
+
281
+ def buy_signal?(fact)
282
+ # Agent's expertise
283
+ fact[:price] < moving_average(fact[:symbol]) * 0.95
284
+ end
285
+ end
286
+
287
+ class ExecutionAgent < Agent
288
+ def run
289
+ # Check for execution messages
290
+ while (msg = @engine.pop_message(:execution))
291
+ # Find pending orders
292
+ orders = @engine.facts.select { |f|
293
+ f.type == :order && !f[:executed]
294
+ }
295
+
296
+ orders.each do |order|
297
+ execute_order(order)
298
+
299
+ # Update fact
300
+ @engine.update_fact(order.id, executed: true)
301
+
302
+ # Notify
303
+ @engine.send_message(:notifications, "Order executed", priority: 10)
304
+ end
305
+ end
306
+ end
307
+ end
308
+
309
+ # Run agents in loop
310
+ engine = KBS::Blackboard::Engine.new(db_path: 'trading.db')
311
+
312
+ market_agent = MarketDataAgent.new("Market", engine)
313
+ trading_agent = TradingAgent.new("Trading", engine)
314
+ execution_agent = ExecutionAgent.new("Execution", engine)
315
+
316
+ loop do
317
+ market_agent.run # Fetch data → blackboard
318
+ trading_agent.run # Analyze → create orders
319
+ execution_agent.run # Execute orders
320
+ sleep 1
321
+ end
322
+ ```
323
+
324
+ ## Transactions
325
+
326
+ Blackboard supports ACID transactions (SQLite backend):
327
+
328
+ ```ruby
329
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
330
+
331
+ # Transaction succeeds
332
+ engine.transaction do
333
+ engine.add_fact(:account, id: 1, balance: 1000)
334
+ engine.add_fact(:account, id: 2, balance: 500)
335
+ end
336
+ # Both facts committed
337
+
338
+ # Transaction fails
339
+ begin
340
+ engine.transaction do
341
+ engine.add_fact(:account, id: 3, balance: 100)
342
+ raise "Error!"
343
+ engine.add_fact(:account, id: 4, balance: 200) # Never reached
344
+ end
345
+ rescue => e
346
+ puts "Transaction rolled back"
347
+ end
348
+ # No facts committed
349
+ ```
350
+
351
+ ## Observers
352
+
353
+ Monitor blackboard changes in real-time:
354
+
355
+ ```ruby
356
+ class FactObserver
357
+ def update(operation, fact)
358
+ case operation
359
+ when :add
360
+ puts "Fact added: #{fact.type} - #{fact.attributes}"
361
+ when :remove
362
+ puts "Fact removed: #{fact.type} - #{fact.attributes}"
363
+ when :update
364
+ puts "Fact updated: #{fact.type} - #{fact.attributes}"
365
+ end
366
+ end
367
+ end
368
+
369
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
370
+ observer = FactObserver.new
371
+ engine.memory.add_observer(observer)
372
+
373
+ engine.add_fact(:sensor, temp: 28)
374
+ # Output: Fact added: sensor - {:temp=>28}
375
+ ```
376
+
377
+ ## Performance Tuning
378
+
379
+ ### SQLite Optimization
380
+
381
+ ```ruby
382
+ engine = KBS::Blackboard::Engine.new(
383
+ db_path: 'kb.db',
384
+ journal_mode: 'WAL', # Write-Ahead Logging
385
+ synchronous: 'NORMAL', # Balance durability/speed
386
+ cache_size: -64000, # 64MB cache
387
+ busy_timeout: 5000 # Wait 5s for locks
388
+ )
389
+ ```
390
+
391
+ ### Redis for Speed
392
+
393
+ ```ruby
394
+ require 'kbs/blackboard/persistence/redis_store'
395
+
396
+ store = KBS::Blackboard::Persistence::RedisStore.new(
397
+ url: 'redis://localhost:6379/0'
398
+ )
399
+
400
+ engine = KBS::Blackboard::Engine.new(store: store)
401
+
402
+ # 10-100x faster than SQLite
403
+ # Perfect for high-frequency updates
404
+ ```
405
+
406
+ ### Hybrid for Production
407
+
408
+ ```ruby
409
+ require 'kbs/blackboard/persistence/hybrid_store'
410
+
411
+ store = KBS::Blackboard::Persistence::HybridStore.new(
412
+ redis_url: 'redis://localhost:6379/0',
413
+ db_path: 'audit.db'
414
+ )
415
+
416
+ engine = KBS::Blackboard::Engine.new(store: store)
417
+
418
+ # Fast access (Redis) + durable audit (SQLite)
419
+ ```
420
+
421
+ ## Best Practices
422
+
423
+ ### 1. Use UUIDs for Fact References
424
+
425
+ ```ruby
426
+ # Good: Store fact UUID
427
+ order_id = engine.add_fact(:order, { ... }).id
428
+ engine.add_fact(:payment, order_id: order_id)
429
+
430
+ # Bad: Use attribute as reference
431
+ engine.add_fact(:order, id: 1)
432
+ engine.add_fact(:payment, order_id: 1) # Fragile
433
+ ```
434
+
435
+ ### 2. Namespace Facts by Agent
436
+
437
+ ```ruby
438
+ # Good: Clear ownership
439
+ engine.add_fact(:market_agent_data, { ... })
440
+ engine.add_fact(:trading_agent_signal, { ... })
441
+
442
+ # Bad: Generic names
443
+ engine.add_fact(:data, { ... })
444
+ engine.add_fact(:signal, { ... })
445
+ ```
446
+
447
+ ### 3. Use Messages for Coordination
448
+
449
+ ```ruby
450
+ # Good: Explicit coordination
451
+ engine.send_message(:execution_queue, "Process order #123", priority: 50)
452
+
453
+ # Bad: Polling facts
454
+ loop do
455
+ orders = engine.facts.select { |f| f.type == :pending_order }
456
+ # Inefficient
457
+ end
458
+ ```
459
+
460
+ ### 4. Clean Up Old Facts
461
+
462
+ ```ruby
463
+ # Remove stale data
464
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
465
+
466
+ kb = KBS.knowledge_base(engine: engine) do
467
+ rule "cleanup_old_facts", priority: 1 do
468
+ on :market_data,
469
+ timestamp: :time?,
470
+ predicate: lambda { |f|
471
+ (Time.now - f[:timestamp]) > 3600 # 1 hour old
472
+ }
473
+
474
+ perform do |facts, bindings|
475
+ engine.remove_fact(facts[0])
476
+ end
477
+ end
478
+ end
479
+ ```
480
+
481
+ ### 5. Use Transactions for Multi-Fact Updates
482
+
483
+ ```ruby
484
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
485
+
486
+ # Good: Atomic updates
487
+ engine.transaction do
488
+ engine.update_fact(account1_id, balance: new_balance1)
489
+ engine.update_fact(account2_id, balance: new_balance2)
490
+ end
491
+
492
+ # Bad: Separate updates (not atomic)
493
+ engine.update_fact(account1_id, balance: new_balance1)
494
+ engine.update_fact(account2_id, balance: new_balance2)
495
+ ```
496
+
497
+ ## Common Patterns
498
+
499
+ ### Leader Election
500
+
501
+ ```ruby
502
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
503
+
504
+ kb = KBS.knowledge_base(engine: engine) do
505
+ # Agent attempts to become leader
506
+ rule "become_leader" do
507
+ on :agent, name: :name?
508
+ without :leader, {}
509
+
510
+ perform do |facts, bindings|
511
+ fact :leader, name: bindings[:name?]
512
+ puts "#{bindings[:name?]} is now leader"
513
+ end
514
+ end
515
+ end
516
+ ```
517
+
518
+ ### Distributed Locking
519
+
520
+ ```ruby
521
+ # Acquire lock
522
+ def acquire_lock(engine, resource_id, agent_id)
523
+ engine.transaction do
524
+ lock = engine.facts.find { |f|
525
+ f.type == :lock && f[:resource_id] == resource_id
526
+ }
527
+
528
+ if lock.nil?
529
+ engine.add_fact(:lock, {
530
+ resource_id: resource_id,
531
+ owner: agent_id,
532
+ acquired_at: Time.now
533
+ })
534
+ true
535
+ else
536
+ false
537
+ end
538
+ end
539
+ end
540
+
541
+ # Release lock
542
+ def release_lock(engine, resource_id, agent_id)
543
+ lock = engine.facts.find { |f|
544
+ f.type == :lock &&
545
+ f[:resource_id] == resource_id &&
546
+ f[:owner] == agent_id
547
+ }
548
+
549
+ engine.remove_fact(lock) if lock
550
+ end
551
+ ```
552
+
553
+ ### Event Sourcing
554
+
555
+ ```ruby
556
+ engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
557
+
558
+ # Store events as facts
559
+ engine.add_fact(:event, {
560
+ type: "order_created",
561
+ aggregate_id: "order-123",
562
+ data: { item: "Widget", quantity: 5 },
563
+ timestamp: Time.now
564
+ })
565
+
566
+ # Reconstruct state from events
567
+ def rebuild_order(engine, order_id)
568
+ events = engine.facts
569
+ .select { |f| f.type == :event && f[:aggregate_id] == order_id }
570
+ .sort_by { |f| f[:timestamp] }
571
+
572
+ state = {}
573
+ events.each do |event|
574
+ apply_event(state, event)
575
+ end
576
+ state
577
+ end
578
+ ```
579
+
580
+ ## Next Steps
581
+
582
+ - **[Persistence](persistence.md)** - Storage backend options
583
+ - **[Architecture](../architecture/blackboard.md)** - Blackboard implementation details
584
+ - **[Blackboard Examples](../examples/index.md#advanced-features)** - Complete multi-agent and blackboard systems
585
+ - **[API Reference](../api/blackboard.md)** - Complete blackboard API
586
+
587
+ ---
588
+
589
+ *The blackboard pattern enables emergent intelligence through agent collaboration. Each agent contributes expertise to solve problems no single agent could solve alone.*