+113
-1
| #!/usr/bin/env node | ||
| const path = require('path'); | ||
| const { startServer } = require('./server'); | ||
@@ -19,3 +21,4 @@ const { startProxy, startRecording, recordToolCall, finishRecording } = require('./proxy'); | ||
| server Run as MCP server (recommended — agent self-reports all actions) | ||
| dashboard [--port <n>] Start the web dashboard | ||
| dashboard [--port <n>] [--quick] Start the web dashboard | ||
| setup One-command onboarding — detect agent, configure MCP | ||
| check [--last <n>] Show latest session details | ||
@@ -82,3 +85,12 @@ stats Show aggregate session stats | ||
| const portIdx = args.indexOf('--port'); | ||
| const quickIdx = args.indexOf('--quick'); | ||
| const port = portIdx >= 0 ? parseInt(args[portIdx + 1]) : 9400; | ||
| if (quickIdx >= 0) { | ||
| const { fork } = require('child_process'); | ||
| fork(path.join(__dirname, 'cli.js'), ['server'], { stdio: 'ignore', detached: true }).unref(); | ||
| console.log('[agent-obs] MCP server started (agent can now connect)'); | ||
| } | ||
| printSummary(); | ||
| await startServer(port); | ||
@@ -150,2 +162,102 @@ return; | ||
| if (command === 'setup') { | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const cwd = process.cwd(); | ||
| let detected = []; | ||
| let actions = []; | ||
| const opencodeJson = path.join(cwd, 'opencode.json'); | ||
| if (fs.existsSync(opencodeJson)) { | ||
| detected.push('opencode'); | ||
| try { | ||
| const config = JSON.parse(fs.readFileSync(opencodeJson, 'utf8')); | ||
| if (!config.mcp) config.mcp = {}; | ||
| if (!config.mcp['agent-obs']) { | ||
| config.mcp['agent-obs'] = { | ||
| type: 'local', | ||
| command: ['npx', '-y', 'agent-obs@latest', 'server'], | ||
| enabled: true | ||
| }; | ||
| fs.writeFileSync(opencodeJson, JSON.stringify(config, null, 2) + '\n'); | ||
| actions.push('opencode.json updated (agent-obs MCP server added)'); | ||
| } else { | ||
| actions.push('opencode.json already has agent-obs ✓'); | ||
| } | ||
| } catch (e) { | ||
| actions.push('Could not update opencode.json: ' + e.message); | ||
| } | ||
| const agentsMd = path.join(cwd, 'AGENTS.md'); | ||
| const instruction = '\n## Agent Observability (Self-Reporting)\n\nWhen the `agent-obs` MCP server is connected, self-report every tool call:\n\n- Call `agent_obs_start_session` at the start of every task\n- Call `agent_obs_log_tool_call` after EVERY tool call (Read, Write, Edit, Bash, Glob, Grep, etc.) with tool name, duration, status, and output summary\n- Call `agent_obs_end_session` at task completion with token counts\n- NEVER skip log_tool_call — every tool call must be logged. One call = one log.\n- Log errors with status: "error" and the error message\n- Do NOT log the agent-obs tools themselves (start_session, log_tool_call, end_session)\n'; | ||
| if (fs.existsSync(agentsMd)) { | ||
| const content = fs.readFileSync(agentsMd, 'utf8'); | ||
| if (!content.includes('Agent Observability (Self-Reporting)')) { | ||
| fs.appendFileSync(agentsMd, instruction); | ||
| actions.push('AGENTS.md updated (self-reporting instruction added)'); | ||
| } else { | ||
| actions.push('AGENTS.md already has self-reporting instruction ✓'); | ||
| } | ||
| } else { | ||
| fs.writeFileSync(agentsMd, instruction + '\n'); | ||
| actions.push('AGENTS.md created (self-reporting instruction added)'); | ||
| } | ||
| } | ||
| const claudeDir = path.join(cwd, '.claude'); | ||
| const mcpJson = path.join(cwd, '.mcp.json'); | ||
| if (fs.existsSync(claudeDir) || fs.existsSync(mcpJson)) { | ||
| detected.push('claude-code'); | ||
| const target = mcpJson; | ||
| let mcpConfig = {}; | ||
| if (fs.existsSync(target)) { | ||
| try { mcpConfig = JSON.parse(fs.readFileSync(target, 'utf8')); } catch(e) {} | ||
| } | ||
| if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {}; | ||
| if (!mcpConfig.mcpServers['agent-obs']) { | ||
| mcpConfig.mcpServers['agent-obs'] = { | ||
| command: 'npx', | ||
| args: ['-y', 'agent-obs@latest', 'server'] | ||
| }; | ||
| fs.writeFileSync(target, JSON.stringify(mcpConfig, null, 2) + '\n'); | ||
| actions.push('.mcp.json created (agent-obs MCP server configured)'); | ||
| } else { | ||
| actions.push('.mcp.json already has agent-obs ✓'); | ||
| } | ||
| } | ||
| const cursorDir = path.join(cwd, '.cursor'); | ||
| if (fs.existsSync(cursorDir)) { | ||
| detected.push('cursor'); | ||
| actions.push('Cursor detected — add this to Cursor Settings > MCP:'); | ||
| actions.push(' { "agent-obs": { "command": "npx", "args": ["-y", "agent-obs@latest", "server"] } }'); | ||
| } | ||
| if (detected.length === 0) { | ||
| detected.push('unknown'); | ||
| actions.push('No AI agent detected in current directory.'); | ||
| actions.push('Manual setup:'); | ||
| actions.push(' npx agent-obs@latest server # start MCP server'); | ||
| actions.push(' Add agent-obs to your agent MCP config'); | ||
| } | ||
| console.log('╔══════════════════════════════════════════╗'); | ||
| console.log('║ agent-obs v' + pkg.version + ' — Setup ║'); | ||
| console.log('╚══════════════════════════════════════════╝'); | ||
| console.log(''); | ||
| console.log('Detected: ' + detected.join(', ')); | ||
| actions.forEach(a => console.log(' ✓ ' + a)); | ||
| console.log(''); | ||
| console.log('Next: restart ' + detected[0]); | ||
| console.log('Dashboard: http://localhost:9400'); | ||
| console.log(''); | ||
| console.log('To verify:'); | ||
| console.log(' agent-obs dashboard'); | ||
| console.log(' # Run any task in your agent'); | ||
| console.log(' # Sessions should appear automatically'); | ||
| process.exit(0); | ||
| } | ||
| if (command === 'proxy') { | ||
@@ -152,0 +264,0 @@ const separatorIdx = args.indexOf('--'); |
+1
-1
| { | ||
| "name": "agent-obs", | ||
| "version": "1.0.1", | ||
| "version": "1.0.2", | ||
| "description": "Open source agent observability — see what your agents did, why they failed, and what it cost. Runs locally.", | ||
@@ -5,0 +5,0 @@ "main": "cli.js", |
@@ -77,5 +77,9 @@ <!DOCTYPE html> | ||
| <div class="empty-state" id="sessions-empty"> | ||
| <span class="empty-icon">∅</span> | ||
| <p>No sessions recorded</p> | ||
| <p class="empty-hint">Agent sessions will appear here as they execute</p> | ||
| <span class="empty-icon">◉</span> | ||
| <p><strong>No agent sessions yet</strong></p> | ||
| <p class="empty-hint">Your agent isn't self-reporting. Run this once:</p> | ||
| <div class="setup-box"> | ||
| <code>npx agent-obs@latest setup</code> | ||
| </div> | ||
| <p class="empty-hint" style="margin-top:8px">Then restart your agent. Sessions will appear here.</p> | ||
| </div> | ||
@@ -82,0 +86,0 @@ </div> |
+14
-0
@@ -172,2 +172,16 @@ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} | ||
| /* Setup Box */ | ||
| .setup-box { | ||
| background: #0f172a; | ||
| border: 1px solid #334155; | ||
| border-radius: 6px; | ||
| padding: 10px 16px; | ||
| margin: 12px 0; | ||
| display: inline-block; | ||
| } | ||
| .setup-box code { | ||
| color: #22d3ee; | ||
| font-size: 13px; | ||
| } | ||
| /* Scrollbar */ | ||
@@ -174,0 +188,0 @@ ::-webkit-scrollbar{width:5px;height:5px} |
+35
-63
@@ -7,14 +7,31 @@ # agent-observability | ||
| Here's how to connect your agent in 2 minutes: install the package, add agent-obs as an MCP server to your agent platform, tell the agent to self-report, and watch sessions appear in the dashboard. | ||
| One command. No manual config. No copy-paste. | ||
| ### Install | ||
| ```bash | ||
| npx agent-obs@latest setup | ||
| ``` | ||
| This auto-detects your AI agent (opencode, Claude Code, Cursor) and configures everything: | ||
| - Adds agent-obs to your MCP config | ||
| - Adds the self-reporting instruction | ||
| - Tells you what to do next | ||
| Then restart your agent. Every action will now self-report. | ||
| ```bash | ||
| npm install -g agent-observability | ||
| agent-obs dashboard # http://localhost:9400 — see your sessions appear | ||
| ``` | ||
| ### 1. opencode | ||
| ### What you'll see | ||
| Add the MCP server to your `opencode.json`: | ||
| After running a task in your agent, the dashboard shows: | ||
| - Every tool call with duration and status | ||
| - A-F session grade (how efficient was your agent?) | ||
| - Cost per session in tokens and dollars | ||
| - Full audit trail of what was read, edited, and executed | ||
| ### Manual setup (if `setup` can't detect your agent) | ||
| **opencode:** Add to `opencode.json`: | ||
| ```json | ||
@@ -24,4 +41,4 @@ { | ||
| "agent-obs": { | ||
| "type": "local", | ||
| "command": ["node", "/Users/williamweishuhn/Documents/New OpenCode Project/agent-observability/cli.js", "server"], | ||
| "command": "npx", | ||
| "args": ["-y", "agent-obs@latest", "server"], | ||
| "enabled": true | ||
@@ -33,10 +50,4 @@ } | ||
| Then add this to your system prompt (e.g. in `AGENTS.md`): | ||
| **Claude Code:** Create `.mcp.json`: | ||
| > After every tool call, call agent_obs_log_tool_call with the tool name, duration, status, input summary, and output summary. Start a session at the beginning of each task with agent_obs_start_session. | ||
| ### 2. Claude Code | ||
| Add to your project's `.mcp.json`: | ||
| ```json | ||
@@ -46,4 +57,4 @@ { | ||
| "agent-obs": { | ||
| "command": "agent-obs", | ||
| "args": ["server"] | ||
| "command": "npx", | ||
| "args": ["-y", "agent-obs@latest", "server"] | ||
| } | ||
@@ -54,21 +65,4 @@ } | ||
| Then add a project-level skill so Claude self-reports. Create `.claude/skills/agent-obs/SKILL.md`: | ||
| **Cursor:** Add to Cursor Settings > MCP: | ||
| ```markdown | ||
| --- | ||
| name: agent-obs | ||
| description: Report every tool call to agent-obs for observability tracking. | ||
| --- | ||
| At the start of each task, call agent_obs_start_session with a description | ||
| of the task. After every tool call, call agent_obs_log_tool_call with the | ||
| tool name, duration, status, input summary, and output summary. When the | ||
| task is done, call agent_obs_end_session with the final status and token | ||
| counts. | ||
| ``` | ||
| ### 3. Cursor | ||
| Add to Cursor's MCP settings (`~/.cursor/mcp.json`, or Settings → MCP → Add new global MCP server): | ||
| ```json | ||
@@ -78,4 +72,4 @@ { | ||
| "agent-obs": { | ||
| "command": "agent-obs", | ||
| "args": ["server"] | ||
| "command": "npx", | ||
| "args": ["-y", "agent-obs@latest", "server"] | ||
| } | ||
@@ -86,12 +80,10 @@ } | ||
| Then add the same self-reporting instruction to your Cursor rules (`.cursorrules` or Settings → Rules): | ||
| See [Agent-Specific Setup](#agent-specific-setup) below for detailed per-platform instructions including self-reporting directives. | ||
| > After every tool call, call agent_obs_log_tool_call with the tool name, duration, status, input summary, and output summary. Start a session at the beginning of each task with agent_obs_start_session. | ||
| > **Note:** All data is written to a local SQLite database in `~/.agent-observability/`. No data leaves your machine. | ||
| ### 4. Self-reporting mode (recommended) | ||
| ### Proxy mode (fallback) | ||
| The MCP server mode above is the primary way to use agent-obs. The agent self-reports every action it takes — including built-in tools (Read, Write, Edit, Bash, etc.) that never travel over MCP and therefore can't be captured by a proxy. Self-reporting also captures reasoning context the wire protocol never sees: why a tool was chosen, what the agent was trying to accomplish, and how the session should be graded. | ||
| For agents that can't self-report, wrap any MCP server and every tool invocation gets traced automatically: | ||
| For MCP-only workloads, there's also a transparent proxy mode that requires no agent cooperation. Wrap any MCP server command and every tool invocation through it gets traced automatically: | ||
| ```bash | ||
@@ -101,24 +93,4 @@ agent-obs proxy --desc "fix login bug" -- npx @modelcontextprotocol/server-filesystem /tmp | ||
| The proxy captures tool names, arguments, results, durations, and success/failure status — but only for calls to the wrapped server. Use it as a supplement, not a replacement, for self-reporting. | ||
| Proxy mode captures only MCP tool calls (~30% of typical agent actions). Prefer the `setup` / MCP server approach above. | ||
| > **Note:** Proxy mode is a fallback for agents that cannot self-report. It only captures MCP tool calls (~30% of typical agent actions). Prefer the MCP server approach above. | ||
| All data is written to a local SQLite database in `~/.agent-observability/`. No data leaves your machine. | ||
| ### 5. How to verify it's working | ||
| ```bash | ||
| agent-obs dashboard | ||
| # Open http://localhost:9400 | ||
| # You should see a session appear after your agent runs a task | ||
| ``` | ||
| The dashboard shows: | ||
| - Session list with grade badges (A-F), timestamps, and token totals | ||
| - Per-session detail view with every tool call, duration, and status | ||
| - Cost estimation breakdowns | ||
| - Full-text search across all tool call inputs and outputs | ||
| - Export to JSON for external analysis | ||
| ## Agent-Specific Setup | ||
@@ -125,0 +97,0 @@ |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
99291
3.91%1731
7.12%340
-7.61%7
75%3
50%