File size: 43,140 Bytes
9c7d451
 
cd5ea2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9c7d451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45633b6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9c7d451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14ecab6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485ea38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14ecab6
 
9c7d451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45633b6
 
 
 
 
 
9c7d451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c1feb60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d724f14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c1feb60
 
 
 
d724f14
 
 
 
 
c1feb60
 
 
8455c4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9c7d451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45633b6
 
 
 
 
14ecab6
 
 
45633b6
9c7d451
d724f14
c1feb60
 
 
 
 
 
 
d724f14
 
 
 
 
 
 
c1feb60
 
 
 
 
9c7d451
 
 
 
 
c1feb60
 
 
9c7d451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
# Headroom SDK: A Complete Explanation

## Architecture Overview

```mermaid
flowchart TB
    subgraph Entry["Entry Points"]
        Proxy["Proxy Mode<br/><i>Zero code changes</i>"]
        SDK["SDK Mode<br/><i>HeadroomClient</i>"]
        Integrations["Integrations<br/><i>LangChain / Agno</i>"]
    end

    subgraph Pipeline["Transform Pipeline"]
        direction TB

        CA["Cache Aligner<br/>━━━━━━━━━━━━━━━<br/>Extracts dynamic content<br/>(dates, UUIDs, tokens)<br/>Stable prefix for caching"]

        SC["Smart Crusher<br/>━━━━━━━━━━━━━━━<br/>Analyzes tool outputs<br/>Keeps: first, last, errors, outliers<br/>70-95% reduction"]

        CM["Context Manager<br/>━━━━━━━━━━━━━━━<br/>Enforces token limits<br/>Scores by recency and relevance<br/>Fits context window"]

        CA --> SC --> CM
    end

    subgraph Cache["Provider Cache Optimization"]
        direction LR
        Anthropic["Anthropic<br/><i>cache_control blocks</i><br/>90% savings"]
        OpenAI["OpenAI<br/><i>Prefix alignment</i><br/>50% savings"]
        Google["Google<br/><i>CachedContent API</i><br/>75% savings"]
    end

    subgraph CCR["CCR: Compress-Cache-Retrieve"]
        Store[("Compression<br/>Store")]
        Tool["Retrieve Tool<br/><i>LLM requests original</i>"]
        Store <--> Tool
    end

    LLM["LLM API<br/><i>OpenAI / Anthropic / Google</i>"]

    Entry --> Pipeline
    Pipeline --> Cache
    Cache --> LLM
    SC -.->|"Stores original"| Store
    LLM -.->|"If needed"| Tool
```

---

## What Problem Does Headroom Solve?

When you use AI models like GPT-4 or Claude, you pay for **tokens** - the pieces of text you send (input) and receive (output). The problem is:

1. **Tool outputs are HUGE**: When an AI agent calls tools (search, database queries, APIs), the responses are often massive JSON blobs with thousands of tokens
2. **Most of that data is REDUNDANT**: 60 metric data points showing `cpu: 45%` repeated, or 50 log entries with the same error message
3. **You're paying for waste**: Every token costs money and adds latency
4. **Context windows fill up**: Models have limits (128K tokens), and bloated tool outputs eat into your available space

**Headroom creates "headroom"** - it intelligently compresses your input tokens so you have more room (and budget) for what matters.

---

## How Headroom Works: The Big Picture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        YOUR APPLICATION                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      HEADROOM CLIENT                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚  β”‚   ANALYZE   β”‚β†’ β”‚  TRANSFORM  β”‚β†’ β”‚    CALL     β”‚             β”‚
β”‚  β”‚  (Parser)   β”‚  β”‚  (Pipeline) β”‚  β”‚   (API)     β”‚             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚         β”‚                β”‚                β”‚                     β”‚
β”‚         β–Ό                β–Ό                β–Ό                     β”‚
β”‚   Count tokens     Apply compressions   Send to OpenAI/Claude  β”‚
β”‚   Detect waste     Preserve meaning     Log metrics            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    OPENAI / ANTHROPIC API                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## The Core Components (In Simple Terms)

### 1. HeadroomClient (`client.py`) - The Wrapper

This is what you interact with. It wraps your existing OpenAI or Anthropic client:

```python
# Before (normal OpenAI)
client = OpenAI(api_key="...")
response = client.chat.completions.create(model="gpt-4o", messages=[...])

# After (with Headroom)
base = OpenAI(api_key="...")
client = HeadroomClient(original_client=base, provider=OpenAIProvider())
response = client.chat.completions.create(model="gpt-4o", messages=[...])
```

**What it does:**
- Intercepts your API calls
- Runs messages through the transform pipeline
- Calls the real API with optimized messages
- Logs metrics to a database
- Returns the response unchanged

**Two modes:**
- `audit`: Just observe and log (no changes)
- `optimize`: Apply transforms to reduce tokens

