Skip to content

ydking0911/observr

Repository files navigation

English | 한국어


observr

Your AI coding agent can see what your app did.
One-line app instrumentation for your local dev loop — structured telemetry your AI coding agent can query.

CI PyPI npm Go License

Problem · Why · Concepts · Quickstart · Query · Roadmap

import observr
observr.init(service="my-agent")
# Every action this agent takes is now recorded and traceable.

The Problem

  • Your AI agent did something unexpected — you don't know which decision caused it
  • Three agents are chained together — you can't tell where the failure started
  • Claude Code or Cursor made a tool call — you want to review it after the fact
  • An agent threw an error — you need to know what prior action led to it

observr answers these questions.


Why observr?

observr is designed for one specific intersection: app-level tracing · local dev loop · one-line setup · output your AI coding agent can query. Each tool below owns its space; here is how they differ:

App tracing & logs Instrumentation Local / no infra AI coding agent can query
DIY logging ✓ manual Manual wiring Build it yourself
Datadog SDK + agent config ✗ Cloud Via paid MCP server
Grafana + OTel OTel SDK config Self-host required Via external tooling
Netdata Infra / kernel Zero-code MCP (infra metrics)
Langfuse / Phoenix LLM behaviour SDK ✓ / cloud options LLM-side traces
observr ✓ App requests, spans, logs 1 init() call ✓ SQLite, zero infra Structured JSON via CLI

observr does not replace any of the tools above — they solve different problems well. It fills the gap at the intersection of lightweight local dev and AI-consumable structured output.

What observr is — and isn't

Is: one-line SDK instrumentation for your app's HTTP requests, spans, and logs — stored locally in SQLite, queryable as structured JSON by your AI coding agent (Claude Code, Cursor).

Is not:

  • A tool for observing LLM / AI agent behaviour — that's Langfuse, Phoenix, Helicone, etc. (excellent tools for that problem, opposite direction)
  • An infrastructure or kernel-level monitor — that's Netdata, Prometheus, etc.
  • A cloud-native operations platform — that's Datadog, Grafana Cloud, etc.

Core Concepts

Causal Attribution — trace any outcome back to its root

Every span carries a parent_span_id that links it to the action that triggered it. Use agent_span() / agentSpan() to attach standard observability keys (intent, trigger, model, tool) — nesting automatically threads the causal chain.

# Python — context propagation is automatic when spans are nested
client = observr.get_client()
with client.agent_span("agent.decide", intent="answer user", model="claude-sonnet-4-6") as root:
    with client.agent_span("tool.call", trigger=root.span_id, tool="web_search") as child:
        results = web_search("relevant context")
        child.set_attribute("result_count", len(results))
trace_id: 4f2a1b3c
├── agent.decide   (a1b2)  intent="answer user"  model="claude-sonnet-4-6"
│   └── tool.call  (c3d4, parent: a1b2)  tool="web_search"  result_count=12
// Node.js
await client.agentSpan("agent.decide", { intent: "answer user", model: "claude-sonnet-4-6" })
  .run(async (root) => {
    await client.agentSpan("tool.call", { trigger: root.spanId, tool: "web_search" })
      .run(async () => { /* causally linked — parent_span_id set automatically */ });
  });

Click any trace chip in the dashboard to open the causality tree — a waterfall showing every span, its duration, and agent attributes.

Behavioral Patterns — signal over noise

observr normalizes event messages and groups similar ones by fingerprint.

"Payment failed for user abc123" and "Payment failed for user xyz789" collapse into the same pattern — so you see frequency over time, not noise.

Audit Log — local, queryable, persistent

All events are stored locally in SQLite (WAL mode) with full timestamps, service attribution, structured attributes, and a tamper-evident SHA-256 hash chain.

Queryable by: level · service · trace ID · time range · HTTP path

Verify integrity with GET /verify. The dashboard header shows chain ✓ when the stored chain is intact and chain ✗ when an older event was modified or deleted.


Quickstart

1. Start the collector

macOS / Linux

curl -sSL https://raw.githubusercontent.com/ydking0911/observr/main/scripts/install.sh | sh
observrd   # → http://localhost:7676

Homebrew

brew tap ydking0911/observr && brew install observr

go install

go install github.com/ydking0911/observr/server/cmd/observrd@latest

2. Install the SDK

pip install observr               # Python
npm install @ydking0911/observr   # Node.js

3. Instrument your agent

Python — FastAPI / Flask / Django (WSGI + ASGI)

import observr
observr.init(service="my-agent")  # auto-detects the framework
# Django: X-Trace-Id / X-Span-Id headers are propagated automatically

Node.js — Express

const { init } = require('@ydking0911/observr')
init({ service: 'my-agent' })

Agent spans — causal chain with standard attribute keys:

client = observr.get_client()
with client.agent_span("tool.call", intent="find recent papers", tool="web_search") as span:
    results = web_search("observability 2026")
    span.set_attribute("result_count", len(results))

