# Summarize Each Customer's Product Usage From PostHog Through an API

Yes. Your backend starts one session per account; the agent reads that account's PostHog events and returns a JSON usage summary to your webhook.

[Run this on Rush](https://cloud.getrush.ai/run/account-activity-summary/posthog/).

## What the agent does

This job has no repository. The agent's only source is your PostHog project, reached through PostHog's own MCP server at `https://mcp.posthog.com/mcp`, which Rush lists as a connector that signs in with OAuth. You connect it once with the API key: `POST /me/connections` with `{"type": "mcp", "name": "posthog", "url": "https://mcp.posthog.com/mcp", "auth": {"mode": "oauth"}}` answers `202` with an `authorize_url`, which the key's creator opens while signed in to the Rush console, and `GET /me/connections/<id>` reads `status: "connected"` once PostHog has approved it. A key run gets only the connections it names, so each request names this one, either with `"connections": ["posthog"]` beside the fields shown below, or by saving an agent with `POST /o/{org}/agents` whose `connections` list `posthog` and sending that agent's id as `agent`.

Your backend then starts one session per account. The `input` is the same instructions every time with one line that changes, the account's PostHog group key, so the prompt reads the same for every customer and only the subject differs. The agent uses the connection's query tools to find events attributed to that group over the last 30 days and the 30 days before, counts distinct users for `active_users`, ranks events or feature-flagged features by count for `top_features`, compares the two windows for `trend`, and writes `risks` from what it sees, such as a drop in active users or a feature that stopped being used.

The answer is the JSON object the prompt describes, as the turn's final message. Rush has no field that enforces a response schema (`output_schema` is `400 FIELD_REMOVED`), so the shape lives in the prompt, and your server parses and validates `result` before storing it. The prompt also says read only: the PostHog MCP server can create insights and dashboards as well as query, and the session transcript at `GET /o/{org}/sessions/{id}/messages` lists every `tool_use` with its `args`, so you can check that a run called only reading tools.

To keep a retry from starting a second run for the same account, send an `Idempotency-Key` header such as the account id and the date: the same key and body return the session it first started, and a new day gets a new key.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Summarize product usage for the account whose PostHog group key follows this prompt. Use the PostHog connection to read its events from the last 30 days. Return JSON with `active_users`, `top_features` (5, with counts), `trend` (up, flat or down versus the 30 days before) and `risks` (short strings). Read only.\n\nGroup key: <account group key>"
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

Each session ends with one JSON object as its answer. Rush POSTs `run.completed` to the webhook URL on the API key within about 30 seconds of the turn ending, with `data.result` holding that answer (included up to 16 KiB, which a summary of this shape stays well under), `data.status`, `data.total_cost_usd` and `data.session_url`. A `run.failed` event means the run did not finish, for example because the PostHog connection needs signing in again, and `GET` on `session_url` with the key returns the error.

Your server matches the event to the account through the `execution_id` it got when it started the session, validates the JSON, and stores it beside the account record, where a customer-success tool can show it before a call. Requests to the webhook are signed per Standard Webhooks, so verify `webhook-signature` against the raw body and drop duplicates by `webhook-id`, since a failed delivery is retried up to three times.

Before relying on the summaries, check a few by hand against PostHog for the same group and window, confirm that the events counted as features are ones your team considers features rather than page views or system events, and read one transcript to see which queries the agent ran. Tighten the prompt with the event names you care about if the top five drift between runs.

## Run it on every account renewal approaching

Run it on a schedule from your own backend: a daily job selects the accounts whose renewal or quarterly review falls in the next two weeks and sends one request per account. A key runs at most `max_concurrent` sessions at once (4 by default) and answers `429` past that, so the job queues the rest and starts the next session when a webhook says one finished.

For a summary on demand, start the session from your customer-success tool when someone opens an account, and show the result when the webhook arrives; the session URL also gives the live event stream at `GET /o/{org}/sessions/{id}/events` if the screen should show progress.

## Why run it on Rush?

A per-account summary is a small piece of analysis repeated hundreds of times, and running it from a laptop or a cron box means holding your PostHog credentials there and writing the queries and the summarising yourself. On Rush each account gets its own session in its own sandbox, the PostHog sign-in stays in Rush's connection rather than in your job's environment, and your backend only sends a prompt and receives a webhook.

Each summary comes with its record. The transcript keeps every query the agent made through the connection and what PostHog returned, so a surprising `trend` or `risk` can be traced to the numbers behind it, and the webhook carries `total_cost_usd` per account, so you know what each summary cost.

## Frequently asked questions

### Can I be sure it only reads from PostHog?

The prompt tells it to read only, and the transcript at `GET /o/{org}/sessions/{id}/messages` lists every tool call with its arguments, so you can check that no create or update tool was used. For a stronger limit, connect PostHog with a user or project whose PostHog permissions are read-only; the connection can then do no more than that user can.

### What if my PostHog project does not use group analytics?

Then there is no group key to filter on. Change the line the prompt reads to whatever identifies an account in your events, such as a `company_id` person or event property, and say in the prompt which property it is. The rest of the request stays the same.

### How do I get the JSON back reliably?

Ask for it in the prompt, as here, and validate `data.result` on your server before using it. If a result does not parse, send a follow-up to the same session with `POST /o/{org}/sessions/{id}/messages` asking for the corrected JSON; the sandbox wakes where it left off, with the queries it already ran.

### Does every run need its own PostHog sign-in?

No. You connect PostHog once with `POST /me/connections`, and every run that names the connection, or every run of a saved agent that lists it, uses that same sign-in. If PostHog revokes it, the connection reads `needs_reauth` and the key's creator signs in again once.
