looplens 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.
Files changed (56) hide show
  1. looplens-0.1.0/.github/workflows/ci.yml +43 -0
  2. looplens-0.1.0/.github/workflows/release.yml +53 -0
  3. looplens-0.1.0/.gitignore +31 -0
  4. looplens-0.1.0/CLAUDE.md +65 -0
  5. looplens-0.1.0/LAUNCH.md +170 -0
  6. looplens-0.1.0/PKG-INFO +250 -0
  7. looplens-0.1.0/PRD.md +1736 -0
  8. looplens-0.1.0/README.md +224 -0
  9. looplens-0.1.0/ROADMAP.md +84 -0
  10. looplens-0.1.0/docs/media/looplens-live-loop-detection.gif +0 -0
  11. looplens-0.1.0/examples/handoff_bounce_agent.py +34 -0
  12. looplens-0.1.0/examples/looping_agent.py +31 -0
  13. looplens-0.1.0/examples/real_research_agent_openai.py +153 -0
  14. looplens-0.1.0/examples/retry_storm_agent.py +23 -0
  15. looplens-0.1.0/examples/simple_agent.py +16 -0
  16. looplens-0.1.0/looplens/__init__.py +17 -0
  17. looplens-0.1.0/looplens/cli.py +339 -0
  18. looplens-0.1.0/looplens/config.py +56 -0
  19. looplens-0.1.0/looplens/sdk.py +306 -0
  20. looplens-0.1.0/looplens/server/__init__.py +1 -0
  21. looplens-0.1.0/looplens/server/__main__.py +10 -0
  22. looplens-0.1.0/looplens/server/_ui/assets/index-D-EP9mOV.css +1 -0
  23. looplens-0.1.0/looplens/server/_ui/assets/index-Dpao4I-T.js +68 -0
  24. looplens-0.1.0/looplens/server/_ui/index.html +13 -0
  25. looplens-0.1.0/looplens/server/app.py +90 -0
  26. looplens-0.1.0/looplens/server/db.py +214 -0
  27. looplens-0.1.0/looplens/server/detectors.py +273 -0
  28. looplens-0.1.0/looplens/server/metrics.py +99 -0
  29. looplens-0.1.0/looplens/server/models.py +180 -0
  30. looplens-0.1.0/looplens/server/routes.py +151 -0
  31. looplens-0.1.0/looplens/server/websocket.py +72 -0
  32. looplens-0.1.0/pyproject.toml +53 -0
  33. looplens-0.1.0/tests/test_detectors.py +131 -0
  34. looplens-0.1.0/tests/test_sdk.py +111 -0
  35. looplens-0.1.0/tests/test_stream.py +72 -0
  36. looplens-0.1.0/traces/sample_run.jsonl +11 -0
  37. looplens-0.1.0/ui/README.md +25 -0
  38. looplens-0.1.0/ui/index.html +12 -0
  39. looplens-0.1.0/ui/package-lock.json +2722 -0
  40. looplens-0.1.0/ui/package.json +26 -0
  41. looplens-0.1.0/ui/postcss.config.js +6 -0
  42. looplens-0.1.0/ui/src/App.tsx +22 -0
  43. looplens-0.1.0/ui/src/api.ts +102 -0
  44. looplens-0.1.0/ui/src/components/EventDrawer.tsx +58 -0
  45. looplens-0.1.0/ui/src/components/MetricsBar.tsx +29 -0
  46. looplens-0.1.0/ui/src/components/Timeline.tsx +46 -0
  47. looplens-0.1.0/ui/src/components/WarningCard.tsx +23 -0
  48. looplens-0.1.0/ui/src/index.css +14 -0
  49. looplens-0.1.0/ui/src/lib.ts +58 -0
  50. looplens-0.1.0/ui/src/main.tsx +24 -0
  51. looplens-0.1.0/ui/src/pages/RunDetailPage.tsx +109 -0
  52. looplens-0.1.0/ui/src/pages/RunsPage.tsx +89 -0
  53. looplens-0.1.0/ui/tailwind.config.js +14 -0
  54. looplens-0.1.0/ui/tsconfig.json +20 -0
  55. looplens-0.1.0/ui/tsconfig.node.json +12 -0
  56. looplens-0.1.0/ui/vite.config.ts +22 -0
