@humane-ai/sdk
v0.3.1
Published
Behavioral intelligence for your LLM apps. Every AI should know who it's talking to.
Maintainers
Readme
@humane-ai/sdk
Every AI should know who it's talking to.
TypeScript/JavaScript client for the Humane AI behavioral intelligence platform. Works in Node 18+, Deno, Bun, and modern browsers.
Install
npm i @humane-ai/sdk
# or
pnpm add @humane-ai/sdkQuick start
import { HumaneClient } from "@humane-ai/sdk";
const client = new HumaneClient({ apiKey: process.env.HUMANE_KEY! });
const r = await client.process({
userId: "patient_42",
message: "I'm really struggling with this",
});
console.log(r.response); // AI response shaped by behavioral context
console.log(r.user.mood); // 0.28
console.log(r.safety.action); // "PROCEED" | "HOLD" | "BLOCK"
console.log(r.analysis?.reasons); // ["'struggling' → sadness (negative)", …]
console.log(r.analysis?.signal_magnitude); // "normal" | "strong" | "pivot"
console.log(r.analysis?.mood_delta); // -0.4 — bigger snap signal
// Safety detail when the gate caught something
for (const m of r.safety.matched ?? []) console.log(m.phrase, m.category);
if (r.safety.override) console.log(r.safety.override); // e.g. "combo_a_force_block"
// A/B experiments assigned for this request
for (const ex of r.experiments ?? []) {
console.log(ex.experiment_name, "→", ex.variant_name);
}One-line OpenAI wrap
import OpenAI from "openai";
import { wrap } from "@humane-ai/sdk";
const client = wrap(new OpenAI(), { humaneKey: process.env.HUMANE_KEY! });
const resp = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "I'm anxious" }],
user: "patient_42",
});
console.log(resp.choices[0].message.content); // standard OpenAI response
console.log((resp as any).humane.user.mood); // 0.28
console.log((resp as any).humane.safety.action); // PROCEED | BLOCKIf Humane's safety gate returns BLOCK, we short-circuit before hitting OpenAI — no tokens spent on blocked messages.
Streaming
for await (const ev of client.stream({ userId: "u1", message: "tell me more" })) {
if (ev.type === "metadata") console.log("state:", ev.data);
if (ev.type === "token") process.stdout.write(ev.data.content);
if (ev.type === "final") console.log("\nfull:", ev.data.response);
}Webhook signature verification
import { verifyWebhookSignature } from "@humane-ai/sdk/webhook";
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.header("X-Humane-Signature");
if (!verifyWebhookSignature(process.env.HUMANE_WEBHOOK_SECRET!, req.body, sig)) {
return res.status(401).end();
}
const event = JSON.parse(req.body.toString("utf8"));
// … handle event
res.sendStatus(200);
});Idempotency
Retrying a transient network failure is safe — pass the same key and same body:
await client.process({
userId: "u1",
message: "hi",
idempotencyKey: "req_8f3c...",
});License
See LICENSE. Commercial use requires a contract; non-commercial/research use is free.
