See how your AI coding agent is actually behaving.
You just spent two hours with Claude Code. Did it work steadily toward the goal, or did it spend forty minutes re-editing the same file and re-running the same failing test? You can scroll back through the transcript to find out. Or you can run one command.
observatory import
The Observatory reads the session your agent already recorded on disk and answers one question:
Is my agent behaving well β and if not, why?
Everything runs on your machine. No account, no API key, nothing uploaded.
A local dashboard that shows what your agent did, how healthy the session was, and why.
And the same answer in your terminal, if you would rather not leave it:
AGENT HEALTH 65 / 100 stable (3/5 components measured)
BEHAVIORAL LEARNING 34 / 100 βΌ DEGRADING
DEGRADATION 27 / 100
Tokens 148M Actions 396 Errors 3 Recovery 33% Repetition 23%
WINDOW actions errors recovery repetition
early 132 1% 100% 16%
middle 132 1% 0% 25%
recent 132 1% 0% 22%
WHY THE AGENT IS DEGRADING
β Recovery rate decreased 100%
β Repetition increased 39%
β 1 retry with no change in between
SIGNALS
β apps/web/src/components/performance-chart.tsx ran 10 times
β apps/server/src/app.ts ran 8 times
That is a real session β the one that built this tool. It caught the author editing the same component ten times while fighting a rendering bug, and called the session degrading for it. Every number comes with the reason behind it; you should never see a score without an explanation.
You need Node.js 20.11 or newer. Nothing else.
npm install -g ai-agent-observatory
Prefer to build it yourself? Same result, one extra minute:
git clone https://github.com/MohammedNihal03/AI-observibility.git
cd AI-observibility
npm install && npm run package
npm install -g ./dist-package
The ./ matters: without it npm looks for a package by that name in the registry.
Start it:
observatory start
Observatory running on http://127.0.0.1:4000
Database C:\Users\you\.observatory\observatory.db
Dashboard http://127.0.0.1:4000
Open http://127.0.0.1:4000. It will be empty β nothing has been recorded yet.
In a second terminal, bring in a session you have already run:
observatory import
Refresh the dashboard. That is the whole loop.
No Claude Code sessions yet? See it work with simulated data instead:
observatory demo --scenario improving --stream
Watch the dashboard while that runs β the numbers, the chart and the timeline fill in live.
Three scores, and they answer different questions. A session can be at 82 and going nowhere, or at 55 and climbing fast.
0β100. A weighted average of five things, each measured, each shown to you:
| Component | Weight | What it measures |
|---|---|---|
| Recovery | 30% | When something failed, did the agent fix it? |
| Tool efficiency | 20% | How many tool calls succeeded |
| Repetition avoidance | 20% | How much of the work was doing something already done |
| Goal adherence | 15% | How much of the work related to what you asked for |
| Context headroom | 15% | How much of the context window is still free |
| Score | Band |
|---|---|
| 80β100 | healthy |
| 60β79 | stable |
| 40β59 | warning |
| 0β39 | degrading |
A component that cannot be measured is excluded, not counted as zero β a session with no failures has no recovery rate, and scoring that as 0 would rank "never failed" below "failed and recovered". The dashboard shows you how many of the five were actually measured.
The session is split into three windows by action count β early, middle, recent β and compared. Improving means errors fell, recovery rose, repetition dropped. Degrading means the reverse. Stable means no meaningful trend either way.
This is not model learning. There are no weights, gradients or loss values here. Claude Code does not expose them, and this tool does not pretend to. "Learning" means the agent's observable behavior got better during this session β nothing more.
0β100, from seven specific signals: the same action failing repeatedly, rising error rate, falling recovery, correction loops that keep failing, drifting off the goal, and context pressure. Each one is listed with the measurement behind it.
| You see | It usually means |
|---|---|
| Repetition high, recovery low | The agent is stuck. Give it new information, not another retry. |
| "failed N times in a row" | It is retrying without changing anything. Intervene. |
| "tried N times, never worked" | The whole approach is wrong, not the details. Redirect it. |
| Context utilization above 90% | It is running out of room. Start a fresh session. |
| Goal adherence falling | It has wandered. Restate the goal. |
| Health high, learning stable | Nothing is wrong. Steady competent work looks exactly like this. |
| Command | What it does |
|---|---|
observatory start |
Start everything β API, live updates and dashboard, on one port |
observatory import |
Read a real Claude Code session and analyze it |
observatory sessions |
List what has been recorded |
observatory status |
What the Observatory is doing right now |
observatory compare |
Compare two sessions, or group them by model or prompt |
observatory demo |
Generate a simulated session (no agent required) |
observatory dashboard |
Open the dashboard in a browser |
observatory doctor |
Check that everything is set up correctly |
Every command takes --help.
observatory import --list # what is on this machine
observatory import # the newest session
observatory import --session 5f80 # a specific one (a prefix is enough)
observatory import --watch # follow a session as it runs, live
observatory import --project myapp # only sessions from one project
Re-running is safe. The Observatory asks how much it already has and sends only what is new β which
is also how --watch keeps up with a running agent.
observatory compare <session-a> <session-b> # side by side
observatory compare --by model # grouped by model
observatory compare --by goal # grouped by prompt
The same thing in the terminal:
left demo_degrading_BA7E (degrading)
right demo_improving_9E21 (improving)
LEFT RIGHT CHANGE
Health 35 74 +39 better
Recovery rate 33% 100% +67 pts better
Error rate 71% 35% -35 pts better
Only on the left:
- npm test β read docs β tried 2 times, never worked
- npm test -- session failed 7 times in a row
Grouped comparison uses medians, not averages β one disastrous session should not define a model β and shows the session count on every row, because a comparison built from one session each is a data point, not a finding. It shows you differences; it does not claim causes. Two sessions differ in the model and the task and the day.
observatory demo --scenario improving --stream # watch it arrive live
observatory demo --scenario degrading # or just print the report
Three scenarios, each with a known verdict:
| Scenario | What the simulated agent does | Verdict |
|---|---|---|
improving |
thrashes, investigates, then recovers from everything | β² IMPROVING |
stable |
one failure per stretch, corrected each time, no trend | β STABLE |
degrading |
the same test fails seven times; edits stop helping; drifts off task | βΌ DEGRADING |
Simulated sessions are always labelled as simulated β in the session id, on every event, and in the dashboard. They are never presented as something your agent did.
This is the part worth reading carefully, because the Observatory reads your agent's transcripts.
Nothing leaves your machine. There is no cloud, no telemetry, no phone-home. The server binds to
127.0.0.1 only, so nothing on your network can reach it either.
And most of the transcript is never even read into the tool. The import takes the shape of the work, not its content:
| Recorded | Never recorded |
|---|---|
| Which tool ran | Your prompts and the agent's replies |
| The file path that was read or edited | File contents and diffs |
| The command line (capped at 500 characters) | Command output, stdout, stderr |
| Whether it succeeded or failed | Error messages |
| Token counts | β |
Anything that does get stored passes through secret redaction first β API keys, tokens, passwords and private keys in twelve known formats β and redaction runs before the database write, so an unredacted value never touches disk.
Your data lives in one place:
~/.observatory/observatory.db
Delete that file and everything is gone. Point OBSERVATORY_DB somewhere else to move it.
Being straight about the limits, because a number presented confidently is worse than no number.
Fully measured with Claude Code:
- Failures and recoveries β Claude Code marks failed tool calls explicitly, so this is a fact, not a guess
- Files read and modified, counted as distinct paths
- Token usage, deduplicated per API response
- Repetition, correction loops, and every score built on them
- Lines added and removed, counted from the patch β the count, never the code
- Thinking tokens, cache hit rate, and commands killed at their time limit
Not available:
- Context utilization. Claude Code records the model but never its context limit, so the Observatory shows "no window reported" rather than inventing a percentage. Codexdoes report it.
- Cost. Shown when the agent recorded it, never estimated from a pricing table that would go stale.
- Codex sessions. Codex writes readable logs and support is planned, but nothing reads them yet.
observatory doctorsays so plainly.
Deliberately approximate:
Goal adherence is word matching β it connects a goal that says "authentication" to a file called
auth.ts, but it will not connect "login" to session-store.ts. That is why the signal is called
possible goal drift and carries little weight. Same for repeated-strategy detection: it compares
generalized actions, not meanings.
The scores themselves are product judgements, not science. The weights above are one reasonable opinion about what good agent behavior looks like. docs/scoring.md explains every one and how to change it.
observatory is not recognised
npm's global install directory is not on your PATH. Find it with npm prefix -g and add it (the
executables are in that folder on Windows, and in its bin subfolder on macOS and Linux). Or skip
the PATH entirely and use npx ai-agent-observatory <command>.
The dashboard says "The Observatory API is not answering"
observatory start is not running, or it is on a different port. Run observatory doctor.
observatory import says no transcripts found
Claude Code writes them the first time you run a session. Confirm with observatory import --list.
If that is empty, no sessions exist on this machine yet.
Port 4000 is already in use
observatory start --port 4100
The dashboard is empty after importing
Check that the import reported events, and that observatory sessions lists the session. If it does,
refresh the page.
Start over
rm ~/.observatory/observatory.db # deletes every recorded session
Uninstall
npm uninstall -g ai-agent-observatory
rm -rf ~/.observatory
git clone <this repo> && cd ai-agent-observatory
npm install
npm run dev # API on :4000, dashboard on :4001, packages in watch mode
npm test # 595 tests, no build required
In development the dashboard runs on its own port under next dev, which is why it is :4001 there
and :4000 once installed. To build the installable package:
npm run package # -> dist-package/
npm install -g ./dist-package # install that build
| Command | What it does |
|---|---|
npm run dev |
Everything, in watch mode |
npm test |
Vitest against package source |
npm run typecheck |
Type-check every workspace, dashboard included |
npm run lint |
ESLint over the repo |
npm run package |
Build the single publishable package |
npm run db:studio |
Browse the local database |
apps/web/ Next.js dashboard (exported to static files when packaged)
apps/server/ Fastify API + WebSocket hub
packages/shared/ Contracts (Zod) and the scoring configuration
packages/telemetry/ Validation, normalization, secret redaction
packages/metrics/ Metric computation β pure functions
packages/behavior/ Repetition, recovery, health, learning, degradation
packages/collectors/ Agent adapters and the demo generator
cli/ The `observatory` command
The analytics packages are pure and synchronous: events in, scores and reasons out. No database, no network, no LLM. That is what makes results reproducible, and it means adding an agent adapter never touches the scoring engine.
The dashboard is an ordinary client of the local server and computes nothing itself.
| Endpoint | What it does |
|---|---|
POST /api/sessions |
Create a session |
GET /api/sessions |
List sessions with their headline scores |
GET /api/sessions/:id |
The full snapshot the dashboard renders |
POST /api/sessions/:id/events |
Ingest one event or a batch |
GET /api/sessions/:id/metrics |
Metrics, windows and the progress series |
GET /api/sessions/:id/health |
Scores β with the reasons behind them |
GET /api/sessions/:id/timeline |
The activity rows |
GET /api/compare |
Compare two sessions, or group them |
WS /api/sessions/:id/stream |
Live updates while a session runs |
Any tool can be observed without an adapter by posting events to that API.
- docs/architecture.md β how a raw event becomes a score
- docs/scoring.md β what every score means and does not mean
- docs/integrations.md β what Claude Code and Codex actually expose
MIT