---

### 2. Providers (`providers/`) - Model-Specific Knowledge

Different AI providers have different rules:

```python
class OpenAIProvider:
    # Knows GPT-4o has 128K context
    # Knows how to count tokens (tiktoken)
    # Knows pricing ($2.50 per million input tokens)

class AnthropicProvider:
    # Knows Claude has 200K context
    # Uses different tokenization (~4 chars per token)
    # Different pricing structure
```

**Why this matters:** Token counting is model-specific. GPT-4 uses different tokenization than Claude. Headroom needs accurate counts to know how much to compress.

---

### 3. Parser (`parser.py`) - Understanding Your Messages

Before optimizing, Headroom needs to understand what's in your messages:

```python
messages = [
    {"role": "system", "content": "You are helpful..."},
    {"role": "user", "content": "Search for X"},
    {"role": "assistant", "tool_calls": [...]},
    {"role": "tool", "content": "{huge JSON}"},
]

# Parser breaks this into "blocks":
blocks = [
    Block(kind="system", tokens=50, ...),
    Block(kind="user", tokens=10, ...),
    Block(kind="tool_call", tokens=20, ...),
    Block(kind="tool_result", tokens=5000, ...),  # ← This is the problem!
]
```

**It also detects waste signals:**
- Large JSON blobs (>500 tokens)
- HTML tags and comments
- Base64 encoded data
- Excessive whitespace

---

### 4. Transforms (`transforms/`) - The Compression Magic

This is where the real work happens. Headroom has 4 transforms that run in sequence:

#### Transform 1: Cache Aligner

**Problem:** LLM providers cache your prompts, but only if they're byte-identical. If your system prompt has today's date, every day is a cache miss.

```python
# Before:
"You are helpful. Current Date: 2024-12-15"  # Changes daily = no cache

# After:
"You are helpful."  # Static = cacheable
"[Context: Current Date: 2024-12-15]"  # Dynamic part moved to end
```

**How it works:**
1. Find date patterns in system prompt
2. Extract them
3. Move to end of message
4. Now the PREFIX is stable β†’ cache hits!

---

#### Transform 2: Tool Crusher (Naive) - DISABLED BY DEFAULT

This was our first approach - simple but limited:

```python
# Before: 60 items
[{"ts": 1, "cpu": 45}, {"ts": 2, "cpu": 45}, ..., {"ts": 60, "cpu": 95}]

# After: First 10 items only
[{"ts": 1, "cpu": 45}, ..., {"ts": 10, "cpu": 45}, {"__truncated": 50}]
```

**Problem:** If the important data (CPU spike) is at position 45, it gets thrown away!

---

#### Transform 3: Smart Crusher (NEW DEFAULT)

This is the intelligent approach using **statistical analysis**:

```python
# Analyzes the data first:
analysis = {
    "ts": {"type": "sequential", "unique_ratio": 1.0},
    "host": {"type": "constant", "value": "prod-1"},  # ← Same everywhere!
    "cpu": {"variance": 892, "change_points": [45]},  # ← Spike detected!
}

# Smart compression:
{
    "__headroom_constants": {"host": "prod-1"},  # Factor out
    "__headroom_summary": "items 0-44: cpu stable at ~45",  # Summarize boring part
    "data": [
        {"ts": 45, "cpu": 92},  # Keep the spike!
        {"ts": 46, "cpu": 95},
        ...
    ]
}
```

**Strategies it uses:**
1. **TIME_SERIES**: Detect variance spikes, keep change points
2. **CLUSTER**: Group similar log messages, keep 1-2 per cluster
3. **TOP_N**: For search results, keep highest scored
4. **SMART_SAMPLE**: Statistical sampling with constant extraction

---

#### Transform 4: LLMLingua Compressor (Optional)

**When to use:** Maximum compression needed and latency is acceptable.

```python
# Opt-in ML-based compression using Microsoft's LLMLingua-2
# BERT-based token classifier trained via GPT-4 distillation

# Before: Long tool output text
"The function processUserData takes a user object and validates all fields..."

# After: Compressed while preserving semantic meaning
"function processUserData validates user fields..."
```

**Key characteristics:**
- Uses `microsoft/llmlingua-2-xlm-roberta-large-meetingbank` model
- Auto-detects content type (code, JSON, text) for optimal compression rates
- Stores original in CCR for retrieval if needed
- Adds 50-200ms latency per request
- Requires ~1GB RAM when loaded

**Proxy integration (opt-in):**
```bash
headroom proxy --llmlingua --llmlingua-device cuda
```

---

#### Transform 5: Rolling Window

**Problem:** Even after compression, you might exceed the model's context limit.

