---
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