SDK quickstart
Drop the SDK into your signup handler and read the briefing.
This guide makes a createActor call and reads the resulting briefing using @qualiaso/sdk.
1. Create a client instance
Do this near app startup. Hold the instance somewhere you can reach from request handlers (a singleton module, your DI container, etc.).
// app/qualia.ts
import { Qualia } from "@qualiaso/sdk";
export const qualia = new Qualia({
auth: () => process.env.QUALIA_API_KEY!,
});For multi-tenant servers, instantiate per request with the right bearer token instead. Each instance owns its own underlying client.
2. Create an actor on signup
createActor is idempotent on email, scoped to your organization. Call it from your signup handler. New emails return a created actor and enqueue enrichment; existing emails return already_exists with the original actorId.
// app/signup-handler.ts
import { qualia } from "./qualia";
const { data, error } = await qualia.createActor({
body: {
email: "anna@ridgeline.co",
name: "Anna Park",
source: "product_signup",
},
});
if (error) throw error;
const { actorId, status } = data;
console.log(status, actorId);status is "created" for a new actor (enrichment is enqueued) or "already_exists" if one with the same email is already on file.
3. Read the briefing
In production, poll the actor until status === "enriched" (success) or "failed" (terminal failure). For a smoke test this is enough:
// app/read-briefing.ts
const { data: actor, error } = await qualia.getActor({
path: { actorId },
});
if (error) throw error;
console.log(actor.status, actor.intelligence);4. Handle blocked actors
When status === "failed", the response carries a failureReason describing what went wrong. Five values:
failureReason | What it means | What to do |
|---|---|---|
quota_exceeded | Your org hit its monthly cap. No actors are enriched until the cap resets or is raised. | Visit /admin to raise the cap, or wait until next month. |
invalid_email | The address failed format validation. Treat the same as 422 from your own form validators. | Ask the user to retype their email. |
disposable_email | The domain is a disposable / throwaway / parked provider. The address won't reach a person. | Skip this signup. Optionally reject at your form layer too. |
suspicious_email | The local-part or signup pattern looks bot-generated. | Skip, or flag for human review depending on how aggressive you want to be. |
insufficient_context | Personal-email signup with neither a name nor any company hint. | Re-call with name (or metadata.company) - see below. |
Personal-email signups
Personal addresses (gmail.com, proton.me, yahoo.com, ...) need at least one of name or a company hint in metadata for us to do useful research. Without those, the agent has nothing to search for and would produce a near-empty briefing.
Recommended metadata keys: company, companyName, employer, organization, title, jobTitle, role, position, linkedin, linkedinUrl, workEmail. Snake_case, camelCase, kebab-case, and PascalCase variants of any of these are accepted.
If your first call was missing context and got failureReason: "insufficient_context", just re-call with the same email plus the missing field. The actor transitions back to pending and enrichment is re-enqueued automatically:
// app/signup-handler.ts
// First call (e.g. before you collected company info on the form):
await qualia.createActor({
body: { email: "alex@gmail.com" },
}); // status: created, but enrichment is later marked failed
// Later, after the user fills out their company:
await qualia.createActor({
body: {
email: "alex@gmail.com",
name: "Alex Reyes",
metadata: { company: "Acme Robotics" },
},
}); // status: already_exists, but enrichment is automatically re-enqueuedRe-call rescue applies to all eligibility-related failure reasons. It does NOT apply to quota_exceeded: the cap is org-level and retrying won't help.
Next
- Errors and retries. The discriminated error model and a recommended retry policy.
- API reference. Every operation page with a
@qualiaso/sdksnippet alongside curl. - Concepts. The meaning behind
actorandbriefing.