```python
# Model limit: 128K tokens
# Your messages: 150K tokens
# Need to drop 22K tokens

# Rolling Window drops OLDEST messages first:
# - Keeps system prompt (always)
# - Keeps last 2 turns (always)
# - Drops old tool calls + their responses as atomic units
```

**Safety rule:** If we drop a tool CALL, we MUST drop its RESPONSE too (or vice versa). Otherwise the model sees orphaned data.

---

#### Transform 6: Intelligent Context Manager (Advanced)

**Problem:** Rolling Window drops by position (oldest first), but position doesn't equal importance.

```python
# Scenario: Error at turn 3, verbose success at turn 10
# Rolling Window: Drops turn 3 error (oldest first)
# Intelligent Context: Keeps turn 3 error (high TOIN error score)
```

**The Solution:** Multi-factor importance scoring using TOIN-learned patterns:

```python
# Message scores (all learned, no hardcodes):
scores = {
    "recency": 0.20,           # Exponential decay from end
    "semantic_similarity": 0.20,  # Embedding similarity to recent context
    "toin_importance": 0.25,   # TOIN retrieval_rate (high = important)
    "error_indicator": 0.15,   # TOIN field_semantics.inferred_type
    "forward_reference": 0.15, # Referenced by later messages
    "token_density": 0.05,     # Unique tokens / total tokens
}

# Drops lowest-scored messages first
# Preserves critical errors even if old
```

**Key principle:** No hardcoded patterns. Error detection uses TOIN's learned `field_semantics.inferred_type == "error_indicator"`, not keyword matching like "error" or "fail".

**TOIN + CCR Integration:**

IntelligentContext is a **message-level compressor** β€” just like SmartCrusher compresses items in an array, IntelligentContext "compresses" messages in a conversation. This means full CCR integration:

```python
# When messages are dropped:
# 1. Store dropped messages in CCR for potential retrieval
ccr_ref = store.store(
    original=json.dumps(dropped_messages),
    compressed="[60 messages dropped]",
    tool_name="intelligent_context_drop",
)

# 2. Record drop to TOIN for cross-user learning
toin.record_compression(
    tool_signature=message_signature,  # Pattern of roles, tools, errors
    original_count=len(dropped_messages),
    compressed_count=1,  # The marker
    strategy="intelligent_context_drop",
)

# 3. Insert marker with CCR reference
marker = f"[Earlier context compressed: 60 messages dropped. Retrieve: {ccr_ref}]"
```

**The feedback loop:**
- If users retrieve dropped messages via CCR, TOIN learns those patterns are important
- Future drops of similar message patterns get higher importance scores
- The system gets smarter across all users, not just within one session

---

### 5. Storage (`storage/`) - Metrics Database

Every request is logged:

```sql
CREATE TABLE requests (
    id TEXT PRIMARY KEY,
    timestamp TEXT,
    model TEXT,
    mode TEXT,  -- audit or optimize
    tokens_input_before INTEGER,  -- Before Headroom
    tokens_input_after INTEGER,   -- After Headroom
    tokens_saved INTEGER,         -- The win!
    transforms_applied TEXT,      -- What we did
    ...
);
```

This lets you:
- See how much you're saving
- Generate reports
- Track trends over time

---

## The Data Flow (Step by Step)

Let's trace a real request:

### Step 1: You call the API
```python
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "You are an SRE. Date: 2024-12-15"},
        {"role": "user", "content": "Check the metrics"},
        {"role": "assistant", "tool_calls": [...]},
        {"role": "tool", "content": "{60 metric points...}"},  # 5000 tokens!
        {"role": "user", "content": "What's wrong?"},
    ],
    headroom_mode="optimize",
)
```

### Step 2: HeadroomClient intercepts
```python
# In client.py:
def _create(self, messages, ...):
    # 1. Parse messages into blocks
    blocks, breakdown, waste = parse_messages(messages, tokenizer)
    # breakdown = {"system": 50, "user": 20, "tool_result": 5000, ...}

    # 2. Count original tokens
    tokens_before = 5100
```

### Step 3: Transform Pipeline runs
```python
# In pipeline.py:
def apply(self, messages, ...):
    # Transform 1: Cache Aligner
    # - Extracts "Date: 2024-12-15" from system prompt
    # - Moves to end

    # Transform 2: Smart Crusher
    # - Analyzes 60 metric points
    # - Detects CPU spike at point 45
    # - Compresses to 17 points (preserving spike)
    # - Factors out constant "host" field

    # Transform 3: LLMLingua (if enabled via --llmlingua)
    # - ML-based compression on remaining long text
    # - Auto-detects content type for optimal rate
    # - Stores original in CCR for retrieval

    # Transform 4: Rolling Window
    # - Checks if we're under limit (we are)
    # - No drops needed

    return TransformResult(
        messages=optimized,
        tokens_before=5100,
        tokens_after=1200,  # 76% reduction!
        transforms=["cache_align", "smart_crush:1"]
    )
```