@@ -0,0 +1,43 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: pytest (py${{ matrix.python-version }})
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+ cache: pip
23
+ - name: Install (server + dev deps)
24
+ run: pip install -e ".[dev]"
25
+ - name: Run tests
26
+ run: pytest -q
27
+
28
+ ui-build:
29
+ name: UI build check
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ - uses: actions/setup-node@v4
34
+ with:
35
+ node-version: "20"
36
+ cache: npm
37
+ cache-dependency-path: ui/package-lock.json
38
+ - name: Install UI deps
39
+ run: npm --prefix ui ci
40
+ - name: Build UI bundle
41
+ run: npm --prefix ui run build
42
+ - name: Assert bundle was produced
43
+ run: test -f looplens/server/_ui/index.html
@@ -0,0 +1,53 @@
1
+ name: Release
2
+
3
+ # Publishes to PyPI when you push a version tag, e.g. `git tag v0.1.0 && git push --tags`.
4
+ # The UI is built first and force-included into the wheel (see pyproject `artifacts`),
5
+ # so the published package installs with zero Node.
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+
10
+ jobs:
11
+ build:
12
+ name: Build wheel + sdist
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: "20"
19
+ cache: npm
20
+ cache-dependency-path: ui/package-lock.json
21
+ - name: Build UI bundle into looplens/server/_ui
22
+ run: |
23
+ npm --prefix ui ci
24
+ npm --prefix ui run build
25
+ test -f looplens/server/_ui/index.html
26
+ - uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+ - name: Build distributions
30
+ run: |
31
+ python -m pip install --upgrade build
32
+ python -m build
33
+ - name: Verify the wheel bundles the UI
34
+ run: |
35
+ python -m zipfile -l dist/*.whl | grep -q "looplens/server/_ui/index.html"
36
+ - uses: actions/upload-artifact@v4
37
+ with:
38
+ name: dist
39
+ path: dist/
40
+
41
+ publish:
42
+ name: Publish to PyPI
43
+ needs: build
44
+ runs-on: ubuntu-latest
45
+ environment: pypi
46
+ permissions:
47
+ id-token: write # trusted publishing (OIDC) — no API token stored
48
+ steps:
49
+ - uses: actions/download-artifact@v4
50
+ with:
51
+ name: dist
52
+ path: dist/
53
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,31 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+ .env
11
+
12
+ # LoopLens local data
13
+ *.db
14
+ *.db-wal
15
+ *.db-shm
16
+ .looplens/
17
+ looplens.env
18
+ looplens-traces/
19
+
20
+ # Node / UI
21
+ node_modules/
22
+ ui/dist/
23
+ ui/.vite/
24
+ # Built dashboard bundled into the wheel (regenerated by `npm --prefix ui run build`)
25
+ looplens/server/_ui/
26
+
27
+ # Editor / OS
28
+ .vscode/
29
+ .idea/
30
+ .DS_Store
31
+ Thumbs.db
@@ -0,0 +1,65 @@
1
+ # CLAUDE.md
2
+
3
+ Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.
4
+
5
+ **Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
6
+
7
+ ## 1. Think Before Coding
8
+
9
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
10
+
11
+ Before implementing:
12
+ - State your assumptions explicitly. If uncertain, ask.
13
+ - If multiple interpretations exist, present them - don't pick silently.
14
+ - If a simpler approach exists, say so. Push back when warranted.
15
+ - If something is unclear, stop. Name what's confusing. Ask.
16
+
17
+ ## 2. Simplicity First
18
+
19
+ **Minimum code that solves the problem. Nothing speculative.**
20
+
21
+ - No features beyond what was asked.
22
+ - No abstractions for single-use code.
23
+ - No "flexibility" or "configurability" that wasn't requested.
24
+ - No error handling for impossible scenarios.
25
+ - If you write 200 lines and it could be 50, rewrite it.
26
+
27
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
28
+
29
+ ## 3. Surgical Changes
30
+
31
+ **Touch only what you must. Clean up only your own mess.**
32
+
33
+ When editing existing code:
34
+ - Don't "improve" adjacent code, comments, or formatting.
35
+ - Don't refactor things that aren't broken.
36
+ - Match existing style, even if you'd do it differently.
37
+ - If you notice unrelated dead code, mention it - don't delete it.
38
+
39
+ When your changes create orphans:
40
+ - Remove imports/variables/functions that YOUR changes made unused.
41
+ - Don't remove pre-existing dead code unless asked.
42
+
43
+ The test: Every changed line should trace directly to the user's request.
44
+
45
+ ## 4. Goal-Driven Execution
46
+
47
+ **Define success criteria. Loop until verified.**
48
+
49
+ Transform tasks into verifiable goals:
50
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
51
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
52
+ - "Refactor X" → "Ensure tests pass before and after"
53
+
54
+ For multi-step tasks, state a brief plan:
55
+ ```
56
+ 1. [Step] → verify: [check]
57
+ 2. [Step] → verify: [check]
58
+ 3. [Step] → verify: [check]
59
+ ```
60
+
61
+ Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
62
+
63
+ ---
64
+
65
+ **These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
@@ -0,0 +1,170 @@
1
+ # LoopLens — Launch Assets
2
+
3
+ Copy-paste launch posts for each channel. Replace `REPO_URL` with the GitHub
4
+ link and attach the demo GIF where noted.
5
+
6
+ ---
7
+
8
+ ## One-liner
9
+
10
+ > LoopLens — Chrome DevTools for AI agent loops. See your agent run live and get
11
+ > warned the moment it repeats itself, retries blindly, or stops making progress.
12
+
13
+ ## The hook (problem → product)
14
+
15
+ Your agent "works." The terminal scrolls. It looks busy. Then it burns 5 LLM
16
+ calls searching the same thing 5 times and gives up — and you only find out from
17
+ the final error. LoopLens makes the loop visible *while it runs* and tells you,
18
+ in plain language, that the agent is stuck and where.
19
+
20
+ ---
21
+
22
+ ## GitHub release notes (v0.1.0)
23
+
24
+ **LoopLens v0.1.0 — local-first loop debugger for AI agents.**
25
+
26
+ - 🪄 **Zero-friction install:** `pip install "looplens[server]"` — no Node, no
27
+ build step; the dashboard is bundled in the wheel.
28
+ - 🧩 **Zero-dependency SDK:** pure-stdlib `trace()` / `event()` / `@observe`.
29
+ Drops into LangGraph, CrewAI, OpenAI Agents SDK, or a plain `while` loop
30
+ without pinning anything or touching your agent's deps.
31
+ - 📺 **Live timeline** over SSE: LLM calls, tool calls, retries, handoffs, state.
32
+ - 🚨 **Six transparent loop detectors:** repeated tool call, similar-input
33
+ repeat, no-progress loop, retry storm, long-running step, cost spike.
34
+ - 🩺 **Health score** (0–100 → Healthy / Warning / Likely stuck / Failed).
35
+ - 💾 **Local-first:** SQLite, no auth, no cloud, no API key. JSONL import/export.
36
+ - 🛟 **Fail-silent:** if the dashboard is down, the SDK buffers to JSONL and
37
+ never crashes your agent.
38
+
39
+ ```bash
40
+ pip install "looplens[server]"
41
+ looplens dev
42
+ looplens demo # watch it trip a loop warning live
43
+ ```
44
+
45
+ MIT. Feedback and framework-adapter requests welcome.
46
+
47
+ ---
48
+
49
+ ## Hacker News (Show HN)
50
+
51
+ **Title:** Show HN: LoopLens – a local-first loop debugger for AI agents
52
+
53
+ **Body:**
54
+
55
+ I kept shipping agents that *looked* like they were working — the logs scrolled,
56
+ tools fired — but they were quietly stuck calling the same tool over and over,
57
+ burning tokens, and failing at the end. Generic tracing tools show me spans;
58
+ they don't tell me the loop is unhealthy.
59
+
60
+ LoopLens is a small local tool focused on exactly that. You add a tiny zero-dep
61
+ SDK to the agent you already have, run a local dashboard, and watch the loop live.
62
+ It raises rule-based warnings — repeated tool call, no-progress loop, retry
63
+ storm, cost spike — with a plain-English "what happened / why it matters / where /
64
+ how to fix."
65
+
66
+ It's deliberately *not* another observability platform: no auth, no cloud, no
67
+ eval datasets, no graph-first UI. Just timeline + warnings + metrics, local-first.
68
+
69
+ The detectors are transparent rules (no black-box scoring), the SDK is pure
70
+ stdlib so it won't fight your agent's dependencies, and the `[server]` install
71
+ ships the prebuilt UI so there's no Node/npm step.
72
+
73
+ ```bash
74
+ pip install "looplens[server]" && looplens dev && looplens demo
75
+ ```
76
+
77
+ Repo: REPO_URL — would love feedback, especially on which framework adapter
78
+ (LangGraph / CrewAI / OpenAI Agents SDK) to build first.
79
+
80
+ ---
81
+
82
+ ## X / Twitter (thread)
83
+
84
+ 1/ Your agent isn't "thinking." It's calling `search_docs("refund policy")` for
85
+ the 5th time and about to give up. You'll find out from the final error.
86
+
87
+ I built **LoopLens** to make that visible *while it runs.* 🧵
88
+
89
+ 2/ It's Chrome DevTools, but for agent loops. Add a tiny zero-dep SDK, open a
90
+ local dashboard, watch every LLM call / tool call / retry stream in live.
91
+
92
+ 3/ The point isn't logs — it's *opinions*. LoopLens warns you:
93
+ • repeated tool call
94
+ • no-progress loop
95
+ • retry storm
96
+ • cost spike
97
+ …each with what happened, why, where, and how to fix.
98
+
99
+ 4/ Local-first: SQLite, no auth, no cloud, no API key. The SDK is pure stdlib so
100
+ it won't conflict with LangGraph / CrewAI / OpenAI Agents SDK / your custom loop.
101
+ If the dashboard's down it buffers to JSONL and never crashes your agent.
102
+
103
+ 5/ Install is one line — the dashboard ships prebuilt, no Node:
104
+ `pip install "looplens[server]" && looplens dev && looplens demo`
105
+ [attach GIF]
106
+ Repo + roadmap 👇 REPO_URL
107
+
108
+ ---
109
+
110
+ ## LinkedIn
111
+
112
+ Agent development is becoming **loop engineering**. Agents don't answer once —
113
+ they plan, call tools, retry, hand off, and loop until success or budget runs
114
+ out. When that loop goes wrong, it's mostly invisible: the logs look busy while
115
+ the agent repeats itself and burns tokens.
116
+
117
+ I built **LoopLens** — a local-first, real-time debugger focused purely on loop
118
+ health. Add a zero-dependency Python SDK to the agent you already have, open a
119
+ local dashboard, and watch the run live. It raises transparent, rule-based
120
+ warnings — repeated tool call, no-progress loop, retry storm, cost spike — each
121
+ with a plain-English explanation and a suggested fix.
122
+
123
+ It's intentionally narrow: not another observability platform — no auth, no
124
+ cloud, no eval suite. Just the fastest way to see *why your agent got stuck.*
125
+
126
+ ```
127
+ pip install "looplens[server]"
128
+ looplens dev
129
+ looplens demo
130
+ ```
131
+
132
+ Open-source (MIT). Roadmap includes LangGraph / CrewAI / OpenAI Agents SDK
133
+ adapters — feedback on ordering welcome. REPO_URL
134
+
135
+ ---
136
+
137
+ ## Reddit (r/LangChain, r/AI_Agents, r/LocalLLaMA)
138
+
139
+ **Title:** I built a local-first "loop debugger" for AI agents — see why it got
140
+ stuck, live
141
+
142
+ Sharing a tool I built to scratch my own itch. My agents kept looking busy while
143
+ secretly repeating the same tool call and failing at the end. LoopLens shows the
144
+ loop live and warns you the moment it detects repeated calls, no-progress loops,
145
+ retry storms, or cost spikes — in plain language, with a suggested fix.
146
+
147
+ - zero-dependency SDK (pure stdlib — drops into LangGraph/CrewAI/OpenAI Agents
148
+ SDK/custom loops without dependency conflicts)
149
+ - local-first: SQLite, no auth, no cloud, no API key
150
+ - one-line install, dashboard bundled (no Node build step)
151
+ - fail-silent: buffers to JSONL if the dashboard's down, never crashes your agent
152
+
153
+ ```bash
154
+ pip install "looplens[server]" && looplens dev && looplens demo
155
+ ```
156
+
157
+ It's an MVP and deliberately narrow (loop health, not full observability).
158
+ Repo + roadmap: REPO_URL. What framework adapter should I build first?
159
+
160
+ ---
161
+
162
+ ## Demo script (for the GIF / video — ~30s)
163
+
164
+ 1. Split screen: terminal (left) running `looplens demo`, dashboard (right).
165
+ 2. Watch the timeline fill: `agent_started` → `llm_call` → `tool_call` repeating.
166
+ 3. By the 3rd `web_search`, a **warning card** appears: *"Same tool called
167
+ repeatedly with similar input — possible no-progress loop."*
168
+ 4. Health score ticks down from 100 → "Likely stuck."
169
+ 5. Click an event → drawer shows the raw JSON (identical inputs each call).
170
+ 6. End card: `pip install "looplens[server]"` + repo URL.
@@ -0,0 +1,250 @@
1
+ Metadata-Version: 2.4
2
+ Name: looplens
3
+ Version: 0.1.0
4
+ Summary: Local-first real-time debugger for AI agent loops — Chrome DevTools for agent loops.
5
+ Project-URL: Homepage, https://github.com/ashutosh-rath02/looplens
6
+ Project-URL: Repository, https://github.com/ashutosh-rath02/looplens
7
+ Author: Ashutosh Rath
8
+ License: MIT
9
+ Keywords: agents,ai,debugging,llm,loops,observability
10
+ Requires-Python: >=3.10
11
+ Provides-Extra: dev
12
+ Requires-Dist: fastapi>=0.110; extra == 'dev'
13
+ Requires-Dist: httpx>=0.27; extra == 'dev'
14
+ Requires-Dist: pydantic>=2.0; extra == 'dev'
15
+ Requires-Dist: pytest>=7.0; extra == 'dev'
16
+ Requires-Dist: typer>=0.9; extra == 'dev'
17
+ Requires-Dist: uvicorn[standard]>=0.27; extra == 'dev'
18
+ Requires-Dist: watchdog>=3.0; extra == 'dev'
19
+ Provides-Extra: server
20
+ Requires-Dist: fastapi>=0.110; extra == 'server'
21
+ Requires-Dist: pydantic>=2.0; extra == 'server'
22
+ Requires-Dist: typer>=0.9; extra == 'server'
23
+ Requires-Dist: uvicorn[standard]>=0.27; extra == 'server'
24
+ Requires-Dist: watchdog>=3.0; extra == 'server'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # LoopLens
28
+
29
+ [![CI](https://github.com/ashutosh-rath02/looplens/actions/workflows/ci.yml/badge.svg)](https://github.com/ashutosh-rath02/looplens/actions/workflows/ci.yml)
30
+
31
+ **Chrome DevTools for AI agent loops.** A local-first, real-time debugger that
32
+ shows your agent's execution live and warns when it repeats itself, burns
33
+ tokens, retries blindly, or stops making progress.
34
+
35
+ LoopLens gives you:
36
+
37
+ - live timeline of agent execution
38
+ - LLM-call and tool-call visibility
39
+ - retry and handoff tracking
40
+ - token and cost metrics
41
+ - loop warnings (repeated tool, no-progress, retry storm, cost spike, …)
42
+ - JSONL import/export
43
+ - a local-first UI — no login, no cloud, no API key
44
+
45
+ ## See it in action
46
+
47
+ A looping agent calls `web_search` over and over. As events stream in live, the
48
+ metrics climb and LoopLens flags **Repeated tool call** and **No-progress loop**
49
+ — the warning counts track the repeat count in real time, and the health score
50
+ drops to *Warning*.
51
+
52
+ ![LoopLens detecting a loop live](docs/media/looplens-live-loop-detection.gif)
53
+
54
+ ## Drop it into any project
55
+
56
+ LoopLens is **not a standalone app you rebuild your agent inside**. It's a tiny
57
+ SDK you add to the agent you already have, plus a dashboard you open when you
58
+ want to look.
59
+
60
+ ```python
61
+ from looplens import trace, event
62
+
63
+ with trace("research-agent"):
64
+ event("tool_call_started", tool="web_search", input={"query": "AI agents"})
65
+ event("tool_call_completed", tool="web_search", output={"results": 5})
66
+ ```
67
+
68
+ Or wrap a function with `@observe` to capture inputs, outputs, latency, and
69
+ errors automatically:
70
+
71
+ ```python
72
+ from looplens import observe
73
+
74
+ @observe(kind="tool")
75
+ def web_search(query):
76
+ ...
77
+ ```
78
+
79
+ The base install is **pure-stdlib with zero third-party dependencies**, so it
80
+ won't conflict with anything in your agent's environment. Events are sent from a
81
+ background thread (your loop never blocks). If the dashboard is running, events
82
+ stream to it live; if not, the SDK buffers to a local JSONL file and **never
83
+ crashes your app**.
84
+
85
+ Configure via environment variables:
86
+
87
+ ```bash
88
+ LOOPLENS_ENDPOINT=http://127.0.0.1:8765 # where the dashboard listens
89
+ LOOPLENS_ENABLED=true # set false to make the SDK a no-op
90
+ LOOPLENS_PROJECT=default
91
+ LOOPLENS_CAPTURE_INPUTS=true
92
+ LOOPLENS_CAPTURE_OUTPUTS=true
93
+ LOOPLENS_TRACE_DIR=looplens-traces # JSONL fallback location
94
+ ```
95
+
96
+ ## Install
97
+
98
+ ```bash
99
+ pip install looplens # the SDK (drop into your agent — zero deps)
100
+ pip install "looplens[server]" # adds the dashboard (FastAPI + prebuilt UI)
101
+ ```
102
+
103
+ That's it — **no Node, no npm, no build step.** The `[server]` extra ships the
104
+ compiled React dashboard inside the wheel, so `looplens dev` serves a ready UI on
105
+ the first run. (`pipx install "looplens[server]"`, `uv pip install`, and
106
+ `uv tool install` work the same way.)
107
+
108
+ ### Works with any agent or framework
109
+
110
+ The base `looplens` SDK is **pure Python stdlib with zero third-party
111
+ dependencies**, so it installs cleanly next to any agent stack and pins nothing:
112
+
113
+ - **LangGraph / LangChain**, **CrewAI**, **AutoGen**, **OpenAI Agents SDK**,
114
+ **Pydantic AI**, or a hand-rolled `while` loop — if it's Python, you can
115
+ instrument it with `trace()` / `event()` / `@observe`.
116
+ - No API key, no login, no network egress — events go to `127.0.0.1` only, and
117
+ the SDK is a no-op when `LOOPLENS_ENABLED=false`.
118
+ - Fail-silent by design: if the dashboard isn't running it buffers to JSONL and
119
+ **never raises into your agent**.
120
+
121
+ ## Quickstart
122
+
123
+ ```bash
124
+ pip install "looplens[server]"
125
+ looplens dev # start backend + prebuilt UI, opens http://localhost:8765
126
+ looplens demo # run a sample looping agent that trips a warning
127
+ looplens doctor # check the port, SDK->server round-trip, and JSONL fallback
128
+ ```
129
+
130
+ `looplens dev` opens the dashboard in your browser automatically (pass
131
+ `--no-open` to skip). If it doesn't, open <http://localhost:8765> yourself and
132
+ watch the run appear live.
133
+
134
+ ## Architecture
135
+
136
+ ```
137
+ Your agent app ──(looplens SDK)──▶ Local FastAPI server ──▶ SQLite
138
+
139
+ └──(live stream)──▶ React UI
140
+ ```
141
+
142
+ - **SDK** (`looplens`): `trace()` + `event()`, background HTTP send, JSONL
143
+ fallback, fail-silent. Zero third-party deps.
144
+ - **Server** (`looplens[server]`): FastAPI + SQLite + Pydantic, loop detectors,
145
+ metrics, real-time stream.
146
+ - **UI**: React + Vite + TypeScript + Tailwind.
147
+
148
+ ## Examples
149
+
150
+ Runnable agents under `examples/` exercise the detectors. Start the dashboard
151
+ (`looplens dev`), then run any of them:
152
+
153
+ ```bash
154
+ python examples/simple_agent.py # a healthy run — no warnings
155
+ python examples/looping_agent.py # repeated tool call + no-progress loop
156
+ python examples/retry_storm_agent.py # retry storm
157
+ python examples/handoff_bounce_agent.py # two agents ping-ponging handoffs
158
+ ```
159
+
160
+ `looplens demo` runs the looping agent without needing the file checked out.
161
+
162
+ `examples/real_research_agent_openai.py` is a **real** agent — it makes live
163
+ OpenAI calls (function calling) against a tiny corpus that lacks the answer, so
164
+ the model genuinely loops. Needs `pip install openai` and `OPENAI_API_KEY`
165
+ (optionally `OPENAI_MODEL`):
166
+
167
+ ```bash
168
+ OPENAI_API_KEY=sk-... PYTHONPATH=. python examples/real_research_agent_openai.py
169
+ ```
170
+
171
+ ## Build status
172
+
173
+ This repo is being built phase by phase (see `PRD.md` section 24).
174
+
175
+ - [x] **Phase 0** — repo scaffold, packaging, config
176
+ - [x] **Phase 1** — FastAPI backend + SQLite + API routes + metrics
177
+ - [x] **Phase 2** — Python SDK (`trace` / `event` / `@observe`, background sender, JSONL fallback)
178
+ - [x] **Phase 3** — CLI (`init / server / ui / dev / watch / import / export / demo`)
179
+ - [x] **Phase 6** — loop detection rules (repeated tool, similar input, no-progress, retry storm, long step, cost spike)
180
+ - [x] **Phase 4** — React UI (runs list, run detail, live timeline, metrics bar, warnings, event drawer)
181
+ - [x] **Phase 5** — real-time streaming (SSE: live events + metrics + warnings)
182
+ - [x] **Phase 7** — polish, examples, demo
183
+
184
+ ## Running from source
185
+
186
+ The published wheel ships the prebuilt dashboard, so end users never touch Node.
187
+ Building **from a git checkout** is the only time you need npm — once, to compile
188
+ the UI into the Python package:
189
+
190
+ ```bash
191
+ pip install -e ".[server]" # backend + CLI
192
+ npm --prefix ui install # one-time UI deps
193
+ npm --prefix ui run build # compiles the React bundle into looplens/server/_ui/
194
+ python -m looplens.server # or: looplens server (serves API + UI)
195
+ looplens demo # seed a looping run that trips warnings
196
+ ```
197
+
198
+ Open `http://localhost:8765` for the dashboard. The backend serves the bundled UI,
199
+ so it's a single URL. For UI development with hot reload, run `npm --prefix ui run
200
+ dev` (Vite on :5173, proxies `/api` to the backend). Interactive API docs are at
201
+ `http://localhost:8765/docs`.
202
+
203
+ Packaging a release: run `npm --prefix ui run build` first, then `python -m build`
204
+ — the wheel force-includes `looplens/server/_ui/` so it's installable with zero
205
+ Node.
206
+
207
+ ## How loop detection works
208
+
209
+ Detection is **rule-based and transparent** (PRD §17) — no black-box scoring. On
210
+ every event the backend re-scans the run and raises (or updates) warnings:
211
+
212
+ | Warning | Fires when |
213
+ | --- | --- |
214
+ | `repeated_tool_call` | same tool ≥3× within the last 8 **tool calls** (window slides over tool calls, not raw events, so interleaved ReAct traces still trip it) |
215
+ | `repeated_tool_call_similar_input` | same tool ≥3× with ≥85% similar input |
216
+ | `repeated_tool_call_exact_input` | same tool ≥3× with **byte-identical** input — highest-confidence repeat signal |
217
+ | `no_progress` | a tool repeats with no `state_updated` / `memory_write` between calls |
218
+ | `retry_storm` | `retry_triggered` ≥3× in the run |
219
+ | `long_running_step` | a step over 30s |
220
+ | `cost_spike` | one event > 50% of run cost so far (above a $0.05 floor) |
221
+ | `handoff_bounce` | control ping-pongs between the same two agents (A→B→A→B) |
222
+
223
+ Each warning carries a health penalty; the run's score (0–100) maps to
224
+ **Healthy / Warning / Likely stuck / Failed**.
225
+
226
+ ## Limitations (MVP)
227
+
228
+ - **Manual instrumentation only.** Framework adapters (LangGraph, OpenAI Agents
229
+ SDK, CrewAI) are on the V1 roadmap; today you call `trace()`/`event()`/`@observe`.
230
+ - **Rule-based detection**, not semantic — similar-input uses string similarity,
231
+ not embeddings.
232
+ - **Near-real-time, not push**: the SSE stream polls SQLite every ~0.5s.
233
+ - **Single local user, no auth** — local-first by design, not a production service.
234
+
235
+ ## Tests
236
+
237
+ ```bash
238
+ pip install -e ".[dev]"
239
+ pytest -q # SDK resilience, all eight detectors, and the SSE stream
240
+ ```
241
+
242
+ ## Roadmap
243
+
244
+ See [`ROADMAP.md`](ROADMAP.md) for what's next — PyPI release, CI, and framework
245
+ adapters (LangGraph, OpenAI Agents SDK, CrewAI) to remove manual instrumentation.
246
+ Launch copy lives in [`LAUNCH.md`](LAUNCH.md).
247
+
248
+ ## License
249
+
250
+ MIT