tracetrim 0.3.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tracetrim-0.3.5/LICENSE +21 -0
- tracetrim-0.3.5/LICENSES.md +23 -0
- tracetrim-0.3.5/PKG-INFO +332 -0
- tracetrim-0.3.5/README.md +297 -0
- tracetrim-0.3.5/pyproject.toml +49 -0
- tracetrim-0.3.5/setup.cfg +4 -0
- tracetrim-0.3.5/src/tracetrim/__init__.py +7 -0
- tracetrim-0.3.5/src/tracetrim/about.py +23 -0
- tracetrim-0.3.5/src/tracetrim/auto.py +245 -0
- tracetrim-0.3.5/src/tracetrim/cli.py +271 -0
- tracetrim-0.3.5/src/tracetrim/measure.py +82 -0
- tracetrim-0.3.5/src/tracetrim/oauth.py +175 -0
- tracetrim-0.3.5/src/tracetrim/projection.py +133 -0
- tracetrim-0.3.5/src/tracetrim/proxy.py +513 -0
- tracetrim-0.3.5/src/tracetrim/report.py +671 -0
- tracetrim-0.3.5/src/tracetrim/runtime.py +65 -0
- tracetrim-0.3.5/src/tracetrim/structural.py +127 -0
- tracetrim-0.3.5/src/tracetrim/traces.py +133 -0
- tracetrim-0.3.5/src/tracetrim/usage.py +216 -0
- tracetrim-0.3.5/src/tracetrim.egg-info/PKG-INFO +332 -0
- tracetrim-0.3.5/src/tracetrim.egg-info/SOURCES.txt +34 -0
- tracetrim-0.3.5/src/tracetrim.egg-info/dependency_links.txt +1 -0
- tracetrim-0.3.5/src/tracetrim.egg-info/entry_points.txt +2 -0
- tracetrim-0.3.5/src/tracetrim.egg-info/requires.txt +13 -0
- tracetrim-0.3.5/src/tracetrim.egg-info/top_level.txt +1 -0
- tracetrim-0.3.5/tests/test_auto.py +71 -0
- tracetrim-0.3.5/tests/test_c4_audit.py +31 -0
- tracetrim-0.3.5/tests/test_core.py +106 -0
- tracetrim-0.3.5/tests/test_function_calling.py +73 -0
- tracetrim-0.3.5/tests/test_multi.py +88 -0
- tracetrim-0.3.5/tests/test_oauth.py +93 -0
- tracetrim-0.3.5/tests/test_proxy.py +73 -0
- tracetrim-0.3.5/tests/test_proxy_passthrough.py +52 -0
- tracetrim-0.3.5/tests/test_report.py +95 -0
- tracetrim-0.3.5/tests/test_safeguards.py +58 -0
- tracetrim-0.3.5/tests/test_structural.py +35 -0
tracetrim-0.3.5/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alessio Pomaro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Licence map
|
|
2
|
+
|
|
3
|
+
| Material | Path | Licence | Notes |
|
|
4
|
+
|---|---|---|---|
|
|
5
|
+
| Library and experiment code | `src/`, `experiments/`, `tests/` | MIT (`LICENSE`) | |
|
|
6
|
+
| Paper text, figures, documentation, protocol | `paper/`, `docs/`, `protocol.md`, README files | CC BY 4.0 | |
|
|
7
|
+
| Aggregate results | `results/` | CC BY 4.0 | counts and measures only, no third-party text |
|
|
8
|
+
| Traces of C3 (literature scan) | `dataset/traces/C3/` (Zenodo) | CC BY 4.0 for our part | tool outputs are OpenAlex records, CC0 |
|
|
9
|
+
| Traces of C4 and C5 (simulated) | `dataset/traces/C4`, `C5` (Zenodo) | CC BY 4.0 | payloads generated by our code |
|
|
10
|
+
| Derived records of C1 and C2 | `dataset/derived/` (Zenodo) | CC BY 4.0 | field paths and token counts only; DataForSEO results are not redistributed |
|
|
11
|
+
|
|
12
|
+
## Third-party materials used, not redistributed in this repository
|
|
13
|
+
|
|
14
|
+
| Material | Use | Terms |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| DataForSEO API (via its MCP server) | tools of C1 and C2 | DataForSEO Terms of Service (read 2026-11-04): aggregates and field names published; raw results not redistributed |
|
|
17
|
+
| OpenAlex API | tools of C3 | data CC0; used without an API key within the free allowance |
|
|
18
|
+
| Stripe OpenAPI description (`stripe/openapi`, commit b213739) | schemas of the C4 simulator | MIT; downloaded at build time, not vendored |
|
|
19
|
+
| GitHub REST API description (`github/rest-api-description`, commit 99b1432) | schemas of the C5 simulator | MIT; downloaded at build time, not vendored |
|
|
20
|
+
| Headroom (`headroom-ai`) | optional backend, token baseline | Apache-2.0; optional dependency, not vendored |
|
|
21
|
+
| TOON format | the library's own TOON-style encoder follows the public specification | specification by J. Schopplich; no code reused |
|
|
22
|
+
|
|
23
|
+
Tavily was not used: its Platform Terms (§3.2(x)) forbid disclosing performance analyses of the service.
|
tracetrim-0.3.5/PKG-INFO
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tracetrim
|
|
3
|
+
Version: 0.3.5
|
|
4
|
+
Summary: Learn which fields of tool outputs an agent visibly reuses, from its traces, and trim the rest.
|
|
5
|
+
Author: Alessio Pomaro
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://www.alessiopomaro.it/
|
|
8
|
+
Project-URL: Repository, https://github.com/alepom/tracetrim
|
|
9
|
+
Project-URL: Paper, https://doi.org/10.5281/zenodo.23953934
|
|
10
|
+
Project-URL: Software DOI, https://doi.org/10.5281/zenodo.23954125
|
|
11
|
+
Project-URL: Changelog, https://github.com/alepom/tracetrim/blob/master/CHANGELOG.md
|
|
12
|
+
Keywords: agents,mcp,llm,tool outputs,token,telemetry
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
License-File: LICENSES.md
|
|
25
|
+
Provides-Extra: measure
|
|
26
|
+
Requires-Dist: tiktoken>=0.7; extra == "measure"
|
|
27
|
+
Provides-Extra: test
|
|
28
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
29
|
+
Requires-Dist: tiktoken>=0.7; extra == "test"
|
|
30
|
+
Provides-Extra: proxy
|
|
31
|
+
Requires-Dist: mcp>=2.3; extra == "proxy"
|
|
32
|
+
Provides-Extra: headroom
|
|
33
|
+
Requires-Dist: headroom-ai>=0.39; extra == "headroom"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# tracetrim
|
|
37
|
+
|
|
38
|
+
**Agents read more than they visibly reuse.** tracetrim learns, from your agent's own traces, which
|
|
39
|
+
fields of each tool output the agent reuses in what it writes, and helps you remove the rest — with a
|
|
40
|
+
telemetry report you can read, a configuration you can review, and an MCP proxy that applies it
|
|
41
|
+
in front of any server without changing your agent.
|
|
42
|
+
|
|
43
|
+
It comes with a [study](https://doi.org/10.5281/zenodo.23953934), with protocols frozen before every run, of
|
|
44
|
+
where this works and where it fails. In short:
|
|
45
|
+
|
|
46
|
+
| | |
|
|
47
|
+
|---|---|
|
|
48
|
+
| Tool-output tokens removed on unseen runs (0.1) | real APIs: 63% and 70% (12% on the third agent); simulated: 69% and 77% |
|
|
49
|
+
| …of which re-serialising the JSON alone, removing nothing | up to 13% (real APIs), up to 17% (simulated) |
|
|
50
|
+
| Same conversations: tracetrim 0.1 / 0.2 / Headroom (stateless) / full minifier, no field removed | the same two real-API agents: 59–68% / 46–53% / 17–28% / 16–24%; simulated: 69–77% / 57–61% / 31–33% / 18–33% |
|
|
51
|
+
| Live runs with `expand`: billed input tokens | −56% (real API) and −32% (simulated); every run passed its gates; a later re-check found one unsupported volume among 180 reported keyword–volume pairs |
|
|
52
|
+
| Learning from tool calls only (what a gateway sees) | a used field missed in 49% of the held-out structured calls it trims (156/317, 3 agents on real APIs), against 4% with the answer |
|
|
53
|
+
| Where it fails | values the agent transforms, fields used only to reason, and — without an id field — agents **inventing** ids |
|
|
54
|
+
|
|
55
|
+
Version 0.2 keeps identifying fields and recognises transformed values by default. Version 0.3
|
|
56
|
+
adds an automatic mode: put one proxy in front of your MCP servers and it observes, learns and
|
|
57
|
+
trims on its own. Read the [paper](https://doi.org/10.5281/zenodo.23953934) before trimming
|
|
58
|
+
anything that matters.
|
|
59
|
+
|
|
60
|
+
## Install
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install "tracetrim[measure,proxy]"
|
|
64
|
+
pip install "tracetrim[headroom]" # + Headroom backend (experimental, heavy)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Python 3.10+. From GitHub: `pip install "tracetrim[measure,proxy] @ git+https://github.com/alepom/tracetrim"`.
|
|
68
|
+
From a clone: `pip install -e ".[measure,proxy,test]"`. To reproduce the
|
|
69
|
+
study's numbers, figures and analyses: `pip install -e ".[measure,proxy,test]"` is enough (they need no agent SDK);
|
|
70
|
+
to run new agent sessions, also `pip install -r requirements-study.txt` (the versions used, OpenAI SDK included).
|
|
71
|
+
|
|
72
|
+
## The short way: automatic mode
|
|
73
|
+
|
|
74
|
+
Your agent already uses one or more MCP servers. Copy their `mcpServers` block — the same JSON
|
|
75
|
+
Claude Desktop, Claude Code and Cursor use — into a file:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{"mcpServers": {
|
|
79
|
+
"billing": {"url": "https://billing.example/mcp", "headers": {"Authorization": "Bearer ${BILLING_TOKEN}"}},
|
|
80
|
+
"code": {"command": "python", "args": ["-m", "my_code_server"], "env": {"API_KEY": "${CODE_KEY}"}}}}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Start one tracetrim in front of all of them:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
tracetrim proxy --servers mcp.json --auto tracetrim-data/ # stdio, for local clients
|
|
87
|
+
export TRACETRIM_TOKEN=CHOOSE_A_SECRET # over HTTP: clients must send it
|
|
88
|
+
tracetrim proxy --servers mcp.json --auto tracetrim-data/ --http 8799
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
In the agent, **replace** those servers with tracetrim (one entry instead of N; keeping both would
|
|
92
|
+
show the agent two copies of every tool), and add one line to its instructions:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
Last step, required if the tool tracetrim_done is available: when your final answer is ready,
|
|
96
|
+
call tracetrim_done once with the complete answer, before you show it; then show the same answer.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The agent sees the same tools with the same names (prefixed with the server name only if two
|
|
100
|
+
servers share one), plus `expand` and `tracetrim_done`. Then use the agent as usual:
|
|
101
|
+
|
|
102
|
+
- **from the first run**, a telemetry report is kept up to date in `tracetrim-data/report.html`
|
|
103
|
+
(over HTTP also live at `/report?token=...`): which tools fill the context, which fields the agent
|
|
104
|
+
never uses, with suggestions;
|
|
105
|
+
- **during the first runs** (5 by default, `--min-runs`) nothing is changed: the proxy only observes.
|
|
106
|
+
`tracetrim_done` is how it sees the answer — in the study, learning from tool calls alone missed a
|
|
107
|
+
used field in 49% of held-out calls (three agents on real APIs), against 4% with the answer;
|
|
108
|
+
- **after that**, it applies the report's automatic actions on its own: the prudent projection, with
|
|
109
|
+
identifying fields kept, transformed values recognised and `expand` on. Everything else stays in the
|
|
110
|
+
report as a manual action for you to review;
|
|
111
|
+
- **it corrects itself**: a tool whose trimmed outputs the agent expands too often is no longer
|
|
112
|
+
trimmed, and the report says so. Runs without `tracetrim_done` count for telemetry, not for learning.
|
|
113
|
+
One agent at a time: calls that arrive together from several agents end up in the same run. Over MCP the
|
|
114
|
+
proxy cannot see the model's turns, so calls emitted together are compared by arrival order: a later call's
|
|
115
|
+
arguments can count as using an earlier sibling's output. In the study this changed no figure; where turns
|
|
116
|
+
matter, record them (`AutoTrim` takes `turn`, JSONL traces accept a `"turn"` field).
|
|
117
|
+
|
|
118
|
+
Everything lives in the work directory (traces, report, config, state), so learning survives restarts;
|
|
119
|
+
delete it to start again. In a check with a real agent on the billing case (5 runs, 3 to learn), the
|
|
120
|
+
tool outputs of the two runs after learning went from 33,492 to 18,725 tokens (−44%, fields asked back
|
|
121
|
+
included), the agent asked for a hidden field once in each, and all five tickets passed the keyword test in every
|
|
122
|
+
run: a check, not a measurement (`results/checks/auto_check_mcp.json`) — the measurements are in the
|
|
123
|
+
paper.
|
|
124
|
+
|
|
125
|
+
### Servers that need credentials
|
|
126
|
+
|
|
127
|
+
Two separate links, two separate credentials: **agent → tracetrim** is protected by the token you
|
|
128
|
+
choose, in `$TRACETRIM_TOKEN` (or `--token`, which other users of the machine can see in the process
|
|
129
|
+
list), only when tracetrim is reachable over HTTP; requests whose Host is not local or listed with
|
|
130
|
+
`--allowed-host` are refused. **tracetrim → your servers**
|
|
131
|
+
uses your servers' own credentials, which tracetrim holds and the agent no longer sees.
|
|
132
|
+
|
|
133
|
+
| how your server authenticates | in `mcp.json` |
|
|
134
|
+
|---|---|
|
|
135
|
+
| API key or bearer token in a header | `"headers": {"Authorization": "Bearer ${MY_TOKEN}"}` (any header name) |
|
|
136
|
+
| local server reading a key from the environment | `"env": {"API_KEY": "${MY_KEY}"}` |
|
|
137
|
+
| OAuth, with a browser login (as in Claude Code or Cursor) | just `"url"`: no headers needed |
|
|
138
|
+
|
|
139
|
+
`${VAR}` is read from the environment when the proxy starts, so keys stay out of the file. For
|
|
140
|
+
OAuth servers, log in once:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
tracetrim login --servers mcp.json # opens the login page of each OAuth server
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Discovery, client registration, PKCE and token renewal follow the MCP authorization spec (through
|
|
147
|
+
the MCP SDK); tokens are kept in `~/.config/tracetrim/oauth/`, readable only by you, and renewed on
|
|
148
|
+
their own, so the proxy never waits for a browser. `tracetrim logout --servers mcp.json` forgets them.
|
|
149
|
+
Not supported: a different identity per end user (the proxy uses one identity for everyone) and the
|
|
150
|
+
legacy SSE transport.
|
|
151
|
+
|
|
152
|
+
### Hosted agents (OpenAI Playground, Responses API)
|
|
153
|
+
|
|
154
|
+
There is no `mcpServers` file in the Playground: each MCP server is added in the UI (*Tools → Add →
|
|
155
|
+
MCP server*) with a URL and, if needed, a header. Write `mcp.json` from those same values — one
|
|
156
|
+
entry per server, URL and header as you typed them — and run tracetrim over HTTP where OpenAI can
|
|
157
|
+
reach it (a server of yours, or a tunnel such as ngrok):
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
export TRACETRIM_TOKEN=CHOOSE_A_SECRET
|
|
161
|
+
tracetrim proxy --servers mcp.json --auto tracetrim-data/ --http 8799 --allowed-host your-tunnel.example
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Then, in the Playground, switch off the servers tracetrim now stands in for and add one MCP server:
|
|
165
|
+
URL `https://your-tunnel.example/mcp`, header `Authorization: Bearer CHOOSE_A_SECRET`. The live
|
|
166
|
+
report is at `http://127.0.0.1:8799/report?token=CHOOSE_A_SECRET` on the machine running the proxy.
|
|
167
|
+
`docs/demo_playground.sh` does all of this for the demo.
|
|
168
|
+
|
|
169
|
+
### Function calling, without MCP
|
|
170
|
+
|
|
171
|
+
If your agent runs its own tools (function calling), there is no proxy to put in between: the
|
|
172
|
+
loop that runs the tools is yours, so tracetrim goes in there, in three places. No
|
|
173
|
+
`tracetrim_done` either: your code already has the final answer.
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from tracetrim.auto import AutoTrim
|
|
177
|
+
|
|
178
|
+
tt = AutoTrim("tracetrim-data/", min_runs=5)
|
|
179
|
+
tools = my_tools + [{"type": "function", **tt.expand_tool}] # 1. offer expand
|
|
180
|
+
|
|
181
|
+
# 2. in the loop, for every tool call the model makes
|
|
182
|
+
if call.name == "expand":
|
|
183
|
+
result = tt.expand(call.arguments)
|
|
184
|
+
else:
|
|
185
|
+
result = tt.output(call.name, call.arguments, run_my_tool(call.name, call.arguments))
|
|
186
|
+
|
|
187
|
+
# 3. when the run is over
|
|
188
|
+
tt.done(final_answer)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`tt.output` records the call and returns what the model should receive: the raw result during the
|
|
192
|
+
first runs, the trimmed one after. `tt.done` closes the run, updates the report
|
|
193
|
+
(`tt.report`, `tracetrim-data/report.html`) and, once `min_runs` runs exist, starts trimming; what
|
|
194
|
+
was learned survives restarts. The rules are those of the proxy's automatic mode. Arguments can be
|
|
195
|
+
a dict or the JSON string most SDKs hand you; `tt.expand_tool` is a name, a description and a JSON
|
|
196
|
+
schema, to adapt to your provider's tool format (`{"type": "function", ...}` for OpenAI, `name` /
|
|
197
|
+
`description` / `input_schema` for Anthropic).
|
|
198
|
+
|
|
199
|
+
Checked with a real agent on the billing case, function calling, 5 runs with 3 to learn: after learning,
|
|
200
|
+
tool outputs went from 33,862 to 18,947 tokens (−44%, fields asked back included), the agent asked for a
|
|
201
|
+
hidden field once, and all five tickets passed the keyword test in every run (a check, not a measurement:
|
|
202
|
+
`results/checks/auto_check_function.json`, from
|
|
203
|
+
`python -m experiments.auto_check --runs 5 --min-runs 3 --mode function`).
|
|
204
|
+
|
|
205
|
+
**Mind the work directory.** To learn, tracetrim keeps the full tool outputs of every run in
|
|
206
|
+
`tracetrim-data/traces/`. If your servers return confidential data, treat that directory as you
|
|
207
|
+
treat the data: local, not shared, not committed.
|
|
208
|
+
|
|
209
|
+
## Quickstart: five runs, one report, one config
|
|
210
|
+
|
|
211
|
+
The manual way, with a review step before anything is applied.
|
|
212
|
+
|
|
213
|
+
**1. Record a few runs with full tool outputs.** A trace is JSONL, one event per line:
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{"kind": "prompt", "text": "You are a billing support agent..."}
|
|
217
|
+
{"kind": "call", "tool": "stripe_list_charges", "arguments": {"customer": "cus_123"}, "output": "{\"object\": \"list\", ...}"}
|
|
218
|
+
{"kind": "message", "text": "{\"ticket\": [...]}"}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`output` is the raw text the tool returned; the last `message` is the agent's answer. The
|
|
222
|
+
answer matters: without it the learner cannot see what the agent used. An optional `"turn"` on
|
|
223
|
+
every event (the model turn that produced it; the prompt is `-1`) lets the learner tell calls
|
|
224
|
+
emitted together apart: their arguments were written before any of their outputs existed. OpenAI
|
|
225
|
+
Playground Python exports are also read directly (`.py`).
|
|
226
|
+
|
|
227
|
+
**2. Generate the report.** It changes nothing; it is useful on its own.
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
tracetrim report traces/*.jsonl -o report.html
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
You get `report.html` (bilingual EN/IT: which tools fill the context, which calls fail and with
|
|
234
|
+
which provider error, which fields the agent never uses, with suggestions), `report.json`, and a
|
|
235
|
+
runtime config with the projection it uses: `report.config.json`, `report.projection.json`.
|
|
236
|
+
|
|
237
|
+
**3. Review the config.** It is plain JSON: which tools are trimmed, with `expand` on. The
|
|
238
|
+
projection lists, per tool, the fields kept and the fields dropped. Remove a tool from the config,
|
|
239
|
+
or a field from the dropped list, if you know the task needs it.
|
|
240
|
+
|
|
241
|
+
**4. Apply it.**
|
|
242
|
+
|
|
243
|
+
In your own code:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
from tracetrim.runtime import Policy
|
|
247
|
+
policy = Policy.load("report.config.json")
|
|
248
|
+
tool_message = policy.apply(tool_name, raw_output)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`Policy.apply` only trims: it adds no `[trimmed]` line and there is no `expand` behind it. For the way
|
|
252
|
+
back, use `AutoTrim` (function calling, below) or the proxy.
|
|
253
|
+
|
|
254
|
+
Or in front of any MCP server, with no code change — locally (Claude Desktop, Claude Code,
|
|
255
|
+
Cursor):
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{"mcpServers": {"billing": {"command": "tracetrim", "args": [
|
|
259
|
+
"proxy", "--upstream-cmd", "python -m my_billing_server", "--config", "/path/report.config.json"]}}}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
or over HTTP, for hosted clients such as the OpenAI Playground:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
export TRACETRIM_TOKEN=CHOOSE_A_SECRET
|
|
266
|
+
tracetrim proxy --upstream-url https://mcp.example.com/mcp --header "Authorization=Bearer UPSTREAM_TOKEN" \
|
|
267
|
+
--config report.config.json --http 8799 --allowed-host your-tunnel.example
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
(`--header` puts the upstream credential in the process list; `--servers mcp.json` with `${VAR}` does not.)
|
|
271
|
+
|
|
272
|
+
The proxy exposes the same tools plus `expand`: every trimmed output ends with a line listing the
|
|
273
|
+
hidden fields, and the agent can fetch any of them back (`"*"` for all of them) while the proxy keeps the original:
|
|
274
|
+
the last 256 trimmed results; at most 25 groups are listed, the rest summarised. `--record traces/live.jsonl`
|
|
275
|
+
records calls and outputs for telemetry; it does not record the agent's answer, so a report learned from it misses
|
|
276
|
+
most of what the agent uses (the study's central finding). To learn while running, use `--auto`, which receives
|
|
277
|
+
the answer through `tracetrim_done`.
|
|
278
|
+
|
|
279
|
+
How it wraps another server: the proxy is an MCP *server* towards your agent and an MCP *client*
|
|
280
|
+
towards the upstream. At start it asks the upstream for its tools and publishes the same names and
|
|
281
|
+
input schemas as its own (plus `expand`); each call is forwarded unchanged, and only the result is
|
|
282
|
+
rewritten on its way back. One proxy can stand in front of several servers (`--servers`).
|
|
283
|
+
|
|
284
|
+
While it runs, the proxy prints one line per call on stderr — tokens from the tool, tokens to the
|
|
285
|
+
agent, hidden fields, `expand` requests and the session total (`--quiet` to silence it). Add
|
|
286
|
+
`--structural toon` or `--structural headroom` to re-encode outputs after the projection
|
|
287
|
+
(experimental; Headroom needs `tracetrim[headroom]`).
|
|
288
|
+
|
|
289
|
+
**5. Measure before you trust it.**
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
tracetrim measure traces/*.jsonl --per-tool
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Leave-one-out: each run is trimmed with a projection learned from the others; you see the tokens
|
|
296
|
+
removed and the *misses* (held-out calls in which a field the agent used would have been removed).
|
|
297
|
+
|
|
298
|
+
## What it does not do
|
|
299
|
+
|
|
300
|
+
- It does not learn from a proxy alone: learn offline from complete traces, apply anywhere.
|
|
301
|
+
- It does not see reasoning: a field read only to decide something looks unused. Identifiers and
|
|
302
|
+
titles are kept for this reason; other such fields need your review.
|
|
303
|
+
- It does not translate: a value the agent rewrites in another language (or form) that the
|
|
304
|
+
normalisers do not cover looks unused.
|
|
305
|
+
- Structural re-encoding (`"structural": "toon"` or `"headroom"` in the config) is optional and was
|
|
306
|
+
seen to change how a model resolves ambiguous data. Validate on your task first.
|
|
307
|
+
|
|
308
|
+
## Reproducing the study
|
|
309
|
+
|
|
310
|
+
`experiments/` contains the agent loop, the simulated MCP servers (Stripe- and GitHub-shaped,
|
|
311
|
+
generated from their public OpenAPI descriptions), the gates and thermometers, and every
|
|
312
|
+
analysis. `protocol.md` is the frozen protocol with all deviations. Every number of the paper is
|
|
313
|
+
generated by `python -m experiments.paper_numbers` from `results/`, and every chart by
|
|
314
|
+
`python -m experiments.paper_figures` from `results/` and the traces. Run them from the repository root
|
|
315
|
+
with `PYTHONPATH=src`. The traces are in the Zenodo dataset: unzip it at the root, and the scripts read
|
|
316
|
+
`dataset/traces/` (C3, C4 and C5; C1 and C2 are released as derived records only, since the search
|
|
317
|
+
data cannot be redistributed, so their analyses run where they were recorded and their results are in
|
|
318
|
+
`results/`; `python -m experiments.misses_from_derived` recomputes their misses from the records). The simulated
|
|
319
|
+
servers download their pinned OpenAPI descriptions on first use. Changes by version are in
|
|
320
|
+
[CHANGELOG.md](https://github.com/alepom/tracetrim/blob/master/CHANGELOG.md).
|
|
321
|
+
|
|
322
|
+
## Citation
|
|
323
|
+
|
|
324
|
+
Paper: Alessio Pomaro, *Agents Read More Than They Use: Learning Tool-Output Projections from Execution Traces,
|
|
325
|
+
and Where They Fail*, preprint, 2026. DOI [10.5281/zenodo.23953934](https://doi.org/10.5281/zenodo.23953934).
|
|
326
|
+
|
|
327
|
+
Software, protocols and dataset: DOI [10.5281/zenodo.23954125](https://doi.org/10.5281/zenodo.23954125).
|
|
328
|
+
See `CITATION.cff`.
|
|
329
|
+
|
|
330
|
+
## License
|
|
331
|
+
|
|
332
|
+
MIT for the code. Third-party materials and their terms: see `LICENSES.md`.
|