@cronicorn/mcp-server 1.4.5 → 1.5.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.
@@ -0,0 +1,457 @@
1
+ ---
2
+ id: coordinating-endpoints
3
+ title: Coordinating Multiple Endpoints
4
+ description: Orchestration patterns and multi-endpoint examples
5
+ tags: [assistant, technical, orchestration]
6
+ sidebar_position: 4
7
+ mcp:
8
+ uri: file:///docs/technical/coordinating-multiple-endpoints.md
9
+ mimeType: text/markdown
10
+ priority: 0.80
11
+ lastModified: 2025-11-02T00:00:00Z
12
+ ---
13
+
14
+ # Coordinating Multiple Endpoints
15
+
16
+ This document shows practical patterns for orchestrating workflows across multiple endpoints. Instead of abstract concepts, you'll find concrete examples you can copy and adapt.
17
+
18
+ ## Core Concept: Coordination via Response Bodies
19
+
20
+ Cronicorn doesn't have built-in workflow orchestration or explicit dependencies. Instead, endpoints coordinate by:
21
+
22
+ 1. Writing signals to their response bodies
23
+ 2. Other endpoints reading those signals via `get_sibling_latest_responses`
24
+ 3. AI acting on the signals (pause, run immediately, adjust intervals)
25
+
26
+ This approach is flexible—you define the coordination protocol in your response data.
27
+
28
+ ## Pattern 1: Flash Sale Load Management
29
+
30
+ **Scenario**: E-commerce site with flash sale. Need to prioritize critical endpoints and pause low-priority work during traffic spikes.
31
+
32
+ ### Endpoints
33
+
34
+ **Job**: "Flash Sale Management"
35
+
36
+ **Endpoint 1: Traffic Monitor** (1-minute interval)
37
+ - Checks current traffic load
38
+ - Returns: `{ "visitors_per_min": 5000, "load_status": "high", "flash_sale_active": true }`
39
+
40
+ **Endpoint 2: Order Processor** (30-second interval)
41
+ - Critical: processes orders
42
+ - Priority: Must keep running
43
+
44
+ **Endpoint 3: Inventory Sync** (5-minute interval)
45
+ - Normal priority: syncs inventory to warehouse
46
+ - Can pause during spikes
47
+
48
+ **Endpoint 4: Analytics Updater** (10-minute interval)
49
+ - Low priority: updates dashboards
50
+ - Should pause during spikes
51
+
52
+ ### Response Body Structure
53
+
54
+ **Traffic Monitor**:
55
+ ```json
56
+ {
57
+ "visitors_per_min": 5000,
58
+ "load_status": "high",
59
+ "flash_sale_active": true,
60
+ "recommendations": {
61
+ "pause_low_priority": true,
62
+ "pause_until": "2025-11-02T15:00:00Z"
63
+ }
64
+ }
65
+ ```
66
+
67
+ **Analytics Updater**:
68
+ ```json
69
+ {
70
+ "last_update_at": "2025-11-02T14:30:00Z",
71
+ "records_processed": 1500,
72
+ "status": "active"
73
+ }
74
+ ```
75
+
76
+ ### AI Coordination Logic
77
+
78
+ When AI analyzes **Analytics Updater**:
79
+
80
+ 1. Calls `get_sibling_latest_responses()`
81
+ 2. Finds Traffic Monitor response: `{ "load_status": "high", "recommendations": { "pause_low_priority": true } }`
82
+ 3. Checks Analytics Updater's priority (low)
83
+ 4. Calls `pause_until("2025-11-02T15:00:00Z", reason="Flash sale traffic spike - pausing low-priority work")`
84
+
85
+ When AI analyzes **Order Processor**:
86
+
87
+ 1. Calls `get_sibling_latest_responses()`
88
+ 2. Finds Traffic Monitor response: `{ "load_status": "high" }`
89
+ 3. Checks Order Processor's priority (critical)
90
+ 4. Takes no action (critical endpoints keep running)
91
+
92
+ When load drops (Traffic Monitor returns `"load_status": "normal"`):
93
+
94
+ 1. AI analyzes Analytics Updater
95
+ 2. Sees normal load status
96
+ 3. Calls `pause_until(null, reason="Load normalized - resuming")`
97
+
98
+ ### Key Points
99
+
100
+ - Traffic Monitor acts as coordinator (writes signals)
101
+ - Other endpoints react to signals (via AI reading sibling responses)
102
+ - Priority is encoded in endpoint names/descriptions, not the system
103
+ - Coordination is eventual (within 5 minutes of AI analysis cycle)
104
+
105
+ ## Pattern 2: ETL Pipeline with Dependencies
106
+
107
+ **Scenario**: Extract-Transform-Load pipeline where each stage depends on the previous stage completing.
108
+
109
+ ### Endpoints
110
+
111
+ **Job**: "Customer Data Pipeline"
112
+
113
+ **Endpoint 1: Extract Customer Data** (cron: `0 2 * * *` - 2 AM daily)
114
+ - Pulls data from external API
115
+ - Returns: `{ "extracted_count": 5000, "batch_id": "2025-11-02", "completed_at": "2025-11-02T02:15:00Z" }`
116
+
117
+ **Endpoint 2: Transform Customer Data** (1-minute interval, waits for extract)
118
+ - Transforms raw data to normalized format
119
+ - Returns: `{ "transformed_count": 5000, "batch_id": "2025-11-02", "ready_for_load": true }`
120
+
121
+ **Endpoint 3: Load to Database** (1-minute interval, waits for transform)
122
+ - Loads normalized data to production database
123
+ - Returns: `{ "loaded_count": 5000, "batch_id": "2025-11-02", "pipeline_complete": true }`
124
+
125
+ ### Response Body Structure
126
+
127
+ **Extract**:
128
+ ```json
129
+ {
130
+ "stage": "extract",
131
+ "batch_id": "2025-11-02",
132
+ "extracted_count": 5000,
133
+ "completed_at": "2025-11-02T02:15:00Z",
134
+ "ready_for_transform": true,
135
+ "status": "success"
136
+ }
137
+ ```
138
+
139
+ **Transform** (before ready):
140
+ ```json
141
+ {
142
+ "stage": "transform",
143
+ "batch_id": "2025-11-01",
144
+ "status": "waiting",
145
+ "waiting_for": "extract_2025-11-02"
146
+ }
147
+ ```
148
+
149
+ **Transform** (after ready):
150
+ ```json
151
+ {
152
+ "stage": "transform",
153
+ "batch_id": "2025-11-02",
154
+ "transformed_count": 5000,
155
+ "completed_at": "2025-11-02T02:30:00Z",
156
+ "ready_for_load": true,
157
+ "status": "success"
158
+ }
159
+ ```
160
+
161
+ ### AI Coordination Logic
162
+
163
+ When AI analyzes **Transform**:
164
+
165
+ 1. Calls `get_sibling_latest_responses()`
166
+ 2. Finds Extract response: `{ "batch_id": "2025-11-02", "ready_for_transform": true }`
167
+ 3. Checks Transform's last response: `{ "batch_id": "2025-11-01", "status": "waiting" }`
168
+ 4. Sees new batch available (batch IDs don't match)
169
+ 5. Calls `propose_next_time(now, reason="New batch 2025-11-02 ready for transform")`
170
+
171
+ When AI analyzes **Load**:
172
+
173
+ 1. Calls `get_sibling_latest_responses()`
174
+ 2. Finds Transform response: `{ "batch_id": "2025-11-02", "ready_for_load": true }`
175
+ 3. Checks Load's last response: `{ "batch_id": "2025-11-01" }`
176
+ 4. Sees new batch available
177
+ 5. Calls `propose_next_time(now, reason="Transformed batch 2025-11-02 ready to load")`
178
+
179
+ ### Key Points
180
+
181
+ - Batch IDs enable idempotency (endpoints know what they've processed)
182
+ - `ready_for_*` flags signal downstream readiness
183
+ - Transform and Load run frequently (1-minute interval) but only process when data is ready
184
+ - Coordination happens within minutes of upstream completion
185
+
186
+ ## Pattern 3: Cooldown-Based Actions
187
+
188
+ **Scenario**: Cache warming endpoint that should run immediately when cache hit rate drops, but not more than once per hour.
189
+
190
+ ### Endpoint
191
+
192
+ **Job**: "Cache Management"
193
+
194
+ **Endpoint: Cache Monitor** (5-minute interval)
195
+ - Monitors cache hit rate
196
+ - Warms cache if hit rate drops below threshold
197
+ - Includes cooldown tracking to prevent duplicate warming
198
+
199
+ ### Response Body Structure
200
+
201
+ **Normal operation**:
202
+ ```json
203
+ {
204
+ "cache_hit_rate_pct": 95.5,
205
+ "cache_size_mb": 512,
206
+ "status": "healthy",
207
+ "last_warm_at": "2025-11-02T12:00:00Z"
208
+ }
209
+ ```
210
+
211
+ **Low hit rate detected**:
212
+ ```json
213
+ {
214
+ "cache_hit_rate_pct": 65.2,
215
+ "cache_size_mb": 512,
216
+ "status": "degraded",
217
+ "last_warm_at": "2025-11-02T12:00:00Z",
218
+ "warm_cache_needed": true,
219
+ "cooldown_minutes": 60
220
+ }
221
+ ```
222
+
223
+ **After warming**:
224
+ ```json
225
+ {
226
+ "cache_hit_rate_pct": 94.8,
227
+ "cache_size_mb": 512,
228
+ "status": "healthy",
229
+ "last_warm_at": "2025-11-02T13:15:00Z",
230
+ "cache_warmed": true
231
+ }
232
+ ```
233
+
234
+ ### AI Coordination Logic
235
+
236
+ When AI analyzes Cache Monitor:
237
+
238
+ 1. Calls `get_latest_response()`
239
+ 2. Sees: `{ "cache_hit_rate_pct": 65.2, "warm_cache_needed": true, "last_warm_at": "2025-11-02T12:00:00Z" }`
240
+ 3. Calls `get_response_history(limit=5)` to check recent warmings
241
+ 4. Calculates time since last warm: `now - last_warm_at = 75 minutes`
242
+ 5. Compares to cooldown: `75 min > 60 min cooldown`
243
+ 6. Calls `propose_next_time(now, reason="Cache hit rate dropped to 65%, cooldown elapsed")`
244
+
245
+ If cooldown not elapsed:
246
+
247
+ 1. AI sees `last_warm_at` was 30 minutes ago
248
+ 2. Cooldown is 60 minutes
249
+ 3. Takes no action (reasoning: "Cache warming needed but cooldown active - 30 min elapsed of 60 min required")
250
+
251
+ ### Key Points
252
+
253
+ - Cooldown prevents duplicate expensive actions
254
+ - `last_warm_at` timestamp enables cooldown calculation
255
+ - AI checks response history to verify pattern
256
+ - Endpoint's response body drives action (not external state)
257
+
258
+ ## Pattern 4: Tiered Priority System
259
+
260
+ **Scenario**: Multiple monitoring endpoints with different priorities. Under load, pause lower tiers.
261
+
262
+ ### Endpoint Naming Convention
263
+
264
+ Use names/descriptions to encode priority:
265
+
266
+ - `[CRITICAL] Payment Processor`
267
+ - `[NORMAL] Inventory Sync`
268
+ - `[LOW] Analytics Updater`
269
+
270
+ Or use description field:
271
+
272
+ ```json
273
+ {
274
+ "name": "Payment Processor",
275
+ "description": "Priority: CRITICAL. Processes customer payments."
276
+ }
277
+ ```
278
+
279
+ ### Coordination Endpoint
280
+
281
+ **System Health Monitor** (1-minute interval)
282
+ - Checks overall system load (CPU, memory, queue depths)
283
+ - Returns recommendations for priority levels to pause
284
+
285
+ **Response Body**:
286
+ ```json
287
+ {
288
+ "system_load_pct": 85,
289
+ "recommendations": {
290
+ "active_priority_levels": ["CRITICAL", "NORMAL"],
291
+ "paused_priority_levels": ["LOW"],
292
+ "reason": "System load at 85% - pausing low-priority work"
293
+ }
294
+ }
295
+ ```
296
+
297
+ ### AI Logic for Each Endpoint
298
+
299
+ When AI analyzes any endpoint:
300
+
301
+ 1. Calls `get_sibling_latest_responses()`
302
+ 2. Finds System Health Monitor response
303
+ 3. Extracts endpoint's priority from name/description
304
+ 4. Checks if priority in `paused_priority_levels`
305
+ 5. If yes: `pause_until(calculated_time, reason="System load high")`
306
+ 6. If no: No action (or resume if paused)
307
+
308
+ ### Key Points
309
+
310
+ - Single health monitor coordinates entire tier
311
+ - Priority encoded in metadata (names/descriptions)
312
+ - AI interprets recommendations and applies to individual endpoints
313
+ - Centralized policy (health monitor) with distributed execution (AI per endpoint)
314
+
315
+ ## Pattern 5: Cross-Job Coordination
316
+
317
+ **Scenario**: Endpoints in different jobs need to coordinate (e.g., upstream service health affects downstream consumers).
318
+
319
+ ### Challenge
320
+
321
+ `get_sibling_latest_responses()` only works within the same job. Cross-job coordination requires a different approach.
322
+
323
+ ### Solution: Shared State Endpoint
324
+
325
+ **Job 1**: "Upstream Service"
326
+ - **Endpoint**: Health Check (1-minute interval)
327
+ - Returns: `{ "service_status": "healthy", "last_check": "..." }`
328
+
329
+ **Job 2**: "Downstream Consumers"
330
+ - **Endpoint 1**: Data Processor
331
+ - **Endpoint 2**: Analytics Pipeline
332
+
333
+ Configure Downstream endpoints to call Upstream Service's health endpoint and include the result in their response body:
334
+
335
+ **Data Processor Response**:
336
+ ```json
337
+ {
338
+ "processed_count": 100,
339
+ "upstream_health": {
340
+ "status": "healthy",
341
+ "checked_at": "2025-11-02T14:30:00Z"
342
+ }
343
+ }
344
+ ```
345
+
346
+ When upstream goes down:
347
+ ```json
348
+ {
349
+ "processed_count": 0,
350
+ "error": "Upstream service unavailable",
351
+ "upstream_health": {
352
+ "status": "unavailable",
353
+ "checked_at": "2025-11-02T14:35:00Z"
354
+ }
355
+ }
356
+ ```
357
+
358
+ ### AI Logic
359
+
360
+ When AI analyzes Data Processor:
361
+
362
+ 1. Calls `get_latest_response()`
363
+ 2. Sees: `{ "upstream_health": { "status": "unavailable" } }`
364
+ 3. Calls `pause_until(now + 15_minutes, reason="Upstream service unavailable")`
365
+
366
+ ### Key Points
367
+
368
+ - Endpoints embed external dependency status in their response bodies
369
+ - AI reacts to dependency signals
370
+ - Works across jobs (no sibling query needed)
371
+ - Endpoint is responsible for checking upstream status
372
+
373
+ ## Common Coordination Signals
374
+
375
+ Here are standard signal patterns you can reuse:
376
+
377
+ ### Readiness Signals
378
+ ```json
379
+ {
380
+ "ready_for_processing": true,
381
+ "data_available": true,
382
+ "batch_ready": true
383
+ }
384
+ ```
385
+
386
+ ### Dependency Status
387
+ ```json
388
+ {
389
+ "dependency_status": "healthy" | "degraded" | "unavailable",
390
+ "upstream_healthy": true
391
+ }
392
+ ```
393
+
394
+ ### Action Requests
395
+ ```json
396
+ {
397
+ "warm_cache_needed": true,
398
+ "scale_up_needed": true,
399
+ "send_alert": true
400
+ }
401
+ ```
402
+
403
+ ### Cooldown Tracking
404
+ ```json
405
+ {
406
+ "last_action_at": "2025-11-02T14:30:00Z",
407
+ "cooldown_minutes": 60,
408
+ "action_type": "cache_warm" | "alert_sent" | "scaled"
409
+ }
410
+ ```
411
+
412
+ ### Load/Priority Signals
413
+ ```json
414
+ {
415
+ "load_status": "normal" | "elevated" | "high" | "critical",
416
+ "pause_priorities": ["LOW", "NORMAL"],
417
+ "active_priorities": ["CRITICAL"]
418
+ }
419
+ ```
420
+
421
+ ## Best Practices
422
+
423
+ 1. **Be explicit**: Use clear signal names (`ready_for_load` not `ready`)
424
+ 2. **Include timestamps**: Enable cooldown calculations and staleness checks
425
+ 3. **Provide context**: Add `reason` fields explaining state
426
+ 4. **Use batch IDs**: Enable idempotency in pipelines
427
+ 5. **Keep signals simple**: AI reads truncated bodies (1000 chars)
428
+ 6. **Document protocols**: Comment what signals mean in endpoint descriptions
429
+ 7. **Test coordination**: Verify AI picks up signals by checking analysis sessions
430
+
431
+ ## Debugging Coordination
432
+
433
+ When coordination isn't working:
434
+
435
+ 1. **Check sibling responses**: Does `get_sibling_latest_responses()` return expected data?
436
+ 2. **Review AI sessions**: What did AI see? What reasoning did it provide?
437
+ 3. **Verify signal format**: Are field names consistent?
438
+ 4. **Check timing**: AI analyzes every 5 minutes—coordination isn't instant
439
+ 5. **Look for errors**: Did endpoint fail to write expected signal?
440
+
441
+ ## Key Takeaways
442
+
443
+ 1. **Coordination via response bodies**: Write signals, other endpoints read them
444
+ 2. **AI interprets signals**: Uses `get_sibling_latest_responses()` and `get_latest_response()`
445
+ 3. **Eventual consistency**: Coordination happens within minutes (AI analysis cycle)
446
+ 4. **Flexible protocols**: You define what signals mean
447
+ 5. **Priority systems**: Use names/descriptions to encode metadata
448
+ 6. **Cooldowns prevent duplicates**: Track `last_action_at` in response bodies
449
+ 7. **Cross-job coordination**: Embed external status checks in responses
450
+
451
+ These patterns give you the building blocks for complex workflows. Mix and match based on your needs.
452
+
453
+ ## Next Steps
454
+
455
+ - **[Configuration and Constraints](./configuration-and-constraints.md)** - Set up endpoints for optimal coordination
456
+ - **[How AI Adaptation Works](./how-ai-adaptation-works.md)** - Understand how AI reads and acts on signals
457
+ - **[Reference](./reference.md)** - Quick lookup for tools and response body patterns