--- sidebar_position: 9 --- # Operations Monitor and manage long-running background tasks in Hindsight. import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; :::tip Prerequisites Make sure you've [installed Hindsight](./installation) and understand [how retain works](./retain). ::: ## What Are Operations? Some Hindsight tasks run asynchronously in the background: - **Batch retain** — Processing large document sets - **Entity observations** — Synthesizing entity summaries - **Graph updates** — Building connections between memories Operations provide a way to track these background tasks. ## Async Batch Retain For large content batches, use async mode to avoid timeouts: ```python # Start async batch retain operation = client.retain_batch_async( bank_id="my-bank", contents=[ {"content": doc1_text}, {"content": doc2_text}, # ... hundreds or thousands of documents ] ) print(f"Operation ID: {operation['operation_id']}") print(f"Status: {operation['status']}") # 'pending' or 'running' # Check status status = client.get_operation( bank_id="my-bank", operation_id=operation['operation_id'] ) print(f"Status: {status['status']}") # 'pending', 'running', 'completed', 'failed' print(f"Progress: {status['progress']}/{status['total']}") # Wait for completion import time while True: status = client.get_operation(bank_id="my-bank", operation_id=operation['operation_id']) if status['status'] in ['completed', 'failed']: break print(f"Progress: {status['progress']}/{status['total']}") time.sleep(5) if status['status'] == 'completed': print(f"Created {len(status['result']['memory_ids'])} memories") ``` ```javascript // Start async batch retain const operation = await client.retainBatchAsync({ bankId: 'my-bank', contents: [ { content: doc1Text }, { content: doc2Text }, // ... hundreds or thousands of documents ] }); console.log(`Operation ID: ${operation.operationId}`); console.log(`Status: ${operation.status}`); // Check status const status = await client.getOperation({ bankId: 'my-bank', operationId: operation.operationId }); console.log(`Status: ${status.status}`); console.log(`Progress: ${status.progress}/${status.total}`); // Wait for completion async function waitForOperation(bankId, operationId) { while (true) { const status = await client.getOperation({ bankId, operationId }); if (['completed', 'failed'].includes(status.status)) { return status; } console.log(`Progress: ${status.progress}/${status.total}`); await new Promise(resolve => setTimeout(resolve, 5000)); } } const finalStatus = await waitForOperation('my-bank', operation.operationId); if (finalStatus.status === 'completed') { console.log(`Created ${finalStatus.result.memoryIds.length} memories`); } ``` ```bash # Start async batch retain hindsight retain my-bank --files docs/*.md --async # Returns operation ID: op-abc123... # Check status hindsight operations get my-bank op-abc123 # Watch progress hindsight operations watch my-bank op-abc123 ``` ## List Operations View all operations for a memory bank: ```python # List all operations operations = client.list_operations(bank_id="my-bank") for op in operations: print(f"{op['operation_id']}: {op['type']} - {op['status']}") if op['status'] == 'running': print(f" Progress: {op['progress']}/{op['total']}") # Filter by status pending = client.list_operations( bank_id="my-bank", status="pending" ) running = client.list_operations( bank_id="my-bank", status="running" ) # With pagination operations = client.list_operations( bank_id="my-bank", limit=50, offset=0 ) ``` ```javascript // List all operations const operations = await client.listOperations({ bankId: 'my-bank' }); operations.forEach(op => { console.log(`${op.operationId}: ${op.type} - ${op.status}`); if (op.status === 'running') { console.log(` Progress: ${op.progress}/${op.total}`); } }); // Filter by status const pending = await client.listOperations({ bankId: 'my-bank', status: 'pending' }); ``` ```bash # List all operations hindsight operations list my-bank # Filter by status hindsight operations list my-bank --status running # Watch all running operations hindsight operations watch my-bank --all ``` ## Cancel Operations Stop a running or pending operation: ```python # Cancel operation client.cancel_operation( bank_id="my-bank", operation_id="op-abc123" ) # Cancel all pending operations operations = client.list_operations(bank_id="my-bank", status="pending") for op in operations: client.cancel_operation(bank_id="my-bank", operation_id=op['operation_id']) ``` ```javascript // Cancel operation await client.cancelOperation({ bankId: 'my-bank', operationId: 'op-abc123' }); // Cancel all pending const pending = await client.listOperations({ bankId: 'my-bank', status: 'pending' }); for (const op of pending) { await client.cancelOperation({ bankId: 'my-bank', operationId: op.operationId }); } ``` ```bash # Cancel operation hindsight operations cancel my-bank op-abc123 # Cancel all pending hindsight operations cancel my-bank --all-pending ``` ## Operation States | State | Description | |-------|-------------| | **pending** | Queued, waiting to start | | **running** | Currently processing | | **completed** | Successfully finished | | **failed** | Encountered an error | | **cancelled** | Stopped by user | ## Operation Types | Type | Description | |------|-------------| | **batch_retain** | Async batch content ingestion | | **regenerate_observations** | Entity observation synthesis | | **graph_update** | Link and connection building | ## Operation Response Format ```json { "operation_id": "op-abc123", "bank_id": "my-bank", "type": "batch_retain", "status": "running", "progress": 450, "total": 1000, "created_at": "2024-03-15T10:00:00Z", "started_at": "2024-03-15T10:00:05Z", "completed_at": null, "error": null, "result": null } ``` ## Monitoring Strategies ### Polling ```python import time def wait_for_operation(client, bank_id, operation_id, poll_interval=5): while True: status = client.get_operation(bank_id=bank_id, operation_id=operation_id) if status['status'] == 'completed': return status['result'] elif status['status'] == 'failed': raise Exception(f"Operation failed: {status['error']}") elif status['status'] == 'cancelled': raise Exception("Operation was cancelled") print(f"Progress: {status['progress']}/{status['total']}") time.sleep(poll_interval) # Use it result = wait_for_operation(client, "my-bank", op_id) print(f"Created {len(result['memory_ids'])} memories") ``` ### Webhooks (Coming Soon) ```python # Configure webhook for operation completion client.configure_webhook( bank_id="my-bank", url="https://myapp.com/webhooks/hindsight", events=["operation.completed", "operation.failed"] ) ``` ## Performance Tips **Use async for large batches:** - Sync: < 100 items or < 100KB - Async: > 100 items or > 100KB **Monitor progress:** - Check `progress` / `total` fields - Poll every 5-10 seconds **Handle failures:** - Check `error` field for details - Retry with exponential backoff - Break large batches into smaller chunks ## Next Steps - [**Documents**](./documents) — Track document sources - [**Entities**](./entities) — Monitor entity tracking - [**Memory Banks**](./memory-banks) — Configure bank settings