Context Snapshot Hooks
Capture exact LLM call boundary state for debugging and verification
from praisonaiagents import Agent
agent = Agent(name="snapshot-agent", instructions="Save and restore context snapshots.")
agent.start("Create a context snapshot before processing this long document.")Snapshot hooks capture the exact state of messages and tools at the LLM call boundary, enabling verification that snapshots match actual payloads.
Quick Start
- Capture at the LLM boundary
python from praisonaiagents import ContextManager manager = ContextManager(model="gpt-4o-mini") hook_data = manager.capture_llm_boundary(messages, tools) print(f"Message hash: {hook_data.message_hash}") - Register a snapshot callback
python def on_llm_call(hook_data): print(f"Sending {len(hook_data.messages)} messages") manager.register_snapshot_callback(on_llm_call)
Architecture
The user registers snapshot hooks; each context change triggers a callback for auditing or custom pipelines.
classDef agent fill:#8B0000,color:#fff classDef tool fill:#189AB4,color:#fff
SnapshotHookData
@dataclass
class SnapshotHookData:
timestamp: str # ISO timestamp
messages: List[Dict] # Exact messages
tools: List[Dict] # Exact tool schemas
message_hash: str # SHA256 hash (16 chars)
tools_hash: str # SHA256 hash (16 chars)
ledger: ContextLedger # Token accounting
budget: BudgetAllocation # Budget infoSnapshot Callbacks
Register callbacks to be notified at every LLM boundary:
def on_llm_call(hook_data):
"""Called before each LLM request."""
print(f"Sending {len(hook_data.messages)} messages")
print(f"Hash: {hook_data.message_hash}")
# Log for debugging
with open("llm_calls.log", "a") as f:
f.write(f"{hook_data.timestamp}: {hook_data.message_hash}\n")
manager.register_snapshot_callback(on_llm_call)Hash Verification
Verify snapshot matches actual payload:
import hashlib
import json
# Capture snapshot
hook_data = manager.capture_llm_boundary(messages, tools)
# Later, verify payload matches
def verify_payload(actual_messages, expected_hash):
actual_json = json.dumps(actual_messages, sort_keys=True, default=str)
actual_hash = hashlib.sha256(actual_json.encode()).hexdigest()[:16]
return actual_hash == expected_hash
# Before sending to LLM
assert verify_payload(messages, hook_data.message_hash)Snapshot Timing
Configure when snapshots are taken:
from praisonaiagents import ManagerConfig
config = ManagerConfig(
snapshot_timing="both", # pre_optimization, post_optimization, or both
)| Timing | Description |
|---|---|
pre_optimization | Before any optimization |
post_optimization | After optimization (default) |
both | Capture both states |
Drift Detection
Detect if context drifted between snapshot and LLM call:
# Take snapshot
hook1 = manager.capture_llm_boundary(messages, tools)
# ... some operations ...
# Take another snapshot
hook2 = manager.capture_llm_boundary(messages, tools)
# Check for drift
if hook1.message_hash != hook2.message_hash:
print("Warning: Context changed between snapshots")Integration with Monitor
Snapshots are automatically included in monitor output:
config = ManagerConfig(
monitor_enabled=True,
monitor_format="json",
)
manager = ContextManager(config=config)
# Snapshots include hash metadata
# {
# "timestamp": "...",
# "message_hash": "abc123...",
# "tools_hash": "def456...",
# ...
# }CLI Usage
# Enable monitoring to capture snapshots
praisonai chat --context-monitor
# Snapshots written to context.txt
# Include message/tool hashes for verificationUse Cases
- Debugging – Verify exact state sent to LLM
- Auditing – Log all LLM calls with hashes
- Testing – Assert snapshot == expected payload
- Replay – Reproduce exact LLM calls
Best Practices
Hash payloads for regression tests
Compare snapshot hashes in CI to detect unintended context changes between releases.
Use hooks for audit trails
Log hashes and token counts when compliance requires proof of what was sent to the model.
Keep hooks lightweight
Avoid heavy I/O inside snapshot hooks — queue writes asynchronously when possible.
Include tool results in snapshots
Verify tool output formatting matches what the model receives, not just user messages.