@apostl-dev/pulse-sdk
v0.4.1
Published
Server-side analytics for AI agent traffic
Maintainers
Readme
Apostl Pulse SDK
Estimate AI agent visits and see which public website, docs, or API pages they use.
Pulse works as a middleware to track any agent-first endpoint:
- Markdown-supported pages
- llms.txt and llms-full.txt
- API endpoints for agents
- app routes for agents
Pulse groups requests with the same project, trusted IP, and full User-Agent into one journey until a 30-minute inactivity window expires. Installations and origins connected to the same project stay in that journey.
An exact llms.txt visit is immediate evidence. A generic non-browser client such as curl is also counted when it visits two distinct machine-readable surfaces within ten minutes—for example openapi.json and a Markdown page. This catches real tool-driven research even when the client does not announce an agent name.
One-line Install
npm install @apostl-dev/pulse-sdkMIT-licensed source code is on GitHub.
Node
import { createPulse } from '@apostl-dev/pulse-sdk';
const pulse = createPulse({
endpoint: 'https://ingest.apostl.dev',
apiKey: process.env.APOSTL_PULSE_API_KEY,
environment: 'production',
// Unknown /api routes fail closed. Add only routes that are intentionally public.
publicApiPrefixes: ['/api/public'],
});
pulse.observeRequest({
method: request.method,
statusCode: response.statusCode,
headers: request.headers,
ip: clientIp, // resolve this from your trusted server or proxy
url: request.url,
});- Pulse SDK sends the trusted client IP and User-Agent data to Apostl website.
- It records the canonical origin and path only. Query parameters, fragments, request bodies, cookies, and authorization headers are not sent.
- Public health and API GET/HEAD requests are included; auth/account routes, assets, mutations, and 5xx responses are excluded.
/api/mcpand/api/turnstile-configare safe defaults. Other/api/*routes are ignored unless their public prefix is listed inpublicApiPrefixes.- Use
cf-connecting-ipwhen your deployment trusts Cloudflare. - Keep
APOSTL_PULSE_API_KEYin the server runtime; never expose it through browser bundles or public environment variables.
Express
import { pulseExpressMiddleware } from '@apostl-dev/pulse-sdk/express';
app.use(pulseExpressMiddleware(pulse));Next.js
import { withPulse } from '@apostl-dev/pulse-sdk/next';
export const GET = withPulse(pulse, async () => new Response(renderDocs(), {
headers: { 'content-type': 'text/html' },
}));Setup for AI agents
Install the public setup skill:
npx skills add apostl-dev/apostl-skills --skill agent-traffic-analytics -g -yThen ask your agent to connect the exact public HTTPS origin where it is authorized to deploy the server middleware. The skill stores the one-time API key and setup token in an owner-only file instead of printing them.
example.com and similar names are reserved documentation domains, not end-to-end demo targets. Pulse rejects them before issuing credentials. Use a real origin you can deploy, or stop and obtain one from the owner.
Example task:
Use $agent-traffic-analytics to connect my authorized public docs origin and verify a real visit to /llms.txt.The unclaimed setup lasts seven days. A claim URL appears only after the signed public response and the matching genuine event both pass. The owner then signs in with Google, GitHub, or an email magic link; the ingest API key remains active after claim.
Read the full agent setup guide or the exact OpenAPI contract.
Troubleshooting
| Symptom | Check |
| --- | --- |
| No events | Confirm the server has the API key and ingest endpoint, and that requests include a trusted client IP and full User-Agent. |
| Verification is waiting | Deploy the adapter on the public HTTPS origin and keep the selected verification path reachable, then retry the same verify_url. |
| IP addresses are the same | Check your trusted proxy setup (Cloudflare, nginx, etc) |
| Final events are missing | Call await pulse.flush() during graceful shutdown. |
| Need local state | diagnostics() returns bounded counters without credentials or captured request data. |
Support
For setup help, message @SwiftAdviser on Telegram.