### Step 4: Call real API
```python
# In client.py:
response = self._original.chat.completions.create(
    model="gpt-4o",
    messages=optimized_messages,  # Only 1200 tokens now!
)
```

### Step 5: Log metrics and return
```python
# Save to database
metrics = RequestMetrics(
    tokens_input_before=5100,
    tokens_input_after=1200,
    tokens_saved=3900,  # 76%!
    ...
)
storage.save(metrics)

return response  # Unchanged from API
```

---

## The Smart Crusher Deep Dive

This is the most sophisticated part. Here's how it analyzes data:

### Field Analysis
```python
def analyze_field(key, items):
    values = [item[key] for item in items]

    return {
        "unique_ratio": len(set(values)) / len(values),
        # 0.0 = all same (constant)
        # 1.0 = all different (unique IDs)

        "variance": statistics.variance(values),  # For numbers
        # Low = stable
        # High = changing

        "change_points": detect_spikes(values),
        # Indices where value jumps significantly
    }
```

### Pattern Detection
```python
def detect_pattern(field_stats):
    # Has timestamp + numeric variance? β†’ TIME_SERIES
    if has_timestamp and has_numeric_variance:
        return "time_series"

    # Has message field + level field? β†’ LOGS
    if has_message_field and has_level_field:
        return "logs"

    # Has score/rank field? β†’ SEARCH_RESULTS
    if has_score_field:
        return "search_results"

    return "generic"
```

### Compression Strategy
```python
def compress(items, analysis):
    if analysis.pattern == "time_series":
        # Keep points around change points
        # Summarize stable regions
        return time_series_compress(items, analysis.change_points)

    elif analysis.pattern == "logs":
        # Cluster similar messages
        # Keep 1-2 per cluster
        return cluster_compress(items, analysis.clusters)

    elif analysis.pattern == "search_results":
        # Sort by score
        # Keep top N
        return top_n_compress(items, analysis.score_field)
```

---

## CCR Architecture: Compress-Cache-Retrieve

### The Key Insight

> "Prefer raw > Compaction > Summarization only when compaction no longer yields enough space. Compaction (Reversible) strips out information that is redundant because it exists in the environmentβ€”if the agent needs to read the data later, it can use a tool to retrieve it." β€” Phil Schmid, Context Engineering

**The problem with traditional compression:** If we guess wrong about what's important, we've permanently lost data. The LLM might need something we threw away.

**CCR's solution:** Make compression **reversible**. When SmartCrusher compresses, the original data is cached. If the LLM needs more, it can retrieve instantly.

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  TOOL OUTPUT (1000 items)                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
                         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  HEADROOM CCR LAYER                                               β”‚
β”‚                                                                   β”‚
β”‚  1. COMPRESS: Keep 20 items (errors, anomalies, relevant)        β”‚
β”‚  2. CACHE: Store full 1000 items in fast local cache             β”‚
β”‚  3. INJECT: Add retrieval capability to LLM context              β”‚
β”‚                                                                   β”‚
β”‚  "20 items shown. Use /v1/retrieve?hash=xxx for more."           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
                         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  LLM PROCESSING                                                   β”‚
β”‚                                                                   β”‚
β”‚  Option A: LLM solves task with 20 items β†’ Done                  β”‚
β”‚  Option B: LLM needs more β†’ retrieves via API                    β”‚
β”‚            β†’ We fetch from cache β†’ Return instantly              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
                         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  FEEDBACK LOOP                                                    β”‚
β”‚                                                                   β”‚
β”‚  Track: What did the LLM retrieve? What queries?                 β”‚
β”‚  Learn: "For this tool, keep items matching common queries"      β”‚
β”‚  Improve: Next compression uses learned patterns                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

### CCR Phase 1: Compression Store

**Location:** `headroom/cache/compression_store.py`

When SmartCrusher compresses, the original content is stored for on-demand retrieval:

```python
@dataclass
class CompressionEntry:
    hash: str                    # 16-char SHA256 for retrieval
    original_content: str        # Full JSON before compression
    compressed_content: str      # Compressed JSON
    original_item_count: int
    compressed_item_count: int
    tool_name: str | None        # For feedback tracking
    created_at: float
    ttl: int = 300               # 5 minute default
```

**Features:**
- Thread-safe in-memory storage
- TTL-based expiration (default 5 minutes)
- LRU-style eviction when capacity reached
- Built-in BM25 search within cached content

**Usage:**
```python
store = get_compression_store()

# Store compressed content
hash_key = store.store(
    original=original_json,
    compressed=compressed_json,
    original_item_count=1000,
    compressed_item_count=20,
    tool_name="search_api",
)

# Retrieve later
entry = store.retrieve(hash_key)

# Or search within cached content
results = store.search(hash_key, "user query")
```

---

