runlens 0.1.0__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.
- runlens-0.1.0/LICENSE +21 -0
- runlens-0.1.0/PKG-INFO +273 -0
- runlens-0.1.0/README.md +245 -0
- runlens-0.1.0/agentlens.py +1217 -0
- runlens-0.1.0/agentlens_engine/__init__.py +1 -0
- runlens-0.1.0/agentlens_engine/classifier.py +461 -0
- runlens-0.1.0/agentlens_engine/clustering.py +251 -0
- runlens-0.1.0/agentlens_engine/diagnose.py +132 -0
- runlens-0.1.0/agentlens_engine/evaluate.py +184 -0
- runlens-0.1.0/agentlens_engine/fixes.py +75 -0
- runlens-0.1.0/agentlens_engine/hallucination.py +300 -0
- runlens-0.1.0/agentlens_engine/preprocess.py +189 -0
- runlens-0.1.0/agentlens_engine/similarity.py +309 -0
- runlens-0.1.0/agentlens_engine/timeline.py +306 -0
- runlens-0.1.0/agentlens_sdk/__init__.py +31 -0
- runlens-0.1.0/agentlens_sdk/collector.py +1062 -0
- runlens-0.1.0/agentlens_sdk/langgraph.py +210 -0
- runlens-0.1.0/agentlens_sdk/pricing.py +60 -0
- runlens-0.1.0/pyproject.toml +44 -0
- runlens-0.1.0/runlens.egg-info/PKG-INFO +273 -0
- runlens-0.1.0/runlens.egg-info/SOURCES.txt +25 -0
- runlens-0.1.0/runlens.egg-info/dependency_links.txt +1 -0
- runlens-0.1.0/runlens.egg-info/entry_points.txt +2 -0
- runlens-0.1.0/runlens.egg-info/requires.txt +6 -0
- runlens-0.1.0/runlens.egg-info/top_level.txt +3 -0
- runlens-0.1.0/setup.cfg +4 -0
- runlens-0.1.0/tests/test_beta_safety.py +111 -0
runlens-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AgentLens
|
|
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.
|
runlens-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: runlens
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: When your AI agent breaks, AgentLens tells you exactly which decision caused it — and what to change.
|
|
5
|
+
Author-email: AgentLens <hello@agentlens.run>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://agentlens.run
|
|
8
|
+
Project-URL: Repository, https://github.com/abishekgiri/agentlens
|
|
9
|
+
Project-URL: Documentation, https://github.com/abishekgiri/agentlens#readme
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/abishekgiri/agentlens/issues
|
|
11
|
+
Keywords: ai,agents,observability,debugging,llm,tracing,anthropic,openai,langgraph
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Provides-Extra: anthropic
|
|
25
|
+
Requires-Dist: anthropic>=0.40.0; extra == "anthropic"
|
|
26
|
+
Provides-Extra: openai
|
|
27
|
+
Requires-Dist: openai>=1.0.0; extra == "openai"
|
|
28
|
+
|
|
29
|
+
# AgentLens
|
|
30
|
+
|
|
31
|
+
**[agentlens.run](https://agentlens.run) · [GitHub](https://github.com/abishekgiri/agentlens)**
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
**When your AI agent breaks, AgentLens tells you exactly which decision caused it — and what to change.**
|
|
36
|
+
|
|
37
|
+
Not logs. Not traces. The answer.
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
ROOT CAUSE: tool_selection
|
|
41
|
+
FAILED AT: Step 2 (search_web)
|
|
42
|
+
WHY: Both tools had identical descriptions — the agent treated them as
|
|
43
|
+
interchangeable and picked the wrong one.
|
|
44
|
+
FIX: Rewrite tool descriptions so search_web is clearly for external
|
|
45
|
+
lookup and query_db is clearly for local records.
|
|
46
|
+
CONFIDENCE: 0.90
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Works with **Anthropic · OpenAI · LangGraph · CrewAI · AutoGen · PydanticAI · raw API**
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install agentlens-ai
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or from source:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git clone https://github.com/abishekgiri/agentlens.git
|
|
63
|
+
cd agentlens
|
|
64
|
+
pip install -e ".[anthropic,openai]"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quickstart — 2 lines
|
|
70
|
+
|
|
71
|
+
Add AgentLens before your existing provider client. No other changes.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import agentlens
|
|
75
|
+
agentlens.init() # patches Anthropic + OpenAI automatically
|
|
76
|
+
|
|
77
|
+
import anthropic
|
|
78
|
+
client = anthropic.Anthropic() # captured from here on
|
|
79
|
+
|
|
80
|
+
@agentlens.run(name="my_agent") # groups everything into one run
|
|
81
|
+
def run_agent(query):
|
|
82
|
+
response = client.messages.create(
|
|
83
|
+
model="claude-3-5-sonnet-latest",
|
|
84
|
+
max_tokens=512,
|
|
85
|
+
messages=[{"role": "user", "content": query}]
|
|
86
|
+
)
|
|
87
|
+
return response
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Async agents work exactly the same — `agentlens.init()` patches `AsyncAnthropic` and `AsyncOpenAI` too.
|
|
91
|
+
|
|
92
|
+
Run your agent, then:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
agentlens runs list
|
|
96
|
+
agentlens diagnose <run_id>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Framework examples
|
|
102
|
+
|
|
103
|
+
**LangGraph**
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import agentlens
|
|
107
|
+
agentlens.init()
|
|
108
|
+
agentlens.patch_langgraph() # call before graph.compile()
|
|
109
|
+
|
|
110
|
+
from langgraph.graph import StateGraph
|
|
111
|
+
|
|
112
|
+
graph = StateGraph(MyState)
|
|
113
|
+
graph.add_node("planner", planner_fn)
|
|
114
|
+
graph.add_node("executor", executor_fn)
|
|
115
|
+
app = graph.compile() # automatically wrapped — all nodes traced
|
|
116
|
+
|
|
117
|
+
@agentlens.run(name="langgraph_agent")
|
|
118
|
+
async def run(input):
|
|
119
|
+
return await app.ainvoke({"messages": input})
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**OpenAI async**
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
import agentlens
|
|
126
|
+
agentlens.init()
|
|
127
|
+
|
|
128
|
+
from openai import AsyncOpenAI
|
|
129
|
+
client = AsyncOpenAI() # captured automatically
|
|
130
|
+
|
|
131
|
+
@agentlens.run(name="openai_agent")
|
|
132
|
+
async def run_agent(query):
|
|
133
|
+
response = await client.chat.completions.create(
|
|
134
|
+
model="gpt-4o-mini",
|
|
135
|
+
messages=[{"role": "user", "content": query}],
|
|
136
|
+
tools=[],
|
|
137
|
+
)
|
|
138
|
+
return response
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Multi-agent tracing**
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
# Parent agent
|
|
145
|
+
ctx = agentlens.get_trace_context()
|
|
146
|
+
|
|
147
|
+
# Child agent (different process / service)
|
|
148
|
+
agentlens.init(parent_context=ctx) # stitches child trace into parent
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## What AgentLens catches
|
|
154
|
+
|
|
155
|
+
Six failure categories, detected automatically:
|
|
156
|
+
|
|
157
|
+
| Category | What it means |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `tool_selection` | Agent picked the wrong tool — usually because descriptions were too similar |
|
|
160
|
+
| `loop` | Agent repeated the same tool call with the same inputs without exit |
|
|
161
|
+
| `cascade` | A tool returned bad/stale data and a downstream step used it and failed |
|
|
162
|
+
| `context_pollution` | Contradictory instructions in the prompt diluted the agent's goal |
|
|
163
|
+
| `state_drift` | Agent abandoned its original goal mid-run |
|
|
164
|
+
| `overflow` | Critical context was pushed out of the context window before the key decision |
|
|
165
|
+
|
|
166
|
+
Plus **hallucination detection** — invented tool parameters, missing required fields, LLM output that contradicts what the tool actually returned.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## CLI reference
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Runs
|
|
174
|
+
agentlens runs list # all recent runs with status + span count
|
|
175
|
+
agentlens runs show <run_id> # full span detail for one run
|
|
176
|
+
agentlens runs view <run_id> # open visual timeline in browser
|
|
177
|
+
agentlens runs prompt <run_id> # print exact LLM prompts sent at each step
|
|
178
|
+
agentlens runs prompt <run_id> --step 2 # prompt for a specific LLM call only
|
|
179
|
+
agentlens runs replay <run_id> # interactive step-by-step playback (ENTER to advance)
|
|
180
|
+
agentlens runs stitch <run_id> # show multi-agent trace tree rooted at this run
|
|
181
|
+
|
|
182
|
+
# Diagnosis
|
|
183
|
+
agentlens diagnose <run_id> # root cause analysis + hallucination report
|
|
184
|
+
agentlens similar <run_id> # find historically similar failures
|
|
185
|
+
agentlens similar <run_id> --top 10 # top-N matches
|
|
186
|
+
agentlens clusters # failure clusters across all runs + top fix
|
|
187
|
+
|
|
188
|
+
# Stats & cost
|
|
189
|
+
agentlens stats # token usage, latency, cost across all runs
|
|
190
|
+
agentlens stats <run_id> # per-run breakdown
|
|
191
|
+
|
|
192
|
+
# Utilities
|
|
193
|
+
agentlens anonymize <run_id> # redact secrets before sharing
|
|
194
|
+
agentlens feedback-template <run_id> # structured feedback form
|
|
195
|
+
agentlens evaluate # accuracy check against fixtures + real cases
|
|
196
|
+
agentlens doctor # system health check
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Real example output
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
AgentLens Diagnosis
|
|
205
|
+
===================
|
|
206
|
+
|
|
207
|
+
ROOT CAUSE:
|
|
208
|
+
cascade
|
|
209
|
+
|
|
210
|
+
FAILED AT:
|
|
211
|
+
Step 3 (get_user_profile)
|
|
212
|
+
|
|
213
|
+
WHY:
|
|
214
|
+
Step 3 produced bad or corrupted output that caused a failure at step 6.
|
|
215
|
+
get_user_profile returned {"email": null, "warning": "stale cache entry"}
|
|
216
|
+
and send_email downstream tried to use the null email field.
|
|
217
|
+
|
|
218
|
+
FIX:
|
|
219
|
+
Validate the output from 'get_user_profile' before using it downstream;
|
|
220
|
+
if it is stale, empty, or malformed, stop and recover instead of feeding
|
|
221
|
+
it into the next step.
|
|
222
|
+
|
|
223
|
+
SECONDARY:
|
|
224
|
+
None
|
|
225
|
+
|
|
226
|
+
CONFIDENCE: 0.90
|
|
227
|
+
|
|
228
|
+
HALLUCINATIONS DETECTED:
|
|
229
|
+
[HIGH] step 5 — invented param: 'send_email' was called with 'priority'
|
|
230
|
+
which is not in its schema. Valid params: ['to', 'body'].
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## How it works
|
|
236
|
+
|
|
237
|
+
`agentlens.init()` monkeypatches your provider clients at import time — no changes to existing code. Every LLM call, tool call, error, and memory snapshot is captured as a span and saved locally to `.agentlens/runs/<run_id>.json`.
|
|
238
|
+
|
|
239
|
+
`agentlens diagnose` runs the trace through a preprocessing pipeline, then either an LLM-powered classifier (if `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` is set) or a fast local heuristic fallback. The local fallback works offline with no API key required.
|
|
240
|
+
|
|
241
|
+
All data stays on your machine. No cloud. No signup. No account.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Add a real-world test case
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
real_world_cases/my-broken-agent/
|
|
249
|
+
├── trace.json # anonymized run from .agentlens/runs/
|
|
250
|
+
├── expected_diagnosis.json # {"root_cause_category": "loop", "failed_at_step": 4}
|
|
251
|
+
└── notes.md # what the agent was doing and what actually broke
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Run `agentlens evaluate` to score the diagnosis engine against your case.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## What this is not
|
|
259
|
+
|
|
260
|
+
No dashboard. No hosted API. No database. No billing. No auth.
|
|
261
|
+
|
|
262
|
+
This is a local developer tool. The goal: when your agent breaks, run one command and get the answer in under 30 seconds.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Feedback
|
|
267
|
+
|
|
268
|
+
If AgentLens finds (or misses) a real bug in your agent, we want to know.
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
agentlens anonymize <run_id> # redact secrets
|
|
272
|
+
agentlens feedback-template <run_id> # fill this in and send it
|
|
273
|
+
```
|
runlens-0.1.0/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# AgentLens
|
|
2
|
+
|
|
3
|
+
**[agentlens.run](https://agentlens.run) · [GitHub](https://github.com/abishekgiri/agentlens)**
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
**When your AI agent breaks, AgentLens tells you exactly which decision caused it — and what to change.**
|
|
8
|
+
|
|
9
|
+
Not logs. Not traces. The answer.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
ROOT CAUSE: tool_selection
|
|
13
|
+
FAILED AT: Step 2 (search_web)
|
|
14
|
+
WHY: Both tools had identical descriptions — the agent treated them as
|
|
15
|
+
interchangeable and picked the wrong one.
|
|
16
|
+
FIX: Rewrite tool descriptions so search_web is clearly for external
|
|
17
|
+
lookup and query_db is clearly for local records.
|
|
18
|
+
CONFIDENCE: 0.90
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Works with **Anthropic · OpenAI · LangGraph · CrewAI · AutoGen · PydanticAI · raw API**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install agentlens-ai
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or from source:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git clone https://github.com/abishekgiri/agentlens.git
|
|
35
|
+
cd agentlens
|
|
36
|
+
pip install -e ".[anthropic,openai]"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Quickstart — 2 lines
|
|
42
|
+
|
|
43
|
+
Add AgentLens before your existing provider client. No other changes.
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import agentlens
|
|
47
|
+
agentlens.init() # patches Anthropic + OpenAI automatically
|
|
48
|
+
|
|
49
|
+
import anthropic
|
|
50
|
+
client = anthropic.Anthropic() # captured from here on
|
|
51
|
+
|
|
52
|
+
@agentlens.run(name="my_agent") # groups everything into one run
|
|
53
|
+
def run_agent(query):
|
|
54
|
+
response = client.messages.create(
|
|
55
|
+
model="claude-3-5-sonnet-latest",
|
|
56
|
+
max_tokens=512,
|
|
57
|
+
messages=[{"role": "user", "content": query}]
|
|
58
|
+
)
|
|
59
|
+
return response
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Async agents work exactly the same — `agentlens.init()` patches `AsyncAnthropic` and `AsyncOpenAI` too.
|
|
63
|
+
|
|
64
|
+
Run your agent, then:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
agentlens runs list
|
|
68
|
+
agentlens diagnose <run_id>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Framework examples
|
|
74
|
+
|
|
75
|
+
**LangGraph**
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
import agentlens
|
|
79
|
+
agentlens.init()
|
|
80
|
+
agentlens.patch_langgraph() # call before graph.compile()
|
|
81
|
+
|
|
82
|
+
from langgraph.graph import StateGraph
|
|
83
|
+
|
|
84
|
+
graph = StateGraph(MyState)
|
|
85
|
+
graph.add_node("planner", planner_fn)
|
|
86
|
+
graph.add_node("executor", executor_fn)
|
|
87
|
+
app = graph.compile() # automatically wrapped — all nodes traced
|
|
88
|
+
|
|
89
|
+
@agentlens.run(name="langgraph_agent")
|
|
90
|
+
async def run(input):
|
|
91
|
+
return await app.ainvoke({"messages": input})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**OpenAI async**
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import agentlens
|
|
98
|
+
agentlens.init()
|
|
99
|
+
|
|
100
|
+
from openai import AsyncOpenAI
|
|
101
|
+
client = AsyncOpenAI() # captured automatically
|
|
102
|
+
|
|
103
|
+
@agentlens.run(name="openai_agent")
|
|
104
|
+
async def run_agent(query):
|
|
105
|
+
response = await client.chat.completions.create(
|
|
106
|
+
model="gpt-4o-mini",
|
|
107
|
+
messages=[{"role": "user", "content": query}],
|
|
108
|
+
tools=[],
|
|
109
|
+
)
|
|
110
|
+
return response
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Multi-agent tracing**
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
# Parent agent
|
|
117
|
+
ctx = agentlens.get_trace_context()
|
|
118
|
+
|
|
119
|
+
# Child agent (different process / service)
|
|
120
|
+
agentlens.init(parent_context=ctx) # stitches child trace into parent
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## What AgentLens catches
|
|
126
|
+
|
|
127
|
+
Six failure categories, detected automatically:
|
|
128
|
+
|
|
129
|
+
| Category | What it means |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `tool_selection` | Agent picked the wrong tool — usually because descriptions were too similar |
|
|
132
|
+
| `loop` | Agent repeated the same tool call with the same inputs without exit |
|
|
133
|
+
| `cascade` | A tool returned bad/stale data and a downstream step used it and failed |
|
|
134
|
+
| `context_pollution` | Contradictory instructions in the prompt diluted the agent's goal |
|
|
135
|
+
| `state_drift` | Agent abandoned its original goal mid-run |
|
|
136
|
+
| `overflow` | Critical context was pushed out of the context window before the key decision |
|
|
137
|
+
|
|
138
|
+
Plus **hallucination detection** — invented tool parameters, missing required fields, LLM output that contradicts what the tool actually returned.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## CLI reference
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Runs
|
|
146
|
+
agentlens runs list # all recent runs with status + span count
|
|
147
|
+
agentlens runs show <run_id> # full span detail for one run
|
|
148
|
+
agentlens runs view <run_id> # open visual timeline in browser
|
|
149
|
+
agentlens runs prompt <run_id> # print exact LLM prompts sent at each step
|
|
150
|
+
agentlens runs prompt <run_id> --step 2 # prompt for a specific LLM call only
|
|
151
|
+
agentlens runs replay <run_id> # interactive step-by-step playback (ENTER to advance)
|
|
152
|
+
agentlens runs stitch <run_id> # show multi-agent trace tree rooted at this run
|
|
153
|
+
|
|
154
|
+
# Diagnosis
|
|
155
|
+
agentlens diagnose <run_id> # root cause analysis + hallucination report
|
|
156
|
+
agentlens similar <run_id> # find historically similar failures
|
|
157
|
+
agentlens similar <run_id> --top 10 # top-N matches
|
|
158
|
+
agentlens clusters # failure clusters across all runs + top fix
|
|
159
|
+
|
|
160
|
+
# Stats & cost
|
|
161
|
+
agentlens stats # token usage, latency, cost across all runs
|
|
162
|
+
agentlens stats <run_id> # per-run breakdown
|
|
163
|
+
|
|
164
|
+
# Utilities
|
|
165
|
+
agentlens anonymize <run_id> # redact secrets before sharing
|
|
166
|
+
agentlens feedback-template <run_id> # structured feedback form
|
|
167
|
+
agentlens evaluate # accuracy check against fixtures + real cases
|
|
168
|
+
agentlens doctor # system health check
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Real example output
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
AgentLens Diagnosis
|
|
177
|
+
===================
|
|
178
|
+
|
|
179
|
+
ROOT CAUSE:
|
|
180
|
+
cascade
|
|
181
|
+
|
|
182
|
+
FAILED AT:
|
|
183
|
+
Step 3 (get_user_profile)
|
|
184
|
+
|
|
185
|
+
WHY:
|
|
186
|
+
Step 3 produced bad or corrupted output that caused a failure at step 6.
|
|
187
|
+
get_user_profile returned {"email": null, "warning": "stale cache entry"}
|
|
188
|
+
and send_email downstream tried to use the null email field.
|
|
189
|
+
|
|
190
|
+
FIX:
|
|
191
|
+
Validate the output from 'get_user_profile' before using it downstream;
|
|
192
|
+
if it is stale, empty, or malformed, stop and recover instead of feeding
|
|
193
|
+
it into the next step.
|
|
194
|
+
|
|
195
|
+
SECONDARY:
|
|
196
|
+
None
|
|
197
|
+
|
|
198
|
+
CONFIDENCE: 0.90
|
|
199
|
+
|
|
200
|
+
HALLUCINATIONS DETECTED:
|
|
201
|
+
[HIGH] step 5 — invented param: 'send_email' was called with 'priority'
|
|
202
|
+
which is not in its schema. Valid params: ['to', 'body'].
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## How it works
|
|
208
|
+
|
|
209
|
+
`agentlens.init()` monkeypatches your provider clients at import time — no changes to existing code. Every LLM call, tool call, error, and memory snapshot is captured as a span and saved locally to `.agentlens/runs/<run_id>.json`.
|
|
210
|
+
|
|
211
|
+
`agentlens diagnose` runs the trace through a preprocessing pipeline, then either an LLM-powered classifier (if `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` is set) or a fast local heuristic fallback. The local fallback works offline with no API key required.
|
|
212
|
+
|
|
213
|
+
All data stays on your machine. No cloud. No signup. No account.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Add a real-world test case
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
real_world_cases/my-broken-agent/
|
|
221
|
+
├── trace.json # anonymized run from .agentlens/runs/
|
|
222
|
+
├── expected_diagnosis.json # {"root_cause_category": "loop", "failed_at_step": 4}
|
|
223
|
+
└── notes.md # what the agent was doing and what actually broke
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Run `agentlens evaluate` to score the diagnosis engine against your case.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## What this is not
|
|
231
|
+
|
|
232
|
+
No dashboard. No hosted API. No database. No billing. No auth.
|
|
233
|
+
|
|
234
|
+
This is a local developer tool. The goal: when your agent breaks, run one command and get the answer in under 30 seconds.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Feedback
|
|
239
|
+
|
|
240
|
+
If AgentLens finds (or misses) a real bug in your agent, we want to know.
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
agentlens anonymize <run_id> # redact secrets
|
|
244
|
+
agentlens feedback-template <run_id> # fill this in and send it
|
|
245
|
+
```
|