cloudllm 0.6.1

A batteries-included Rust toolkit for building intelligent agents with LLM integration, multi-protocol tool support, and multi-agent orchestration.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
# CloudLLM Memory Tool Guide

The Memory tool is a persistent, TTL-aware key-value store designed for agent state management. It enables agents to maintain context across sessions, create recovery checkpoints, and coordinate shared state in multi-agent scenarios.

## Overview

The Memory tool provides:
- **Persistent Storage**: Key-value pairs survive across LLM calls
- **TTL-Based Expiration**: Automatic cleanup of old data
- **Metadata Tracking**: Know when data was stored and when it expires
- **Token Efficiency**: Minimal overhead in LLM prompts
- **Easy Integration**: Works with single agents or councils

## Core Concepts

### 1. Single-Agent Memory Usage

An agent can use Memory to:
- Store task metadata and progress
- Create snapshots at milestones
- Save recovery instructions for session restart
- Track state of multi-step processes

### 2. Multi-Agent Shared Memory

Multiple agents in a Council can share Memory to:
- Coordinate decisions across a team
- Build on each other's analysis
- Maintain a shared record of conclusions
- Track discussion state for recovery

### 3. TTL (Time-To-Live)

Each memory entry can have an expiration time:
- Entries without TTL persist indefinitely
- Entries with TTL are automatically deleted when expired
- Default cleanup interval: 1 second

## Setup

### Basic Usage

```rust
use cloudllm::tools::Memory;
use cloudllm::tool_adapters::MemoryToolAdapter;
use cloudllm::tool_protocol::ToolRegistry;
use std::sync::Arc;

// Create memory instance
let memory = Arc::new(Memory::new());

// Create adapter for tool protocol
let adapter = Arc::new(MemoryToolAdapter::new(memory));

// Create tool registry
let registry = Arc::new(ToolRegistry::new(adapter));
```

### With an Agent

```rust
use cloudllm::Agent;

let agent = Agent::new("analyzer", "Data Analyzer", client)
    .with_tools(registry);
```

### With a Council

```rust
use cloudllm::council::Council;

let mut council = Council::new("council", "Analysis Council")
    .with_mode(CouncilMode::RoundRobin);

// Create shared memory
let shared_memory = Arc::new(Memory::new());
let shared_adapter = Arc::new(MemoryToolAdapter::new(shared_memory));
let shared_registry = Arc::new(ToolRegistry::new(shared_adapter));

// All agents get the same registry
let agent1 = Agent::new("a1", "Analyst 1", client1).with_tools(shared_registry.clone());
let agent2 = Agent::new("a2", "Analyst 2", client2).with_tools(shared_registry.clone());

council.add_agent(agent1)?;
council.add_agent(agent2)?;
```

## Protocol Reference

The Memory tool uses a simple, token-efficient protocol. Agents communicate via tool calls:

```json
{
  "tool_call": {
    "name": "memory",
    "parameters": {
      "command": "P doc_name Important_Report 3600"
    }
  }
}
```

### Commands

#### Put (P): Store Data
Store a key-value pair with optional TTL.

```
P <key> <value> [ttl_seconds]
```

**Examples:**
```
P doc_name My_Document            # No expiration
P milestone Step_1_Complete 3600  # Expires in 1 hour
P counter 42 60                   # Expires in 60 seconds
```

#### Get (G): Retrieve Data
Retrieve a value with optional metadata.

```
G <key> [META]
```

**Examples:**
```
G doc_name        # Get value only
G milestone META  # Get value with creation time and TTL info
```

**Response:**
```json
{
  "value": "Important_Report"
}
```

Or with metadata:
```json
{
  "value": "Step_1_Complete",
  "added_utc": "2024-11-25T14:30:00Z",
  "expires_in": 3600
}
```

#### List (L): List All Keys
List all stored keys with optional metadata.

```
L [META]
```

**Examples:**
```
L      # List keys only
L META # List with metadata
```

**Response:**
```json
{
  "keys": ["doc_name", "milestone", "checkpoint"]
}
```

#### Delete (D): Remove Data
Remove a specific key from memory.

```
D <key>
```

**Example:**
```
D old_checkpoint
```

#### Clear (C): Clear All Data
Remove all stored entries.

```
C
```

#### Total Bytes (T): Check Memory Usage
Get total memory consumption.

```
T <scope>
```

Scopes:
- `A` (all): Total bytes
- `K` (keys): Bytes used by keys
- `V` (values): Bytes used by values