### CCR Phase 2: Retrieval API

**Endpoints:**

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/v1/retrieve` | POST | Retrieve original content by hash |
| `/v1/retrieve?query=X` | POST | Search within cached content |

**Retrieval Request:**
```json
{
    "hash": "abc123def456...",
    "query": "find errors"     // Optional: search within
}
```

**Response (full retrieval):**
```json
{
    "hash": "abc123def456...",
    "original_content": "[{...}, {...}, ...]",
    "original_item_count": 1000,
    "tool_name": "search_api"
}
```

**Response (search):**
```json
{
    "hash": "abc123def456...",
    "query": "find errors",
    "results": [{...}, {...}, ...],
    "count": 15
}
```

---

### CCR Phase 3: Tool Injection

When compression happens, Headroom injects retrieval instructions into the LLM context.

**Method A: System Message Injection**
```
## Compressed Context Available
The following tool outputs have been compressed. If you need more detail,
call the retrieve_compressed tool with the hash.

Available: hash=abc123 (1000β†’20 items from search_api)
```

**Method B: MCP Tool Registration (Hybrid)**
When running as MCP server, Headroom exposes retrieval as a tool:

```json
{
    "name": "headroom_retrieve",
    "description": "Retrieve more items from compressed tool output",
    "inputSchema": {
        "type": "object",
        "properties": {
            "hash": {"type": "string"},
            "query": {"type": "string"}
        }
    }
}
```

**Marker Injection:**
Compressed content includes retrieval markers:
```json
{
    "__headroom_compressed": true,
    "__headroom_hash": "abc123def456",
    "__headroom_stats": {
        "original_items": 1000,
        "kept_items": 20,
        "errors_preserved": 5
    },
    "data": [...]
}
```

---

### CCR Phase 4: Feedback Loop

**Location:** `headroom/cache/compression_feedback.py`

The feedback system learns from retrieval patterns to improve future compression.

**Tracked Patterns per Tool:**
```python
@dataclass
class ToolPattern:
    tool_name: str
    total_compressions: int      # Times we compressed this tool
    total_retrievals: int        # Times LLM asked for more
    full_retrievals: int         # Retrieved everything
    search_retrievals: int       # Used search query
    common_queries: dict[str, int]   # Query frequency
    queried_fields: dict[str, int]   # Fields mentioned in queries
```

**Key Metrics:**
- **Retrieval Rate**: `total_retrievals / total_compressions`
  - High (>50%) β†’ Compressing too aggressively
  - Low (<20%) β†’ Compression is effective
- **Full Retrieval Rate**: `full_retrievals / total_retrievals`
  - High (>80%) β†’ Data is unique, consider skipping compression

**Compression Hints:**
```python
@dataclass
class CompressionHints:
    max_items: int = 15          # Target item count
    suggested_items: int | None  # Calculated optimal
    skip_compression: bool       # Don't compress at all
    preserve_fields: list[str]   # Always keep these fields
    aggressiveness: float        # 0.0 = aggressive, 1.0 = conservative
    reason: str                  # Explanation
```

**Feedback-Driven Adjustment:**
```python
# In SmartCrusher._crush_array()
if self.config.use_feedback_hints and tool_name:
    feedback = get_compression_feedback()
    hints = feedback.get_compression_hints(tool_name)

    if hints.skip_compression:
        return items, f"skip:feedback({hints.reason})", None

    if hints.suggested_items is not None:
        self.config.max_items_after_crush = hints.suggested_items
```

**Feedback Endpoints:**

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/v1/feedback` | GET | Get all learned patterns |
| `/v1/feedback/{tool_name}` | GET | Get hints for specific tool |

**Example Response:**
```json
{
    "total_compressions": 150,
    "total_retrievals": 23,
    "global_retrieval_rate": 0.15,
    "tools_tracked": 5,
    "tool_patterns": {
        "search_api": {
            "compressions": 50,
            "retrievals": 5,
            "retrieval_rate": 0.10,
            "full_rate": 0.20,
            "search_rate": 0.80,
            "common_queries": ["status:error", "level:critical"],
            "queried_fields": ["status", "level", "message"]
        }
    }
}
```

---

### CCR Phase 5: Response Handler (Automatic Tool Call Handling)

**Location:** `headroom/ccr/response_handler.py`

**The Problem:** When the proxy injects the `headroom_retrieve` tool, the LLM might call it. But who handles that tool call? Without response handling, the tool call would go back to the client unhandled.

**The Solution:** The Response Handler intercepts LLM responses, detects CCR tool calls, executes retrievals automatically, and continues the conversation until the LLM produces a final response.

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  RESPONSE HANDLER FLOW                                           β”‚
β”‚                                                                   β”‚
β”‚  1. LLM Response arrives                                         β”‚
β”‚     └─ Contains: tool_use(headroom_retrieve, hash=abc123)       β”‚
β”‚                                                                   β”‚
β”‚  2. Handler detects CCR tool call                                β”‚
β”‚     └─ Extracts hash and optional query                         β”‚
β”‚                                                                   β”‚
β”‚  3. Handler executes retrieval                                   β”‚
β”‚     └─ Full retrieval: store.retrieve(hash)                     β”‚
β”‚     └─ Search: store.search(hash, query)                        β”‚
β”‚                                                                   β”‚
β”‚  4. Handler continues conversation                               β”‚
β”‚     └─ Adds tool result to messages                             β”‚
β”‚     └─ Makes another API call                                   β”‚
β”‚                                                                   β”‚
β”‚  5. Repeat until no CCR tool calls                              β”‚
β”‚     └─ Max 3 rounds (configurable)                              β”‚
β”‚                                                                   β”‚
β”‚  6. Return final response to client                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

**Key Classes:**

```python
@dataclass
class CCRToolCall:
    tool_call_id: str      # For matching response
    hash_key: str          # CCR hash to retrieve
    query: str | None      # Optional search query

@dataclass
class CCRToolResult:
    tool_call_id: str
    content: str           # Retrieved data as JSON
    success: bool
    items_retrieved: int
    was_search: bool       # True if search, False if full retrieval

class CCRResponseHandler:
    async def handle_response(
        self,
        response: dict,           # Initial LLM response
        messages: list,           # Conversation history
        tools: list,              # Tool definitions
        api_call_fn: Callable,    # Function to make API calls
        provider: str,            # "anthropic" or "openai"
    ) -> dict:
        """Handle CCR tool calls until final response."""
```

**Streaming Support:**

The handler also supports streaming responses via `StreamingCCRHandler`:

```python
class StreamingCCRBuffer:
    """Buffers streaming chunks to detect CCR tool calls."""
    chunks: list[bytes]
    detected_ccr: bool

class StreamingCCRHandler:
    """Handles CCR in streaming responses."""
    async def process_stream(self, stream, messages, tools, api_call_fn):
        """Yields chunks, switching to buffered mode if CCR detected."""
```

---

### CCR Phase 6: Context Tracker (Multi-Turn Awareness)

**Location:** `headroom/ccr/context_tracker.py`

**The Problem:** In multi-turn conversations, earlier compressed data might become relevant later. Without tracking, the LLM has "context amnesia" - it can't reference data that was compressed in turn 1 when answering a question in turn 5.

**The Solution:** The Context Tracker maintains awareness of all compressed content across the conversation and can proactively expand relevant data when a new query might need it.

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CONTEXT TRACKER FLOW                                            β”‚
β”‚                                                                   β”‚
β”‚  Turn 1: Search returns 100 files β†’ compressed to 10            β”‚
β”‚          Tracker stores: hash=abc123, sample="auth.py, db.py"   β”‚
β”‚                                                                   β”‚
β”‚  Turn 5: User asks "What about the authentication middleware?"  β”‚
β”‚          Tracker analyzes query:                                 β”‚
β”‚          - "authentication" matches "auth.py" in sample         β”‚
β”‚          - Relevance score: 0.7 (above threshold)               β”‚
β”‚                                                                   β”‚
β”‚  Proactive Expansion:                                           β”‚
β”‚          - Retrieves abc123 before LLM responds                 β”‚
β”‚          - Adds expanded context to request                     β”‚
β”‚                                                                   β”‚
β”‚  Result: LLM sees full file list, can answer accurately         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

**Key Classes:**

```python
@dataclass
class CompressedContext:
    hash_key: str              # CCR hash
    turn_number: int           # When compression happened
    timestamp: float           # For age-based filtering
    tool_name: str | None      # Which tool was compressed
    original_item_count: int
    compressed_item_count: int
    query_context: str         # User query at compression time
    sample_content: str        # Preview for relevance matching

@dataclass
class ExpansionRecommendation:
    hash_key: str
    reason: str                # Human-readable explanation
    relevance_score: float     # 0-1, higher = more relevant
    expand_full: bool          # True = full retrieval
    search_query: str | None   # If expand_full=False

class ContextTracker:
    def track_compression(self, hash_key, turn_number, ...):
        """Track a compression event."""

    def analyze_query(self, query: str) -> list[ExpansionRecommendation]:
        """Find relevant compressed contexts for a query."""

    def execute_expansions(self, recommendations) -> list[dict]:
        """Execute recommended expansions."""
```

**Relevance Calculation:**

The tracker uses simple but effective heuristics:

1. **Keyword overlap with sample content** - Extract keywords from query, match against compressed content preview
2. **Keyword overlap with original query** - Match against the query that triggered compression
3. **Tool name relevance** - File operations more likely to need expansion for "file", "where", "find" queries
4. **Age discount** - Older contexts get lower scores

