An observation console for how agents talk to LLMs — intercepts OpenAI-compatible calls and visualizes context, tools, and tokens. Single-file deployment with mock / proxy / custom responses built in.
中文文档请见 README_zh.md
- Mock Mode: Accepts any OpenAI-format request and returns a valid response without calling a real LLM
- Proxy Mode: Forwards requests to a real OpenAI-compatible endpoint (OpenAI / DeepSeek / ARK, etc.) while recording both upstream and downstream content
- Custom Responses: Bind a custom response to a request hash; subsequent identical conversations return the response directly
- Visual Inspection Console: View request/response details in the browser with switchable Human and JSON views
- Provider Management: Save multiple proxy targets and switch between them at any time
- Token Statistics: Automatically extracts input/output/cache tokens and cache hit rate
- SQLite Persistence: All data (requests, config, custom responses) is stored in a single
agentlens.dbwith configurable retention - i18n: Switch between English and Chinese in the console
- Theme: Light / Dark / Auto theme switching
Visit the Releases page and download the executable for your platform:
| Platform | File |
|---|---|
| Windows | agentlens-windows-amd64.exe |
| Linux | agentlens-linux-amd64 |
| macOS (Intel) | agentlens-darwin-amd64 |
| macOS (Apple Silicon) | agentlens-darwin-arm64 |
Run directly after download — no runtime environment required.
# Build the frontend
cd web && npm install && npm run build && cd ..
# Build the backend (frontend assets are embedded into the binary)
go build -o agentlens.exe .
# Run
./agentlens.exe# Terminal 1: Start the Go backend (API + static files)
go run .
# Terminal 2: Start the frontend dev server with HMR (http://localhost:5173/admin/)
cd web && npm run devAfter starting:
| Entry | URL |
|---|---|
| OpenAI API | http://localhost:12010/v1 |
| Visual UI (production) | http://localhost:12010/admin/ |
| Visual UI (development) | http://localhost:5173/admin/ |
No configuration required. Just point your client to the mock service:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:12010/v1",
api_key="sk-anything", # any value
)
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Hello"}],
)Requests are recorded in the inspection console, and responses are generated automatically (echoing the user message; returns tool_calls when tools are present).
- Open
http://localhost:12010/admin/ - Click ⚙ Settings -> Provider Management -> Add Provider
- Name: e.g. DeepSeek
- Base URL: e.g.
https://api.deepseek.com/v1 - API Key: your real key
- Override Model: leave blank to keep original, or fill in a replacement model name
- After saving, click "Use"
- Switch the top mode selector to
proxy
Subsequent requests will be forwarded to the real LLM, and the inspection console displays both the client request and the LLM response.
- Click a request in the inspection console
- Click "Edit Custom Response"
- Modify the JSON response in the editor
- After saving, subsequent requests with the same hash will return this response directly
Each request detail contains the following sections — click the title to collapse/expand:
| Section | Default State | Collapsed Summary |
|---|---|---|
| Request Overview | Collapsed | Model · Source · Duration |
| Request Parameters | Collapsed | Parameter name list |
| Tools | Collapsed | Tool name list |
| Messages | Expanded | - |
| Forwarded Upstream Request | Collapsed | model |
| Upstream Response | Expanded | - |
| Response Returned to Client | Expanded | Response summary |
Each section has a "View JSON" button in the top-right corner to toggle between raw JSON and Human views.
Each message has a direction arrow on the left:
- ↑ Blue: Sent to the LLM (system / user / tool)
- ↓ Green: Returned by the LLM (assistant)
Click the message header to collapse it (the content area remains freely selectable and copyable); when collapsed, a content summary is displayed.
- List items: Each request shows duration (seconds when >500ms), input/output tokens, and cache hit rate
- Header stats: Cumulative input/output/cache tokens and overall hit rate across all requests
- Request overview: Expanded view shows full token breakdown and cache hit rate
- Wide screens: Sidebar occupies space normally
- Narrow screens (<768px): Auto-hidden; hovers out when the mouse approaches the left edge, or toggle with the ☰ button
All data is stored in a single SQLite database agentlens.db, generated automatically at runtime:
| Table | Contents |
|---|---|
requests |
Request records |
config |
Provider configs, mode, max records |
custom_responses |
Custom responses bound by request hash |
The retention count is configurable in ⚙ Settings -> General Settings (default 50 entries). Delete agentlens.db to reset all configurations and records.
├── main.go # Routing + embedded frontend + SPA fallback
├── store.go # Data model + SQLite persistence
├── handlers.go # Request handling + admin API
├── web/ # React frontend
│ ├── src/
│ │ ├── App.tsx # Main app
│ │ ├── components/ # Sidebar / Detail / SettingsModal / CustomEditor / JsonTree / Markdown / ErrorBoundary
│ │ ├── api.ts # API wrappers
│ │ ├── i18n.ts # Internationalization (en/cn)
│ │ ├── theme.ts # Theme switching (light/dark/auto)
│ │ ├── types.ts # Type definitions
│ │ └── utils.ts # Utility functions
│ ├── vite.config.ts # base: /admin/ + dev proxy
│ └── package.json
├── .github/workflows/
│ └── release-please.yml # Auto changelog + tag + multi-platform build
└── go.mod
The React build output is embedded into the binary via //go:embed, producing a single file after compilation.
The project uses release-please to manage versions and changelog automatically.
<type>: <description>
feat: New feature (triggers minor version bump)
fix: Bug fix (triggers patch version bump)
perf: Performance improvement
refactor: Code refactoring
ci: CI/CD changes
docs: Documentation
chore: Miscellaneous
1. Create a branch from main for development
git checkout main && git pull
git checkout -b feat/some-feature
2. Commit with conventional commits
git commit -m "feat: add some feature"
3. Create a PR to merge into main
4. release-please automatically creates a "Release PR" (with changelog)
- Multiple feat/fix commits accumulate in the same Release PR
- You can wait until all development is done before merging
5. Merge the Release PR -> auto-create tag -> release-please.yml auto-builds and publishes
No manual git tag or git push origin v* required.
| Workflow | Responsibility | Trigger |
|---|---|---|
release-please.yml |
Analyzes commits, updates CHANGELOG.md, creates Release PR; after merge, creates tag + Release and auto-builds multi-platform binaries for upload | Push to main |
Build platforms:
| Platform | Runner |
|---|---|
| Windows amd64 | windows-latest |
| Linux amd64 | ubuntu-latest |
| macOS Intel | macos-15-intel |
| macOS Apple Silicon | macos-latest |
Note: Before use, enable
Allow GitHub Actions to create and approve pull requestsin the GitHub repository's Settings -> Actions -> General -> Workflow permissions.
