@bryel/browser
v0.1.10
Published
Client-side bryel tracing for AI-SDK apps that run the agent in the browser. Ships LLM and agent traces to bryel over OTLP/HTTP, non-blocking, with no app-boot cost.
Maintainers
Readme
@bryel/browser
Client-side bryel tracing for AI-SDK apps that run the agent in the browser. Ships LLM and agent traces to bryel over OTLP/HTTP — non-blocking, with no app-boot cost.
npm i @bryel/browserThe Vercel AI SDK emits OpenTelemetry spans in any runtime and accepts a tracer per call, so the cleanest setup adds zero global state:
import { createBryelTracer } from "@bryel/browser";
import { streamText } from "ai";
// build once, where you trace — not at app boot. Lazy-import friendly.
const tracer = createBryelTracer({ apiKey: "bkp_…", serviceName: "studio-agent" });
await streamText({
model,
experimental_telemetry: { isEnabled: true, tracer, metadata: { sessionId, userId } },
prompt,
});Spans batch and flush asynchronously in the background — your model/tool calls
never wait on export, and export failures are swallowed (never thrown into your
app). Gate isEnabled on your own logic to exclude a cohort (e.g. enterprise
tenants); their data never leaves the browser.
If your app has no other OpenTelemetry setup you can register a global provider
instead and drop the tracer:
import { registerBryelBrowser } from "@bryel/browser";
registerBryelBrowser({ apiKey: "bkp_…", serviceName: "studio-agent" });
// then: experimental_telemetry: { isEnabled: true }Eval Runtime
Use createEvalClient when a runner must fetch a platform evalcase, execute it,
and upload the resulting evidence. The suite manifest provides the configured
agentRunnerModels and maxRunDurationSeconds; each model execution becomes
one eval run.
import { createEvalClient } from "@bryel/browser";
const evals = createEvalClient({ apiKey: "bkp_…" });
const manifest = await evals.getCaseManifest({
suiteSlug: "designcritiquebench",
caseKey: "cryptix-risk-alerts",
});
for (const actorModel of manifest.suite.agentRunnerModels) {
const started = await evals.startRun({
caseVersionId: manifest.caseVersionId,
suiteSlug: manifest.suite.slug,
caseKey: manifest.case.key,
runnerKind: "framer-agent",
actorModel,
sessionId: crypto.randomUUID(),
});
const runId = (started as { run: { id: string } }).run.id;
// Run the agent here, then upload its final screenshot.
await evals.uploadArtifactBlob(runId, {
kind: "screenshot",
role: "final_surface",
blob: finalScreenshot,
contentType: "image/png",
});
await evals.finishRun(runId, { status: "succeeded" });
}final_surface must match the case's evidence specification. Use
addRunLog() for runner stdout/stderr and finishRun(..., { status: "failed",
error }) when one model execution fails.
For a local batch runner, getSuiteMissingRunPlan() returns active case
manifests plus only the configured models which have not yet produced a run for
their current case version. This endpoint requires a secret server-side bk_…
key and is intended for local or server-side runners, never a browser bundle:
const plan = await evals.getSuiteMissingRunPlan({
suiteSlug: "designcritiquebench",
runnerKind: "framer-agent",
});Security
Your browser bundle is public. Use a publishable, write-only key (bkp_…),
never a secret bk_ project key. Publishable keys are origin-locked and can only
write traces — they cannot read or query your data.
Server-side?
If your model calls run on the server (Next.js route handlers, server actions),
use @bryel/vercel instead — it instruments the
server runtime with zero client bundle.
MIT © bryel
