Foreword¶
Every time an Agent reads a tool result, it is actually a “readback”: the tool returns 8,000 characters, and the model has to re-read these 8,000 characters to decide the next step. The dsh-memory-router introduced below handles this before the readback—avoiding paying for the same content twice, trimming long outputs by field, and avoiding repeatedly injecting state-related issues.
It needs to keep an account book first. This plugin comes with its own “Save / Spend / Lose” ledger, recording the tokens saved by truncation, the tokens spent by injection, and the loss items caused by over-compression forcing the model to re-read, rather than just reporting good news. The article concludes with its own empirical findings: single hits definitely save, but the long-term accumulated net benefit is currently negative.
What is this¶
dcd887/dsh-memory-router, maintained by dcd887, category “Workflow”. It hooks into the boundary of DSH’s tool invocation, handling two types of waste:
- The same file or command is called twice, and the text model reads the text again the second time;
- The tool returns a long output, but the model only needs a few specific fields.
It corresponds to the three mechanisms EDG / GDR / CCS proposed in HarnessMM (arXiv 2610.32813) and is a runnable equivalent implementation by the author on DSH. Note that the author explicitly states: DSH’s PostToolDecision only has accept / block branches, there is no “execute next action” branch, so the plugin saves context volume, not model turns.
Core Features¶
The plugin consists of four modules, all verified in production environments (the inject injection gate is unit-test passed):
dedupe: For the same tool and parameters, directly reuses the previous text within the TTL cache window; the tool itself is not executed again;edg: Declarative decision graph, matches tool names and parameters, executes a local read-only action when the guard condition is true, replacing the original output with structured results;liveState: Session continuation, automatically persists “what is being processed, which files were touched” to disk, injected in the first round of new sessions;inject: Injection gate, controls the number of injections using content hashing, length limits, and ledger row rate limiting.
The processing order is fixed: Deduplication → Decision Graph → Threshold Compression → Cache Final Text. Any step throwing an exception will roll back, not blocking the main loop.
The gate of edg is narrow: guards only have five pure local operators (exitCode / fileExists / regex / minChars / jsonPath); actions only have four read-only actions (readJson / readFileSlice / grep / stat). Writing exec will throw an error directly. The design intent is: if the decision graph is misconfigured, the worst result is degradation to a state without it.
Installation and Enablement¶
The installation method given in the README is to clone the repo, run the tests, and then mount it as a local plugin into the profile:
git clone https://github.com/dcd887/dsh-memory-router.git
cd dsh-memory-router && npm test # 6 test suites, 92 items
# Create a link under node_modules in the profile (use mklink /J on Windows)
ln -s /path/to/dsh-memory-router ~/.dsh/profiles/web/node_modules/@local/dsh-memory-router
Takes effect after restarting DSH. The repo is marked as alpha, Node requires >=18, license is MIT (README notes that a LICENSE file should be added before submitting). This plugin runs with the permissions of the current DSH process; before installing, you should read the source code in index.js and lib/ to confirm the behavior matches expectations.
Typical Usage¶
Decision graph configuration is placed in ~/.dsh/memory-router/edg.json, the edg.example.json in the repo provides an example of ten nodes. A node looks like this:
{
"id": "tax-table-pick-fields",
"match": { "tool": "read", "args": { "file_path": { "$re": "hs_codes" } } },
"guard": { "minChars": 2000 },
"then": [
{ "act": "readJson", "path": "${args.file_path}", "limit": 3,
"pick": ["hs_code", "name", "import_tariff", "category"] }
]
}
This rule matches calls to read files related to hs_codes, and after a hit, checks if the character count exceeds 2,000; if so, it returns only the 4 fields of the first 3 entries.
Comparison data for a real session comes from the README:
| Scenario | Native | With Plugin | Saved |
|---|---|---|---|
| Reading tax tariff large table (8,972 rows) | 6031 chars | 298 chars (total count + 3 sample entries × 4 fields) | 1433 tokens |
| Reading blind recommendation records (26 KB) | 8035 chars | 1707 chars (title skeleton + error row + conclusion row) | 1582 tokens |
| Re-executing the same command | Re-executed | Hit cache, not executed | Ledger records dedupe |
Results for the ten-case A/B test (node scripts/ab.mjs, reproducible): 6/10 hits, average saving of 96% when hitting; the total is a sample selected, which is an upper bound; calculated based on a 30% hit rate, it is about 29%.
Accounting Standards¶
The plugin writes every cost into metrics.jsonl, with the following standards:
Net Benefit = Trim Savings + Dedupe Savings + Decision Graph Savings − Reread Losses − Injection Costs − Summary Costs
| Account | Records what |
|---|---|
trim |
Tokens saved by compression |
trim-skip |
Count of times saved too little and no compression occurred (not recorded) |
dedupe |
Tokens saved by reusing the cache |
edg |
Tokens saved by local execution replacing the output |
reread |
Negative income: last time compressed, same call came again |
inject |
Tokens spent on injection |
To view the ledger:
node scripts/stats.mjs
The cumulative ledger explicitly written in the README is:
Trim Savings 1223 · Dedupe Savings 0 (2 times) · Decision Graph Savings 3015 (2 times)
Reread Losses 0 · Injection Costs 14755 · Net −10517
Two explanations: injection overhead is historically accumulated, mostly happening before the “injection gate” was installed; also, the verification method amplifies it—the author has been repeatedly testing on similar questions. So “saving 1400–1600 tokens per single hit” is true, but “long-term net benefit is positive” has not yet been proven.
The author additionally added a subject reread not in the paper. The reason is: the more you compress, the more it looks like it saves on the ledger, but the model might re-read because information was trimmed, making it actually more expensive. If this is not recorded, the ledger will be systematically high.
Applicable Scenarios and Notes¶
Suitable scenarios are workflows where tool output is long, fields are fixed, and calls repeat. The load types mentioned in the README are Writing and Research Agents.
A few points to note:
- The accumulated net benefit is currently negative; the author put this prominently in the README and suggests reading it before deciding whether to Star;
- It is in alpha status, and functionality or configuration formats may change;
- It saves context volume, not model turns, which is different from the starting point of the GDR paper, so do not apply the numbers in the paper directly;
- The plugin runs with the permissions of the current DSH process; read source code and confirm license before installing;
- Star count is 0, the niche is early; run
node scripts/ab.mjslocally to reproduce before using.
Related Links¶
Directory Page: https://www.skillhub.cn/plugins/dcd887/dsh-memory-router
Repo: https://github.com/dcd887/dsh-memory-router
Paper: https://arxiv.org/abs/2610.32813
The directory page is an independent site with no official affiliation to DeepSeek / Hypersphere.