Logs are captured automatically:

import logging
logger = logging.getLogger(__name__)
logger.error("Payment failed", extra={"user_id": "u_123", "amount": 9900})

Query the Audit Log

# Recent errors as JSON
observrd query --level error --last 100 --format json

# All actions from a specific agent
observrd query --service my-agent --last 500 --format json

# Trace a full decision tree
observrd query --trace-id 4f2a1b3c

# Export for review
observrd query --level error --last 10000 --format csv > audit.csv

# Human-readable table
observrd query --format text

Example — an AI agent auditing itself:

User: What errors did the agent produce in the last hour?
Claude: Let me pull the audit trail...
$ observrd query --service my-agent --level error --last 200 --format json
→ 3 errors, all traced to span "tool.call" → parent "agent.decide" at 14:32:01
→ Root cause: agent.decide passed malformed input to tool.call

Verify Audit Integrity

Each inserted event stores its canonical JSON plus SHA256(prev_hash + event_json). Recomputing the chain detects in-place tampering: modifying a past event, or deleting an event from the middle of the log, breaks the next link.

curl http://localhost:7676/verify
{ "ok": true, "checked": 1042, "skipped": 0, "broken_at": null }

If the chain is broken, broken_at is the first event ID whose stored hash no longer matches:

{ "ok": false, "checked": 204, "skipped": 0, "broken_at": "evt_abc123" }

skipped counts leading legacy rows written before this feature existed. Upgrading an existing database in place is safe: those rows have no stored hash, so they are reported as unverifiable (skipped) rather than broken, and verification continues from the first hashed event.

What it protects against, and what it does not. This is a local, unkeyed hash chain — not a blockchain. It is honest about its limits:

  • Detects in-place edits and deletion of events from the middle of the log.
  • Does not detect tail truncation. Deleting the most recent N events leaves a shorter but internally consistent chain, so ok stays true. Closing this gap requires an external head anchor (planned).
  • Does not resist an attacker with write access to the database file. Because the hash is unkeyed, anyone who can edit a row can recompute every following hash and pass verification. Tamper-evidence holds only against actors who cannot recompute the chain (e.g. accidental corruption, a process without the verification logic, or read-only-then-tampered exports). A keyed (HMAC) or externally anchored variant is future work.
  • No distributed consensus. Single-node tamper evidence only.
  • Retention interaction. Retention cleanup deletes the oldest rows; once the genesis events are gone, the surviving prefix no longer chains from the empty seed and /verify reports broken for the new oldest row.

Alerts

Fire Slack or Discord notifications when error thresholds are exceeded:

observrd start \
  --alert-slack-url   https://hooks.slack.com/services/... \
  --alert-discord-url https://discord.com/api/webhooks/... \
  --alert-level       error \
  --alert-threshold   5 \
  --alert-window      60s \
  --alert-cooldown    5m

Event Schema

{
  "id":             "evt_1711234567890",
  "trace_id":       "4f2a1b3c8e9d0f1a",
  "span_id":        "a1b2c3d4",
  "parent_span_id": "9f8e7d6c",
  "service":        "my-agent",
  "timestamp":      "2026-03-24T12:34:56.789Z",
  "type":           "span",
  "level":          "error",
  "duration_ms":    3241.5,
  "message":        "tool.call failed",
  "attributes": {
    "tool":  "web_search",
    "error": "timeout after 3000ms"
  }
}

parent_span_id links a span to its causal parent, enabling full decision tree reconstruction.


Roadmap

Version Status Features
v0.1 Python SDK · Go collector · React dashboard · CLI · CI/CD
v0.2 Node.js SDK · PyPI publish · npm publish
v0.3 Slack/Discord alerts · Event retention (TTL) · JSON/CSV export
v0.4 Causal attribution (parent_span_id) · Behavioral pattern detection · Fastify support
v0.5 agent_span() / agentSpan() helper · Dashboard causality tree view · Django support
v0.6 Deep behavioral pattern analysis — temporal trends, anomaly detection, agent-attribute grouping (intent/tool/model), causal pattern correlation, dashboard Patterns view
v0.7 🚧 Go SDK · Tamper-proof hash-chain audit log · Multi-agent W3C TraceContext propagation
v0.8 📋 Native MCP server — AI coding agents (Claude Code, Cursor) query observr directly without CLI (planned, not yet implemented)
v1.0 📋 API stability guarantee · CHANGELOG · Cross-platform release artifacts

Development

make build          # build everything (dashboard embedded into binary)
make dev-server     # Go server on :7676
make dev-dashboard  # Vite dev server on :5173 (proxies to :7676)
make test           # Go + Python + Node.js
make test-e2e       # full end-to-end test
make lint

See CONTRIBUTING.md to get started.


MIT License · LICENSE

About

One-line app instrumentation for your local dev loop — structured telemetry your AI coding agent can query.

Topics

Resources

License

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors