Skip to main content

awecompress: Context Compression Proxy

Freeze old turns into one summary before they reach your provider.

Local context compression for coding agents — three wire protocols, standalone proxy or in-process inside awerouter. When a session's history crosses a token threshold, the oldest whole turns are replaced by a single frozen LLM summary — cached, so every later request reuses the same bytes and your provider's prompt cache stays warm.

English · 简体中文

Version Python License

Status pip Platform Stars

Compress long coding-agent context: old turns become one frozen summary, requests shrink, sessions run for days without a /clear. Standalone proxy, or one flag inside awerouter.

How it works

Claude Code resubmits the whole conversation every turn. Hours in, most of that is dead weight — old file reads, finished exploration, failed attempts.

awecompress sits between the agent and whatever speaks its protocol upstream — Anthropic Messages, OpenAI Chat Completions, or OpenAI Responses:

Responses requests that use the valid string form of input are forwarded transparently; compression requires the list form so turn boundaries remain explicit.

Claude Code → awecompress (:8808) → awerouter → providers

For each request it estimates the context size. Above a threshold, it picks a cut point on a turn boundary (a message a human actually sent — so a tool call is never separated from its result), summarizes everything before it with one LLM call, replaces those messages with a single summary message, and freezes the result in a local SQLite store. Protected content — todo lists, plans, task/skill outcomes, files you name by pattern — renders into the summarizer uncapped and must survive the summary verbatim.

Three properties matter:

  • Frozen, not recomputed. The summary is stored once. Every later request reuses the same bytes, so the provider prompt cache sees a stable prefix. Growing the covered span rewrites the summary once — a one-time cache miss.
  • Fail-open. Any failure in the compression path forwards the original body untouched. A compression problem never breaks the session.
  • No auth, no routing. Auth headers pass through; routing and failover stay in awerouter (or whatever your upstream is). The summary calls themselves are ordinary requests through that upstream — awerouter's flash routing applies to them like anything else.

Set X-Awecompress: off on a request to bypass compression entirely.

Install

pip install awecompress

Or from source:

git clone https://github.com/wehuman01/awecompress
cd awecompress && pip install -e .

Quick Start

Stack with awerouter (the intended setup):

awerouter serve run          # your routing daemon, as usual
awecompress serve            # the compression proxy, foreground

# point Claude Code at awecompress instead of awerouter
export ANTHROPIC_BASE_URL=http://127.0.0.1:8808
claude

# openai-chat / openai-responses clients work the same way
export OPENAI_BASE_URL=http://127.0.0.1:8808/v1

Or skip the proxy entirely — with awerouter installed, flip the profile flag and the compression runs inside the router (see below).

Standalone against any Anthropic-protocol endpoint:

awecompress serve --upstream https://api.anthropic.com

Watch it work — one line per compressed request, and stats on demand:

[awecompress] 3f9a2c1b: init — summarized messages 0..61 (est 41200 tok) into 1100
              via claude-sonnet in 2.8s; body est 48900 -> 8800 tokens
[awecompress] 3f9a2c1b: applied frozen summary (messages 0..61) — est 48900 -> 8800 tokens
awecompress status

With awerouter (in-process, no proxy)

awerouter accepts an awecompress profile flag, exactly like rtk/odcp. The compression core runs inside the router's pipeline — ahead of odcp pruning and rtk compression — so clients keep pointing at the router port and the flag hot-reloads with routing.json:

"cc-router-1": {
  "protocol": "anthropic",
  "destinations": { "flash": "stepfun,step-3.7-flash", "pro": "glm,glm-5.3" },
  "odcp": true,
  "awecompress": true
}

An object tunes it — summaryModel picks who serves the summary calls: "flash" (default, the flash destination — routed directly, never re-priced to pro by the long-context rule), "pro", or any model a provider declares in providers.json (validated at serve start). The other keys mirror the standalone config:

"awecompress": {
  "summaryModel": "flash",
  "thresholdTokens": 60000,
  "keepRecentTurns": 4,
  "protectedTools": ["task", "skill", "todowrite", "todoread", "updateplan"],
  "protectedFilePatterns": ["**/*.schema.json"]
}

