Storage¶
The seller agent uses a pluggable storage backend for all persistent state. The StorageBackend abstract base class defines the interface, and concrete implementations handle the actual data storage.
StorageBackend Interface¶
Defined in src/ad_seller/storage/base.py.
Core Methods¶
All methods are async:
| Method | Signature | Description |
|---|---|---|
connect |
() -> None |
Establish connection to storage backend |
disconnect |
() -> None |
Close connection |
get |
(key: str) -> Optional[Any] |
Retrieve a value by key |
set |
(key: str, value: Any, ttl: Optional[int] = None) -> None |
Store a value with optional TTL in seconds |
delete |
(key: str) -> bool |
Delete a key, returns True if key existed |
exists |
(key: str) -> bool |
Check if key exists |
keys |
(pattern: str = "*") -> list[str] |
List keys matching a glob pattern |
Higher-Level Operations¶
The base class provides convenience methods built on the core interface. These handle key prefixing automatically:
| Method | Key Pattern | Description |
|---|---|---|
get_product / set_product |
product:{id} |
Product catalog entries |
get_proposal / set_proposal |
proposal:{id} |
Buyer proposals |
get_deal / set_deal / list_deals |
deal:{id} |
Executed deals |
get_session / set_session / list_sessions |
session:{id} |
Buyer conversation sessions |
get_quote / set_quote / list_quotes |
quote:{id} |
Price quotes (default 24h TTL) |
get_order / set_order / list_orders |
order:{id} |
Order state machines |
get_change_request / set_change_request / list_change_requests |
change_request:{id} |
Post-deal modifications |
get_negotiation / set_negotiation |
negotiation:{proposal_id} |
Negotiation histories |
get_agent / set_agent / list_agents |
agent:{id} |
Registered buyer agents |
get_package / set_package / list_packages |
package:{id} |
Media kit packages |
get_media_kit / set_media_kit |
media_kit:{org_id} |
Seller organization media kit metadata |
Key Prefix Convention¶
All keys follow the pattern {entity_type}:{identifier}. This enables efficient listing via the keys() method with glob patterns.
| Prefix | Entity | Example Key |
|---|---|---|
product: |
Product catalog | product:display |
proposal: |
Buyer proposal | proposal:prop-a1b2c3d4 |
deal: |
Executed deal | deal:DEMO-A1B2C3D4E5F6 |
session: |
Conversation session | session:550e8400-e29b-... |
quote: |
Price quote | quote:qt-a1b2c3d4e5f6 |
order: |
Order state machine | order:ORD-A1B2C3D4E5F6 |
change_request: |
Change request | change_request:CR-A1B2C3D4E5F6 |
negotiation: |
Negotiation history | negotiation:prop-a1b2c3d4 |
agent: |
Registered agent | agent:550e8400-e29b-... |
media_kit: |
Media kit metadata | media_kit:default |
package: |
Curated/dynamic package | package:pkg-a1b2c3d4 |
Index keys use a secondary prefix pattern: session_index:buyer:{pricing_key} and agent_url_index:{url}.
Available Backends¶
SQLite (Default)¶
File-based storage using aiosqlite. Suitable for development and single-instance deployments.
Redis¶
Network-based storage using aioredis. Supports native TTL, key pattern matching, and multi-instance deployments. Recommended for production.
Implementing a Custom Backend¶
- Subclass
StorageBackendfromsrc/ad_seller/storage/base.py - Implement the 7 core abstract methods:
connect,disconnect,get,set,delete,exists,keys - All higher-level methods (get_product, set_order, etc.) are provided by the base class and do not need to be overridden unless you want to optimize them
Example skeleton:
from ad_seller.storage.base import StorageBackend
from typing import Any, Optional
class MyCustomBackend(StorageBackend):
async def connect(self) -> None:
# Initialize your connection
pass
async def disconnect(self) -> None:
# Clean up
pass
async def get(self, key: str) -> Optional[Any]:
# Return stored value or None
pass
async def set(self, key: str, value: Any, ttl: Optional[int] = None) -> None:
# Store value, respect TTL if provided (seconds)
pass
async def delete(self, key: str) -> bool:
# Delete key, return True if it existed
pass
async def exists(self, key: str) -> bool:
# Check existence
pass
async def keys(self, pattern: str = "*") -> list[str]:
# Return keys matching glob pattern
pass
Register your backend in the storage factory to make it available to the application.