Quickstart
Record your agent's first model call and see it in the console. Pick your language in any code block and every block on every page follows it.
You need an organisation and an API key with Write ticked, from the API keys page.
Install the recorder
pip install techbridge-agentpulse
npm install techbridge-agentpulse
go get github.com/techbridgeinnovation/agentpulse/recorder
The recorder has no dependencies of its own. The TypeScript recorder needs Node 18.18 or newer.
To have your coding agent do the rest of this page for you, install the Agent Pulse plugin in Claude Code with /plugin install agentpulse --marketplace techbridgeinnovation/agentpulse, or copy the Cursor rule into your project's .cursor/rules/, then ask it to add Agent Pulse to your service.
Set four settings
Copy them from the Connect page into your agent's environment. The recorder stops at startup if one is missing, so a mistake shows straight away.
AP_GATEWAY=gateway.agentspulse.ai
AP_API_KEY=organisations/northwind/apiKeys/7f2c
AP_API_SECRET=<shown once when the key is created>
AP_AGENT=organisations/northwind/agents/support-triage
| Setting | What it is |
|---|---|
AP_GATEWAY |
The address on the Connect page. |
AP_API_KEY |
The key's name. It says which organisation the spend belongs to, and is not secret. |
AP_API_SECRET |
The secret, shown once. Keep it in your secrets manager. |
AP_AGENT |
A name you choose for this agent, under your organisation. |
One key serves every agent in the organisation. Nothing registers an agent: it appears after its first call.
Connect, once where your agent starts
import agentpulse
reporter = agentpulse.connect(service="support-triage")
import { connect } from "techbridge-agentpulse";
const reporter = connect("support-triage");
key := os.Getenv("AP_API_KEY")
organisation := recorder.OrganisationOfKey(key)
agent := os.Getenv("AP_AGENT")
conn, err := recorder.DialWithKey(os.Getenv("AP_GATEWAY"), key, os.Getenv("AP_API_SECRET"))
if err != nil || organisation == "" || agent == "" {
log.Fatal("AP_GATEWAY, AP_API_KEY, AP_API_SECRET and AP_AGENT must all be set")
}
rec := recorder.New(recorder.Config{
Sinks: []recorder.Sink{recorder.NewGRPCSink(conn, organisation)},
})
defer rec.Close(ctx)
reporter := rec.For(recorder.Attribution{Agent: agent, Service: "support-triage"})
The service name is how this process shows up in the console. Records are sent in the background, in batches.
Record your model calls
Wrap your model client once, where you create it. Every call through it is recorded from then on.
from openai import OpenAI
from anthropic import Anthropic
from google import genai
gpt = OpenAI(http_client=reporter.openai_http_client())
claude = Anthropic(http_client=reporter.anthropic_http_client())
gemini = genai.Client(http_options=reporter.genai_http_options())
import { wrapLanguageModel } from "ai";
import { openai } from "@ai-sdk/openai";
const model = wrapLanguageModel({ model: openai("gpt-5"), middleware: reporter.aiSdkMiddleware() });
gemini, err := genai.NewClient(ctx, &genai.ClientConfig{Backend: genai.BackendVertexAI})
reporter.InstrumentGenAI(gemini)
claude := anthropic.NewClient(option.WithMiddleware(reporter.AnthropicMiddleware()))
gpt := openai.NewClient(option.WithMiddleware(reporter.OpenAIMiddleware()))
Built on a framework instead? See Google ADK, LangChain, OpenAI Agents SDK or the LiteLLM proxy.
Say who the work is for
Once per request, where you have checked the sign-in. Every call inside is counted against that request, customer and user.
with agentpulse.scope(request=request_id, workspace=customer_id, user=agentpulse.User(id=user_id)):
handle(request)
import { scope } from "techbridge-agentpulse";
await scope({ request: requestId, workspace: customerId, user: { id: userId } }, () => handle(req));
ctx = recorder.WithUser(recorder.WithRequest(ctx, requestID), recorder.User{ID: userID})
ctx = recorder.WithWorkspace(ctx, customerID)
Leave out the workspace if your product has no customers of its own. See Track cost per customer and user.
Run your agent
Make one model call as you normally would. The agent appears on the Agents page with the call's model, tokens and cost.
To check from code, read the recorder's counts, for example when the process stops:
stats = reporter.recorder.stats()
print(f"recorded {stats.recorded}, delivered {stats.delivered}, dropped {stats.dropped}")
const s = reporter.recorder.stats();
console.log(`recorded ${s.recorded}, delivered ${s.delivered}, dropped ${s.dropped}`);
s := rec.Stats()
log.Printf("recorded %d, delivered %d, dropped %d", s.Recorded, s.Delivered, s.Dropped)
dropped above zero means the recorder's queue filled and some calls were not recorded. It never slows your agent down to avoid that.