Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
Back to tool/Back to issues
#2634·agentscope

Storage layer: adding a persisted feature costs the same boilerplate in three files

Author: DavdGaoCreated Sep 15, 2026Updated Sep 16, 2026

What the storage layer costs per feature

StorageBase now declares 61 abstract methods across 1445 lines, and every one of them is implemented twice — AsyncSQLAlchemyStorage (2210 lines) and RedisStorage (2519 lines). Adding a feature that persists anything means writing the same set of methods in three files:

Entity Methods on StorageBase
credential / mcp / skill / agent / schedule / channel / team / knowledge base / knowledge document 3–4 each
session 6
sop + sop run 9

For the SOP work that was ~300 lines across the three files, of which roughly 30 were specific to SOP — the cascade on delete, and a phase filter. The rest is the same four operations named differently.

The similarity is measurable, not impressionistic: 53 of the SQL backend's method bodies are thin wrappers over the same three generic helpers (_write_row, _from_record, _to_record), driven by each row class' _indexed_fields / _index_paths. On the Redis side the equivalent is 70 hand-written key-format and index-set calls, the same shape repeated per entity.

Where it is felt

Both backends must be kept in step by hand. Nothing enforces that RedisStorage and AsyncSQLAlchemyStorage agree on a new method's semantics. Differences that are legitimate (Redis cannot index a value derived from a JSON payload, so it filters after reading) sit next to differences that would be bugs, and only the test suite tells them apart.

Cross-entity deletes are where the logic actually lives, and they are buried. There are 5 cascade implementations (_delete_session_impl, _delete_schedule_impl, _delete_agent_impl, _delete_team_impl, _delete_sop_run_impl) referenced from 23 places. These carry real rules — a team deletes the members it created but not the ones it borrowed; deleting an agent takes its sessions and schedules. They are hard to find among the boilerplate, and a missing one is silent: the SOP work shipped a run delete that left its sessions behind, which was caught by review rather than by anything structural.

Reviewing a storage change means reading three files to learn one fact. The intent is in _base.py, and whether it holds is in two other files 2000+ lines each.

The router surface grows with it. Each persisted entity brings its own CRUD router and schema module; _router/ is now 17 modules. A deployment that uses none of a given feature still carries its endpoints, its tables, and its share of StorageBase.

Why this is worth raising now rather than later

The growth is linear in features and shows no sign of levelling off — channels, knowledge bases, schedules, teams and SOP all arrived the same way, and each one made the next one's boilerplate slightly more tempting to copy than to question. The parts that differ between entities are small and interesting; the parts that repeat are large and mechanical, and they are what a reviewer has to read past to reach the interesting ones.

Generated with Claude Code

https://claude.ai/code/session_017j3JnCeguJKTXAj8FEqBdr

Source: agentscope-ai/agentscope

View original on GitHubView discussion on GitHub