Open-source analytics that runs your growth loop, not just your dashboards.
Every analytics tool can tell you what happened. The real work — measure → diagnose → test → learn — falls to a human who rarely has time to run it, and the loop stalls at the dashboard. AgentRay ships that loop as the product: the same event store that powers your charts also powers agents that read the data, find the single weakest link in your funnel, design the smallest test, remember the result, and pick the thread back up next cycle.
Underneath is a complete product-analytics base you can self-host with one
docker compose up — fast Go ingestion, cheap event storage in ClickHouse,
PostgreSQL metadata, and a PostHog-compatible event model, so existing
instrumentation migrates by changing only the host. On top sits what other
platforms bolt on: an MCP server and ready-made agent skills, so Claude Code or
Codex works your real event data — from one-off product questions to a
scheduled, unattended growth loop.
The foundation architecture (detailed in docs/PostHog-clone.md):
- Go ingestion API built with Echo
- ClickHouse raw event storage plus a materialized session view
- PostgreSQL project metadata, saved queries, and analyst feedback tables
- Redis-backed rate limiting for ingestion endpoints
- NATS-backed asynchronous ingestion from HTTP handlers into ClickHouse
- Next.js dashboard app in
web/for project keys, activity, dashboards, and chart management - MVP analytics workflows: insight builder, dashboard filters, templates, web analytics, event explorer, agent session replay, and saved SQL-lite queries
- PostHog-compatible
capture,batch, andidentifyendpoints so existing browser and backend instrumentation can move over incrementally
The agent runtime powering AgentRay's growth loop is exported as two reusable Go packages you can import on their own:
agentcore— a provider-agnostic agent loop (Anthropic or any OpenAI-compatible gateway), with progressive-disclosure skills, tool policies, budget gating, and context compaction.sandbox— read-only workspace tools (read_file,grep,glob) for grounding an agent in a repository.
go get github.com/lohi-ai/agentray@latestSwatter, the validated PR-review bugbot, is built entirely on these packages.
- Built for AI-first products: agent runs, tool usage, token cost, latency, and failures fit the data model instead of feeling bolted on.
- Easier to self-host: Go + ClickHouse + Postgres is simpler to reason about than a much larger analytics platform.
- Familiar migration path: it accepts the common event payload shape teams already send today.
- Open-source by default: the storage layer and local workflow are readable, hackable, and designed for extraction into a standalone repository.
The current service is the ingestion and storage base layer:
POST /capturePOST /batchPOST /identifyGET /api/eventsGET /api/sessionsGET /api/activityGET|POST /api/projectsPOST /api/projects/:project_id/rotate-keyGET|POST|PUT|DELETE /api/dashboardsGET|POST /api/dashboards/:dashboard_id/chartsPUT|DELETE /api/charts/:chart_idGET /api/insights/runGET /api/templatesPOST /api/templates/:template_id/applyGET /api/web-analyticsGET /api/personsGET /api/events/exploreGET /api/sessions/:session_id/replayGET|POST /api/saved-queriesPOST /api/saved-queries/:query_id/runPOST /api/sql/runGET /healthz
Supported compatibility aliases:
POST /e/POST /ePOST /i/v0/e/POST /i/v0/e
Both api_key and token are accepted for project authentication.
Ingestion requests follow the foundation architecture from
docs/PostHog-clone.md:
HTTP API -> Redis rate limit -> NATS queue -> ClickHouse storage
Every new project (signup, workspace project creation, and the default local project) is auto-seeded with a "Product overview" dashboard holding four predefined charts — event trend, top events, sessions, and agent cost — so the Dashboards tab gives a readable answer before any custom chart is built.
Browser — @agentray/browser (sdk/browser/). One init() wires identity,
batched delivery, retries, and sendBeacon flush on unload:
import { init } from '@agentray/browser';
const ar = init({ host: 'https://agentray.example.com', apiKey: 'phc_...', autocapture: true });
ar.capture('checkout_started', { plan: 'pro' });
ar.identify('user-123', { email: 'alice@example.com' });Autocapture is dependency-free and framework-agnostic: every page reports
pageviews (user.pageview, which powers the Web analytics tab), delegated clicks
($autocapture), and [data-track-view] visibility (element_viewed) with no
per-button wiring. Markup conventions: data-track="label" opts an element into
click capture with an explicit label, data-track-ignore mutes a subtree, and
data-track-view="label" fires element_viewed once when the element becomes at
least half visible. See sdk/browser/README.md.
Python — agentray (sdk/python/). Non-blocking server-side capture with a
background batch thread; PostHog-compatible payloads:
from agentray import Client
ar = Client(host="https://agentray.example.com", api_key="phc_...")
ar.capture("order_paid", distinct_id="user-123", properties={"amount": 29})
ar.flush()Node/Bun server — @agentray/server (sdk/server/). Awaitable, idempotent
capture for events the browser must not be trusted to send — payments,
subscriptions, refunds:
import { AgentRayServerClient } from '@agentray/server';
const ar = new AgentRayServerClient({ apiUrl: process.env.AGENTRAY_URL!, apiKey: process.env.AGENTRAY_API_KEY! });
await ar.revenue('user-123', { amount: 19, currency: 'USD' }, { idempotencyKey: webhook.id });All three SDKs speak the same capture / batch / identify payload, so a
PostHog integration migrates by changing only the host.
cmd/cli builds the agentray binary (make cli, or
go install github.com/lohi-ai/agentray/cmd/cli@latest). It is self-serve from
zero — an agent can create an account and fetch a project API key without ever
opening the web app:
agentray signup --email you@example.com # account + workspace + project
agentray login --email you@example.com # session saved to ~/.agentray
export AGENTRAY_API_KEY=$(agentray key) # bare key on stdout
agentray key --rotate # rotate and print the new key
agentray projects # list projects; `whoami`, `logout`Passwords come from --password, AGENTRAY_PASSWORD, or a hidden prompt. After
login, the saved server URL and project key become the defaults, so every
operation works with zero flags:
agentray ops # list operations + schemas
agentray activity_summary '{"hours":24}'
agentray run_sql '{"sql":"SELECT count() FROM events"}'The operation set IS the shared registry — the same definitions the server exposes as REST, MCP tools, and in-process agent tools.
AgentRay exposes its analytics operations to external AI agents (Claude Code,
Codex, any MCP client) over an MCP server at POST /mcp. The agent can read
activity, run funnels/retention/SQL over your events, and pin dashboards — the
same operations the in-app analyst and the web client use, with no second API to
learn.
Authenticate with a project API key (Settings → project → API key) passed as a request header:
claude mcp add --transport http --header "X-API-Key: <project-key>" \
agentray https://agentray.lohi2.com/mcpCodex:
codex mcp add agentray --url https://agentray.lohi2.com/mcp \
--header "X-API-Key: <project-key>"Self-hosted: swap the host for your instance (e.g. http://localhost:8080/mcp).
The API key scopes every call to one project — there is no separate login step.
The MCP tools are projected from the operation registry, so they stay in sync with the in-app agent and REST API:
activity_summary,recent_events— monitoring and incident triageexplore_events,persons— data-quality and audience sizingrun_insight(timeseries / funnel / retention),run_sql(SELECT-only) — analysislist_dashboards,create_dashboard,create_chart— pin viewssubmit_recommendation,remember— capture findings
Reusable workflow guides for Claude Code / Codex live in
.agents/skills/. They teach an agent how to drive the MCP
above:
agentray-setup— integrate an app end to end, in the right order: project + API key (web app oragentray signup/keyCLI), SDK install, event instrumentation contract, dashboards, agents.agentray-instrument— design the tracking plan: which events to capture, why each earns its place, and the consumer (chart, ask-AI question, SQL, alert) planned for every event before it is instrumented.agentray-analytics— start here for questions; connect, then answer product questions from real event data and pin dashboards.agentray-growth-loop— run one full measure → diagnose → hypothesize → recommend → remember cycle: find the weakest funnel link, design the smallest reversible test, file it with evidence.agentray-funnel-retention— build a conversion funnel or retention readout and pin it.agentray-incident-triage— investigate an error spike, latency, or cost regression from activity and raw events.
Install them into your agent's skills folder:
# Claude Code
mkdir -p ~/.claude/skills && cp -R .agents/skills/* ~/.claude/skills/
# Codex
mkdir -p ~/.codex/skills && cp -R .agents/skills/* ~/.codex/skills/Start the full local stack:
docker compose up --build -dServices exposed on your machine:
- API:
http://localhost:8088 - Dashboard web:
http://localhost:3200 - ClickHouse HTTP:
http://localhost:18123 - ClickHouse native:
localhost:19000 - PostgreSQL:
localhost:5434 - Redis:
localhost:6389 - NATS:
localhost:4223
Default local project token:
lohi_dev_project_token
Send a smoke event:
curl -s http://localhost:8088/capture \
-H 'Content-Type: application/json' \
-d '{
"api_key": "lohi_dev_project_token",
"event": "agent.tool_call",
"distinct_id": "local-user",
"session_id": "session-1",
"properties": {
"tool_name": "search",
"latency_ms": 120,
"tokens_input": 42,
"tokens_output": 11
}
}'Inspect recent events:
curl -s 'http://localhost:8088/api/events?api_key=lohi_dev_project_token&limit=10'Inspect recent sessions:
curl -s 'http://localhost:8088/api/sessions?api_key=lohi_dev_project_token&limit=10'Open the dashboard:
open http://localhost:3200Run the dashboard app without Docker:
cd web
bun install
NEXT_PUBLIC_AGENTRAY_API_URL=http://localhost:8088 bun run devRun the e2e test from the host machine:
go test -tags=e2e ./internal/app -run TestAnalyticsServiceE2E -count=1 -vIf you run the test from inside a container that talks to the host Docker daemon, point it back at the host-published ports:
AGENTRAY_E2E_INFRA_HOST=host.docker.internal \
go test -tags=e2e ./internal/app -run TestAnalyticsServiceE2E -count=1 -vThe storage model is tuned for the roadmap without overbuilding the MVP:
- Raw events stay append-only in ClickHouse.
- A
sessions_mvmaterialized view rolls session aggregates forward as events arrive, which keeps common session analytics cheap. - PostgreSQL keeps relational metadata and adds indexes for the read paths that are already present in the design.
AgentRay currently targets Go 1.25 and the latest dependency set verified in
container build during this migration:
github.com/ClickHouse/clickhouse-go/v2 v2.46.0github.com/jackc/pgx/v5 v5.10.0github.com/labstack/echo/v4 v4.15.2github.com/nats-io/nats.go v1.52.0github.com/redis/go-redis/v9 v9.20.0- Next.js
16.1.6, React19.2.3, and Apache ECharts6.1.0inweb/
The living roadmap — current priorities, acceptance criteria, and sequencing —
lives in ROADMAP.md, with the detailed engineering breakdown in
docs/IMPLEMENTATION-PLAN.md.
AgentRay is the product name because it is short, easy to say, and signals
visibility into agent behavior instead of generic web analytics.
MIT