Official client for the Gradient Labs API. Written
in TypeScript, ships full type declarations and both ESM and CommonJS builds, and
has zero runtime dependencies (it uses Node's built-in fetch and crypto).
Requires Node.js 20 or newer.
npm install @gradientlabs/clientimport { GradientLabs } from "@gradientlabs/client";
const client = new GradientLabs({ apiKey: process.env.GRADIENT_LABS_API_KEY! });
const conversation = await client.conversations.start({
id: "ticket-12345",
customer_id: "customer-678",
channel: "web",
assignee_type: "AI Agent",
});
console.log(conversation.status);The client is organised into resource namespaces, e.g. client.conversations,
client.tools, client.procedures. There are two API key roles:
- Integration — conversation runtime endpoints (
conversations,outboundConversations,backOfficeTasks,voice). - Management — configuration endpoints (
tools,articles,topics,procedures,handOffTargets,resourceSources,resourceTypes,secrets,notes,terminologySubstitutions,trafficGroups,ipAddresses).
const client = new GradientLabs({
apiKey: "sk_live_...", // required
baseUrl: "https://api.gradient-labs.ai", // optional (this is the default)
webhookSigningKey: "whsec_...", // optional, required to verify webhooks
webhookLeewayMs: 5 * 60 * 1000, // optional, default 5 minutes
timeoutMs: 30_000, // optional per-request timeout
fetch: myFetch, // optional, inject a custom fetch (tests, proxies, instrumentation)
});Every method accepts an optional final argument carrying an AbortSignal for
cancellation:
const controller = new AbortController();
const tools = await client.tools.list({ signal: controller.signal });Non-2xx responses throw an ApiError; client misconfiguration throws a
ConfigurationError. Both extend GradientLabsError.
import { ApiError, ErrorCode } from "@gradientlabs/client";
try {
await client.conversations.get("missing");
} catch (err) {
if (err instanceof ApiError) {
console.error(err.statusCode, err.code, err.message);
if (err.code === ErrorCode.NotFound) {
// handle 404
}
console.error("trace id:", err.traceId); // give this to support
}
}The client never retries failed requests — retry policy is left to you.
List endpoints that paginate return a Page<T> with opaque next/prev
cursors. Use listAll() to iterate every page automatically:
for await (const procedure of client.procedures.listAll()) {
console.log(procedure.name);
}
// or page manually:
const page = await client.procedures.list();
const next = await client.procedures.list({ cursor: page.pageInfo.next });Construct the client with your webhookSigningKey, then verify and parse
incoming requests. Pass the raw request body — the signature is computed over
the exact bytes received.
import { GradientLabs, InvalidWebhookSignatureError } from "@gradientlabs/client";
const client = new GradientLabs({
apiKey: process.env.GRADIENT_LABS_API_KEY!,
webhookSigningKey: process.env.GL_WEBHOOK_SIGNING_KEY!,
});
// Express example (use express.raw() so req.body is the raw payload):
app.post("/webhooks", express.raw({ type: "*/*" }), (req, res) => {
try {
const { event, token } = client.webhooks.parse({
body: req.body, // Buffer
headers: req.headers,
});
switch (event.type) {
case "agent.message":
console.log(event.data.body);
break;
case "conversation.hand_off":
console.log(event.data.reason_code);
break;
// ...other event types
}
res.sendStatus(200);
} catch (err) {
if (err instanceof InvalidWebhookSignatureError) {
res.sendStatus(401);
} else {
res.sendStatus(500);
}
}
});event is a discriminated union on event.type, so narrowing gives you a
fully-typed event.data. The optional X-GradientLabs-Token header is returned
as token.
Supported event types: agent.message, conversation.hand_off,
conversation.finished, action.execute, resource.pull,
back-office-task.complete, back-office-task.hand-off, back-office-task.fail.
See the examples/ directory for runnable examples covering
conversations, tools, articles, procedures, resources, back-office tasks, and a
webhook server.
npm install
npm run build # dual ESM/CJS + type declarations
npm test # vitest (no network required)
npm run lint
npm run typecheck
npm run format