**Configuration:**

```python
@dataclass
class ContextTrackerConfig:
    enabled: bool = True
    max_tracked_contexts: int = 100      # LRU eviction
    relevance_threshold: float = 0.3     # Min score to recommend
    max_context_age_seconds: float = 300 # 5 minutes
    proactive_expansion: bool = True
    max_proactive_expansions: int = 2    # Per query
```

---

### Why CCR is a Moat

1. **Reversible**: No permanent information loss. Worst case = retrieve everything.
2. **Transparent**: LLM knows it can ask for more data.
3. **Automatic**: Response Handler executes retrievals without client intervention.
4. **Context-Aware**: Context Tracker prevents multi-turn amnesia.
5. **Feedback Loop**: Learn from actual needs, not guesses.
6. **Network Effect**: Retrieval patterns across users improve compression for everyone.
7. **Zero-Risk**: If compression fails, instant fallback to original data.

---

## Image Compression Architecture

Vision models charge by the token, and images are expensive (765-2900 tokens for a typical image). Headroom's image compression uses a **trained ML router** to automatically select the optimal compression technique.

### The Key Insight

Not all image queries need full resolution:
- "What is this?" β†’ Low detail is fine (87% savings)
- "Count the whiskers" β†’ Need full detail (0% savings)
- "Read the sign" β†’ Could convert to text (99% savings)

### How It Works

```
User: [image] + "What animal is this?"
           ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  1. Query Analysis              β”‚
β”‚  TrainedRouter (MiniLM)         β”‚
β”‚  Classifies β†’ full_low          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  2. Image Analysis (Optional)   β”‚
β”‚  SigLIP checks:                 β”‚
β”‚  - Has text? Is complex?        β”‚
β”‚  - Fine details needed?         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  3. Apply Compression           β”‚
β”‚  OpenAI: detail="low"           β”‚
β”‚  Anthropic: Resize to 512px     β”‚
β”‚  Google: Resize to 768px        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           ↓
Compressed request β†’ LLM β†’ Response
```

### The Trained Router

A fine-tuned MiniLM classifier hosted on HuggingFace:

- **Model**: `chopratejas/technique-router`
- **Size**: ~128MB (downloaded once, cached)
- **Accuracy**: 93.7% on 1,157 training examples
- **Latency**: ~10ms CPU, ~2ms GPU

The router learns from examples like:
| Query | Technique |
|-------|-----------|
| "What is this?" | `full_low` |
| "Count the items" | `preserve` |
| "Read the text" | `transcode` |
| "What's in the corner?" | `crop` |

### Provider-Specific Compression

Each provider handles images differently:

| Provider | Method | Savings |
|----------|--------|---------|
| **OpenAI** | `detail="low"` parameter | ~87% |
| **Anthropic** | PIL resize to 512px | ~75% |
| **Google** | PIL resize to 768px (tile-optimized) | ~75% |

### Integration Points

Image compression runs in the proxy **before** text compression:

```
Request arrives
      ↓
[Image Compression] ← NEW
      ↓
[Transform Pipeline: Cache Aligner β†’ Smart Crusher β†’ ...]
      ↓
Forward to LLM
```

This ensures images are compressed first, then text compression (CCR, SmartCrusher) handles the rest.

### Code Location

```
headroom/
β”œβ”€β”€ image/
β”‚   β”œβ”€β”€ __init__.py         # Public API
β”‚   β”œβ”€β”€ compressor.py       # ImageCompressor class
β”‚   └── trained_router.py   # TrainedRouter (HuggingFace model)
β”œβ”€β”€ proxy/
β”‚   └── server.py           # Integration point
```

---

## File Structure Explained

