API surface
Every export of @pradra/sdk in one page. For the underlying HTTP endpoints,
see the API reference.
Client
import { Pradra } from "@pradra/sdk";
const pradra = new Pradra({
baseUrl: "https://your-host", // host only; /api/v1 is appended
apiKey: "aif_….…", // an API token
token: "eyJ…", // …or a JWT access token
orgId: "…", // default for org-scoped calls
});
| Method | Returns |
|---|---|
login(email, password) | TokenPair — also stores it on the client |
refresh(refreshToken) | TokenPair |
predict(capability, inputs, { sessionId?, signal? }) | PredictResult |
predictStream(capability, inputs, { sessionId?, signal? }) | AsyncGenerator<StreamEvent> |
PredictResult is { capability_id, outputs, usage?, cost_usd? }.
Agents
| Method | Notes |
|---|---|
agents.run(capabilityId, { goal, principal?, sessionId? }) | Returns as soon as the run is recorded |
agents.stream(capabilityId, { goal, … , signal? }) | Progress events |
agents.get(runId) | The run with its full trace |
agents.list(capabilityId) | Run history |
agents.wait(runId, { timeoutMs?, intervalMs? }) | Polls to a terminal state |
agents.approve(stepId) | Re-checks the parked call from scratch |
agents.reject(stepId, reason?) | Fed back to the agent as an observation |
wait() treats awaiting_approval as terminal for the caller: nothing
will change until a human acts, so continuing to poll would be a lie.
Sessions
| Method | Notes |
|---|---|
sessions.create({ capabilityId, externalRef?, title?, principal? }) | principal is stamped here and is immutable |
sessions.send(sessionId, inputs) | Generative answers directly; an agent returns run_id to poll |
sessions.messages(sessionId) | Transcript in replay order |
sessions.list({ capabilityId?, workspaceId?, externalRef?, status? }) | |
sessions.get(sessionId) | |
sessions.update(sessionId, { title?, status? }) | Only these two are mutable |
sessions.delete(sessionId) | Agent traces survive |
Knowledge
| Method | Notes |
|---|---|
knowledge.create(input) / knowledge.upsert(input) | Use upsert in deploy scripts |
knowledge.ingest(sourceId, textOrFile) | Async; poll get() to a terminal status |
knowledge.search(sourceId, query, { hybrid?, contextWindow?, topK?, minScore?, sourceVersion?, mode? }) | |
knowledge.get(sourceId) / knowledge.list(workspaceId) |
A hit carries citation, score, match (vector / lexical /
neighbour), page? and content.
Model adapters, pools, tool registry
| Method | Notes |
|---|---|
modelAdapters.create({ name, provider, modelIdentifier, apiKey? | secretId?, … }) | The key is sealed and never returned |
modelAdapters.list(orgId?) | |
modelAdapters.pin(capabilityId, adapterId, orgId?) | Pins the exact model for lineage |
pools.create(name, description?, orgId?) / pools.list(orgId?) | |
tools.createMl(body, orgId?) | ML-backed tools only |
tools.grant(capabilityId, toolId) | Always a separate, human-authored step |
Worker tools do not go through tools.create* — they auto-register from
the worker's manifest.
Serving
import { tool, mlTool, runWorker, mountTools, createWebhookHandler, createToolHandler } from "@pradra/sdk";
tool(def) — { name, description?, sideEffect, permission?, costWeight?, routing?, input?, output?, handler }. input is a field map:
{ order_id: "integer", note: "string?" }. Types: string, text,
category, number, float, double, decimal, integer, int,
boolean, bool, date, datetime, timestamp. A ? suffix means
optional.
runWorker(opts) — { baseUrl, apiKey, orgId, pool, tools, contexts?, instanceId?, handlerTimeoutMs?, heartbeatMs?, onError?, fetch? }. Returns a
Worker with stop() (drains in-flight handlers) and done.
Handler context — the second argument:
| Field | |
|---|---|
principal | The caller's end-user identity. Scope with this, always. |
jobId | Stable across retries — use as your idempotency key |
runId? | The agent run, when it came from one |
attempt | 1 on the first try; only read-only tools are ever retried |
signal | Aborted when the lease is about to lapse or the worker is stopping |
Webhooks — mountTools(app, opts) for Express-like apps,
createWebhookHandler(opts) for standard Request/Response runtimes,
createToolHandler(opts) for raw body + headers. Options: { tools, secret, toleranceSeconds?, replayCacheSize?, path? }.
Streaming events
state · delta · tool_call · tool_result · approval_required · done
· error, each with a type discriminant. An unrecognized event arrives as
{ type, …fields } rather than being dropped — new events are additive within
a stream version, so ignore what you do not know instead of failing on it.
parseSSE(body) is exported if you need to consume a stream you opened
yourself.
Errors
Every non-2xx throws ApiError:
class ApiError extends Error {
status: number; // HTTP status
code: string; // VALIDATION_FAILED, RATE_LIMITED, …
requestId?: string; // quote this when investigating
details?: Array<{ field?: string; issue?: string }>;
}
A terminal error event inside a stream is yielded, not thrown: by then
you may already have received text, and losing it in an exception would be
worse than reporting the failure in order. A stream that never opened throws.
Versioning
The package version tracks the API contract version. Both are 0.1.0 today.
Pin it: the platform's REST surface is versioned at /api/v1, and new fields
are additive within that version.
SDK_VERSION and API_PREFIX are exported if you need to log them.
Next
- Start here if you skipped ahead: SDK overview.
- The full HTTP surface: API reference.