**Examples:**
```
T A  # Total usage
T K  # Keys size
T V  # Values size
```

**Response:**
```json
{
  "total_bytes": 512
}
```

#### SPEC: Get Protocol Specification
Request the protocol specification (useful for LLM learning).

```
SPEC
```

## System Prompt Examples

### Single Agent with Memory

```
You are a document summarization assistant.

You have access to a memory system for tracking your progress.
Use it to:
1. Store document metadata when you start
2. Create snapshots after each major section
3. Save recovery checkpoints for continuation

Memory Protocol:
- Store: {"tool_call": {"name": "memory", "parameters": {"command": "P key value ttl"}}}
- Retrieve: {"tool_call": {"name": "memory", "parameters": {"command": "G key META"}}}
- List: {"tool_call": {"name": "memory", "parameters": {"command": "L META"}}}

Example workflow:
1. Start: P doc_name TechReport_50pages 7200
2. Progress: P current_section Section_3_of_10 7200
3. Checkpoint: P recovery_point Resume_at_section_4 7200
4. Check progress: G current_section META
```

### Council with Shared Memory

```
You are part of a strategic decision council.

All council members share a memory system. Use it to:
1. Record your analysis and findings
2. Review other members' contributions
3. Build consensus decisions

Memory is shared across all agents. One agent's storage is visible to all.

Example:
- Analyst stores: P analysis_findings Data_shows_trend_up 3600
- Strategist reads: G analysis_findings META
- Implementer records: P decision Proceed_with_plan 3600
```

## Usage Examples

### Example 1: Document Processing with Snapshots

```rust
// Agent stores document metadata
registry.execute_tool("memory",
    serde_json::json!({
        "command": "P doc_name TechArticle_25pages 7200"
    })).await?;

// Agent updates progress
registry.execute_tool("memory",
    serde_json::json!({
        "command": "P current_section Pages_1_to_5_summarized 7200"
    })).await?;

// Agent checks current status
let result = registry.execute_tool("memory",
    serde_json::json!({
        "command": "G current_section"
    })).await?;
println!("Progress: {}", result.output["value"]);

// Agent saves recovery point
registry.execute_tool("memory",
    serde_json::json!({
        "command": "P recovery_point Resume_at_page_6 7200"
    })).await?;
```

### Example 2: Council Decision Tracking

```rust
// All agents share this memory
let shared_memory = Arc::new(Memory::new());
let shared_adapter = Arc::new(MemoryToolAdapter::new(shared_memory));
let shared_registry = Arc::new(ToolRegistry::new(shared_adapter));

// Analyst stores findings
shared_registry.execute_tool("memory",
    serde_json::json!({
        "command": "P analyst_findings Option_A_has_best_ROI 3600"
    })).await?;

// Strategist reviews and adds perspective
let findings = shared_registry.execute_tool("memory",
    serde_json::json!({
        "command": "G analyst_findings"
    })).await?;

shared_registry.execute_tool("memory",
    serde_json::json!({
        "command": "P strategy_assessment Aligns_with_5year_plan 3600"
    })).await?;

// Implementer makes decision
let strategy = shared_registry.execute_tool("memory",
    serde_json::json!({
        "command": "G strategy_assessment"
    })).await?;

shared_registry.execute_tool("memory",
    serde_json::json!({
        "command": "P final_decision CONSENSUS_on_Option_A 7200"
    })).await?;

// Review all stored decisions
let all = shared_registry.execute_tool("memory",
    serde_json::json!({
        "command": "L META"
    })).await?;
println!("Decision record: {}", serde_json::to_string_pretty(&all.output)?);
```

### Example 3: TTL-Based Cleanup

```rust
// Store temporary checkpoint that expires in 60 seconds
registry.execute_tool("memory",
    serde_json::json!({
        "command": "P temp_state Processing 60"
    })).await?;

// Store permanent record that never expires
registry.execute_tool("memory",
    serde_json::json!({
        "command": "P final_result Completed"
    })).await?;

// After 61 seconds, temp_state is automatically deleted
tokio::time::sleep(Duration::from_secs(61)).await;

let keys = registry.list_tools().await?;
// final_result still exists, temp_state is gone
```

## Best Practices

### 1. Naming Conventions
Use descriptive, understandable names for keys:
```
✓ P current_milestone Section_2_Complete
✓ P recovery_checkpoint Resume_at_section_3
✗ P m2  # Too vague
✗ P x 42
```

### 2. TTL Strategy
- **Short TTL (60-300s)**: Temporary state during processing
- **Medium TTL (600-3600s)**: Progress checkpoints
- **No TTL**: Important decisions and final results

