Migrating from 0.9 → 0.10
Read this if you are upgrading an app from Loomflow 0.9.x. The 0.10 release is additive: no public API was renamed and no constructor argument was removed. Three changes may still need attention.
1. Postgres memory_blocks schema migrated
The empty-string anonymous bucket is replaced with a reserved sentinel
(__jeeves_anon_user__). The framework’s init_schema() runs the
rewriting UPDATE automatically; if you bypass it and manage
migrations yourself, run:
UPDATE memory_blocks SET user_id = '__jeeves_anon_user__'
WHERE user_id = '';
ALTER TABLE memory_blocks ALTER COLUMN user_id
SET DEFAULT '__jeeves_anon_user__';Passing the sentinel as a real user_id now raises ValueError, so
no caller can impersonate the anonymous bucket.
2. LoomDeprecationWarning for legacy protocol shapes
Custom Permissions, HookHost and AuditLog implementations whose
methods don’t accept a user_id= keyword emit
LoomDeprecationWarning. The framework still calls the old shape, so
nothing breaks today, but the fallback will be removed in 1.0. To
silence the warning, add the keyword:
from collections.abc import Mapping
from typing import Any
from loomflow.core.types import PermissionDecision, ToolCall
class MyPermissions:
async def check(
self,
call: ToolCall,
*,
context: Mapping[str, Any],
user_id: str | None = None, # new in 0.10
) -> PermissionDecision:
return PermissionDecision.allow_()3. Bounded in-process state by default
Per-user state in StandardBudget and InMemoryMemory is now bounded
by default (100k users, 24-hour idle TTL, LRU eviction). A workload
that legitimately keeps more than 100k active users in one process
needs to raise the cap or opt out:
from loomflow import InMemoryMemory
from loomflow.governance.budget import BudgetConfig, StandardBudget
StandardBudget(BudgetConfig(), max_users=None, user_idle_ttl_seconds=None)
InMemoryMemory(max_users=None, user_idle_ttl_seconds=None)See Bounded in-process state for what eviction does.
That’s the whole upgrade.