```
headroom/
β”œβ”€β”€ __init__.py          # Public exports
β”œβ”€β”€ client.py            # HeadroomClient - the main wrapper
β”œβ”€β”€ config.py            # All configuration dataclasses
β”œβ”€β”€ parser.py            # Message β†’ Block decomposition
β”œβ”€β”€ tokenizer.py         # Token counting abstraction
β”œβ”€β”€ utils.py             # Hashing, markers, helpers
β”‚
β”œβ”€β”€ providers/
β”‚   β”œβ”€β”€ base.py          # Provider/TokenCounter protocols
β”‚   β”œβ”€β”€ openai.py        # OpenAI-specific (tiktoken)
β”‚   └── anthropic.py     # Anthropic-specific
β”‚
β”œβ”€β”€ transforms/
β”‚   β”œβ”€β”€ base.py              # Transform protocol
β”‚   β”œβ”€β”€ pipeline.py          # Orchestrates all transforms
β”‚   β”œβ”€β”€ cache_aligner.py     # Date extraction for caching
β”‚   β”œβ”€β”€ tool_crusher.py      # Naive compression (disabled)
β”‚   β”œβ”€β”€ smart_crusher.py     # Statistical compression (default)
β”‚   β”œβ”€β”€ rolling_window.py    # Token limit enforcement (position-based)
β”‚   β”œβ”€β”€ intelligent_context.py  # Semantic context management (score-based)
β”‚   β”œβ”€β”€ scoring.py           # Message importance scoring
β”‚   └── llmlingua_compressor.py  # ML-based compression (opt-in)
β”‚
β”œβ”€β”€ cache/               # CCR Architecture - Caching & Storage
β”‚   β”œβ”€β”€ compression_store.py    # Phase 1: Store original content
β”‚   β”œβ”€β”€ compression_feedback.py # Phase 4: Learn from retrievals
β”‚   β”œβ”€β”€ anthropic.py     # Anthropic cache optimizer
β”‚   β”œβ”€β”€ openai.py        # OpenAI cache optimizer
β”‚   β”œβ”€β”€ google.py        # Google cache optimizer
β”‚   └── dynamic_detector.py # Dynamic content detection
β”‚
β”œβ”€β”€ ccr/                 # CCR Architecture - Tool Injection & Response Handling
β”‚   β”œβ”€β”€ __init__.py             # CCR module exports
β”‚   β”œβ”€β”€ tool_injection.py       # Phase 3: Inject retrieval tool
β”‚   β”œβ”€β”€ response_handler.py     # Phase 5: Handle CCR tool calls
β”‚   β”œβ”€β”€ context_tracker.py      # Phase 6: Multi-turn context tracking
β”‚   └── mcp_server.py           # MCP server for retrieval tool
β”‚
β”œβ”€β”€ relevance/           # Relevance scoring for compression
β”‚   β”œβ”€β”€ bm25.py          # BM25 keyword scorer
β”‚   β”œβ”€β”€ embedding.py     # Semantic embedding scorer
β”‚   └── hybrid.py        # Adaptive fusion scorer
β”‚
β”œβ”€β”€ storage/
β”‚   β”œβ”€β”€ base.py          # Storage protocol
β”‚   β”œβ”€β”€ sqlite.py        # SQLite implementation
β”‚   └── jsonl.py         # JSON Lines implementation
β”‚
β”œβ”€β”€ proxy/
β”‚   └── server.py        # Production HTTP proxy (CCR endpoints)
β”‚
└── reporting/
    └── generator.py     # HTML report generation
```

---

## Key Design Decisions

### 1. Provider-Agnostic
Works with ANY OpenAI-compatible API:
- OpenAI
- Azure OpenAI
- Anthropic
- Groq
- Together
- Local models (Ollama)

### 2. Deterministic Transforms
No LLM calls for compression. Everything is:
- Statistical analysis
- Pattern matching
- Rule-based

This means:
- Predictable results
- Fast (<10ms overhead)
- No added API costs

### 3. Safety First
- Never modify user/assistant TEXT content
- Tool call + response are atomic (drop both or neither)
- Parse failures = no-op (return unchanged)
- Audit mode for testing before optimizing

### 4. Smart by Default
- SmartCrusher enabled (statistical analysis)
- ToolCrusher disabled (naive rules)
- Conservative settings that preserve important data

---

## What Makes This Different?

### vs. Summarization (LLM-based compression)
| Headroom | Summarization |
|----------|---------------|
| Deterministic | Non-deterministic |
| ~10ms overhead | ~2-5 seconds overhead |
| No extra API cost | Costs money to summarize |
| Preserves structure | Loses structure |
| Can't hallucinate | Can hallucinate |

### vs. Simple Truncation
| Headroom | Truncation |
|----------|------------|
| Keeps important data | Loses end of data |
| Statistical analysis | No analysis |
| Detects spikes | Misses spikes |
| Factors out constants | Keeps redundancy |

---

## The Numbers (From Our Tests)

Real-world SRE incident investigation:
- **5 tool calls**: Metrics, logs, status, deployments, runbook
- **Original**: 22,048 tokens
- **After SmartCrusher**: 2,190 tokens
- **Reduction**: 90%
- **Quality Score**: 5.0/5 (no information loss)

The model could still:
- Identify the CPU spike (preserved by change point detection)
- Reference specific error rates (kept in compressed data)
- Provide correct remediation commands

---

## Summary

**Headroom is a Context Budget Controller that:**

1. **Wraps** your existing LLM client
2. **Analyzes** your messages to find waste
3. **Compresses** tool outputs intelligently (not blindly)
4. **Preserves** important information (spikes, anomalies, unique data)
5. **Logs** everything for observability
6. **Saves** 70-90% of tokens on tool-heavy workloads

**The key insight:** Most tool output redundancy is **statistical** (repeated values, constant fields, similar messages). By analyzing the data first, we can compress intelligently without losing the information that matters.