### 3. Key Organization
Use prefixes to organize related data:
```
P task_description Summarize_report
P task_status InProgress
P task_section Current_page_5
P task_recovery Resume_page_6

G task_description  # Easy to retrieve related items
L                   # All task_ keys visible together
```

### 4. Memory Efficiency
Keep values concise to minimize token usage:
```
✓ P status Done              # 4 tokens
✗ P status Task is complete  # 6 tokens
```

### 5. Coordination in Teams
Use consistent naming for shared memory:
```
// All agents know to look for these keys
P analyst_findings ...
P strategist_perspective ...
P implementer_assessment ...
P team_decision ...
```

## Performance Considerations

- **Storage**: No practical limit (system RAM dependent)
- **Lookup**: O(1) for Get, O(n) for List
- **Expiration**: Checked on each Get/List, background cleanup every 1 second
- **Token Cost**: Minimal - simple key-value operations

## Common Patterns

### Pattern 1: Resumable Tasks
```rust
// Start
P task_id unique_123 7200
P progress Step_1 7200

// Mid-session check recovery
if interrupted {
    let progress = G progress;
    // Resume from progress
}
```

### Pattern 2: Voting/Consensus
```rust
// Agent 1 votes
P vote_agent1 option_A 3600

// Agent 2 votes
P vote_agent2 option_A 3600

// Agent 3 tallies
L  # See all votes
// Majority is option_A
P consensus option_A 3600
```

### Pattern 3: Hierarchical Decisions
```rust
// Workers analyze
P worker1_analysis Finding_X 1800
P worker2_analysis Finding_Y 1800

// Supervisor aggregates
L META
P supervisor_summary Both_X_and_Y_important 3600

// Executive decides
G supervisor_summary
P executive_decision Proceed_with_both 7200
```

## Troubleshooting

### Data Not Found
- Check key spelling and case sensitivity
- Verify TTL hasn't expired: `G key META`
- List all keys: `L META`

### Session Recovery
- Save recovery checkpoint before processing: `P recovery_point <state>`
- On restart, retrieve: `G recovery_point`
- Resume from saved point

### Memory Growing Too Large
- Review TTLs - add expiration for temporary data
- Use `T A` to check total usage
- Clear old entries: `D old_key` or `C` to clear all

## Full Working Examples

See the complete examples in the `examples/` directory:

1. **`memory_session_with_snapshots.rs`**: Single agent using memory for progress tracking
2. **`council_with_memory.rs`**: Multiple agents coordinating via shared memory

Run examples:
```bash
cargo run --example memory_session_with_snapshots
cargo run --example council_with_memory
```

## API Reference

### Memory Struct

```rust
impl Memory {
    pub fn new() -> Self
    pub fn put(&self, key: String, value: String, ttl: Option<u64>)
    pub fn get(&self, key: &str, include_metadata: bool) -> Option<(String, Option<MemoryMetadata>)>
    pub fn delete(&self, key: &str) -> bool
    pub fn list_keys(&self) -> Vec<String>
    pub fn clear(&self)
    pub fn get_total_bytes_stored(&self) -> (usize, usize, usize)
    pub fn get_protocol_spec() -> String
}
```

### MemoryToolAdapter Struct

```rust
impl MemoryToolAdapter {
    pub fn new(memory: Arc<Memory>) -> Self
    fn process_memory_command(&self, command: &str) -> ToolResult
}

impl ToolProtocol for MemoryToolAdapter {
    async fn execute(
        &self,
        tool_name: &str,
        parameters: serde_json::Value,
    ) -> Result<ToolResult, Box<dyn Error + Send + Sync>>

    async fn list_tools(&self) -> Result<Vec<ToolMetadata>, Box<dyn Error + Send + Sync>>
    async fn get_tool_metadata(&self, tool_name: &str) -> Result<ToolMetadata, Box<dyn Error + Send + Sync>>
    fn protocol_name(&self) -> &str
}
```

### MemoryMetadata Struct

```rust
pub struct MemoryMetadata {
    pub added_utc: DateTime<Utc>,
    pub expires_in: Option<u64>,
}
```

## Integration with Other CloudLLM Features

The Memory tool works seamlessly with:

- **Agents**: Each agent can have a memory registry
- **Councils**: All council members can share memory
- **Sessions**: Memory persists across LLMSession calls
- **Tool Registry**: Memory is registered like any other tool
- **Custom Protocols**: Can be adapted for other communication protocols