Requires the package on the router's side: pip install awerouter[compress] (the flag dies at serve start with that hint when it is missing). Savings land in the usage log next to rtk/odcp (awecompress_saved, shown by awerouter usage), X-Awerouter-Token-Saver: off disables all lossy layers at once, and the frozen store is shared with the standalone proxy (awecompress status / clear manage it either way).

Config

~/.config/awecompress/config.json (or $AWECOMPRESS_CONFIG_DIR), written with defaults on first run:

{
  "port": 8808,
  "upstream": "http://127.0.0.1:20128",
  "thresholdTokens": 60000,
  "keepRecentTurns": 4,
  "minSpanTokens": 8000,
  "summaryModel": "",
  "summaryMaxTokens": 2048
}
Key Default Meaning
port 8808 Listen port.
upstream http://127.0.0.1:20128 Where requests go — awerouter by default.
thresholdTokens 60000 Estimated context above which compression triggers.
keepRecentTurns 4 Human turns always kept verbatim.
minSpanTokens 8000 Don't summarize spans smaller than this — not worth a call.
summaryModel "" Model for summary calls. Empty = the request's own model, routed by your upstream (usually flash).
summaryMaxTokens 2048 Max output tokens for a summary.
summaryTimeoutSeconds 60 Give up on a summary call after this; the request forwards uncompressed.
protectedTools see below Tools whose calls/results render into the summarizer uncapped and must survive the summary verbatim.
protectedFilePatterns [] Glob patterns; a call whose file_path/path argument matches renders uncapped too.
transcriptResultCap 4000 Per-tool-result cap (chars) when flattening history for the summarizer.
dbPath config dir SQLite store for frozen summaries.

Commands

awecompress serve                  # run the proxy in the foreground
awecompress serve --port 8809 --upstream http://127.0.0.1:20128
awecompress status                 # running state + compression stats
awecompress config path            # where the config lives
awecompress config show            # print it
awecompress clear --yes            # drop all frozen summaries

Notes and limits

  • Three protocols — Anthropic Messages, OpenAI Chat Completions, OpenAI Responses. Requests to other paths are relayed untouched.
  • Compression is lossy by design. The summarizer prompt demands exhaustive technical detail and verbatim short user messages, but a summary is still a summary. keepRecentTurns keeps the working set verbatim; raise it if you want more raw history.
  • A session rewound to a checkpoint (changed history under a stored summary) is detected by hash and recompressed from scratch.
  • /v1/messages/count_tokens applies existing summaries but never triggers a new summary call.
  • Inspired by DCP's Compress strategy (AGPL) and the closed-source Sleev — both harness-integrated. awecompress is an independent, proxy-native implementation; no DCP code is used.

Development

pip install -e ".[dev]"
pytest

See docs/CONTRIBUTING.md for architecture and the design contract.

License

MPL-2.0. Compression behavior inspired by DCP's public Compress documentation; implementation written from scratch.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

awecompress-0.2.0.tar.gz (38.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

awecompress-0.2.0-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file awecompress-0.2.0.tar.gz.

File metadata

  • Download URL: awecompress-0.2.0.tar.gz
  • Upload date:
  • Size: 38.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for awecompress-0.2.0.tar.gz
Algorithm Hash digest
SHA256 83107a7296f658c0651ec3006a76445746cb03f79adcd8910538ba265a48a7d2
MD5 ab71c2aeabb0689f14b79a42efdd8b07
BLAKE2b-256 f48623e47cc4e3d86be86822efe35d01df1692eada8bac60028fc6f0a4827b82

See more details on using hashes here.

File details

Details for the file awecompress-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: awecompress-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for awecompress-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 df83ad3e0acd0302e587530f8d088f877c768d53ff7e15f4ac0f6d547b77731b
MD5 99488b2e6db060c5c2638da1e2d9e06d
BLAKE2b-256 355986e0a083c7c1741390be1be4e367185b4459b57ff19260be168878640e04

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page