TypeScript SDK
The @klent/sdk package — types, methods, and the batching model.
npm install @klent/sdkThe SDK is a thin client over the HTTP API with one piece of added logic: client-side
event batching so that logEvent never blocks your agent loop.
Most apps want a higher-level entry point. This page documents the raw HTTP-shaped methods (
startExecution,evaluateAction,logEvent). For day-to-day code, the auto-instrumentation helpers —runTool,runAnthropicAgent,runOpenAIAgent— collapse the five-step boilerplate into a single call and run a complete Anthropic or OpenAI tool-use loop end-to-end. See Auto-instrumentation.
Instantiating the client
import { KlentClient } from '@klent/sdk';
const klent = new KlentClient({
apiKey: process.env.KLENT_API_KEY!,
});Options
| Option | Default | Description |
|---|---|---|
apiKey | required | A ak_live_… or ak_test_… key for a project. |
baseUrl | https://api.klent.dev/v1 | Override the API endpoint (e.g. a regional host). |
fetch | globalThis.fetch | Swap the fetch implementation (tests, polyfills). |
maxBatchSize | 50 | Events buffered before a flush. |
flushIntervalMs | 2000 | Time window before flushing a partial batch. |
maxRetries | 3 | Retries for 5xx and 429. Uses exponential backoff + jitter. |
Methods
startExecution(body)
Start a new execution. Synchronous with respect to your code — the SDK awaits the HTTP round-trip.
const execution = await klent.startExecution({
agent_id: 'billing-agent',
metadata: { user_id: 'u_123' },
});
// → { id: 'exec_…', project_id, agent_id, status, started_at, ended_at, metadata }| Param | Type | Notes |
|---|---|---|
agent_id | string | Your identifier for the agent. Free-form. |
metadata | object (optional) | Any JSON-serializable payload; searchable in the dashboard. |
evaluateAction(body)
Check an action against the project's policies before executing it.
const decision = await klent.evaluateAction({
execution_id: execution.id,
tool: 'transfer_funds',
input: { amount: 50_000, currency: 'USD' },
});
// → { decision: 'allow' | 'deny' | 'modify', matched_policy_id, modifications, reason }Klent records the decision on the execution timeline automatically.
logEvent(body)
Append an event to an execution. Non-blocking — buffered and flushed in batches.
klent.logEvent({
execution_id: execution.id,
type: 'action_executed',
payload: { tool: 'transfer_funds', reference: 'tx_abc' },
});| Event type | When to use |
|---|---|
decision | An agent's internal reasoning step (also written by the policy engine on allow/modify). |
action_requested | The LLM has asked to call a tool. |
action_executed | A tool call completed successfully. |
action_blocked | Emitted by Klent automatically when evaluateAction denies. |
action_steered | Emitted by Klent automatically when a steer policy redirects the action. |
pending_approval | Emitted by Klent when an approve policy parks the action for human review. |
approval_vote | Emitted by Klent on each individual reviewer vote (only meaningful for multi-approver policies). |
approval_resolved | Emitted by Klent when a pending action reaches its terminal state (approved or rejected). |
error | A tool call failed or an exception bubbled up. |
getPendingAction(id, options?)
Fetch the current state of a pending action — the row created when an approve policy
parks an action awaiting human review. Returns the resolved status (pending, approved,
rejected) plus, on terminal states, the reviewer note and any last-mile modifications
the reviewer staged.
const row = await klent.getPendingAction('pact_…');
// → { id, status, requested_approvals, votes, resolved_at, resolution_note, ... }
if (row.status === 'pending') {
// still waiting on a human
}options.waitMs opts into a server-side long-poll: the request stays open until the row
resolves or the budget elapses (server caps each call at 30 s; runTool's
approval.wait chains multiple long-polls under the hood for longer budgets).
const row = await klent.getPendingAction('pact_…', { waitMs: 30_000 });Most apps don't call this directly — runTool({ approval: { wait: { timeoutMs } } })
in Auto-instrumentation wraps it. Use the raw method when
you're polling from a different process (e.g. a worker that resumes paused executions).
flush()
Wait until all buffered events have been sent. Call this before a short-lived process exits if you want to be sure the last events landed.
await klent.flush();The SDK also registers a best-effort flush on beforeExit in Node.
Error handling
Every method throws on:
- Missing or invalid API key (401)
- Validation errors (400) — the error message includes the Zod issue path
- Exhausted retries on transient failures (5xx, 429)
Client-side validation errors (e.g. a missing execution_id) surface synchronously before
the HTTP call.
Batching model
logEvent pushes into an in-memory buffer. The buffer is flushed when any of these is true:
buffer.length >= maxBatchSize- More than
flushIntervalMshas elapsed since the last flush with a non-empty buffer flush()is called explicitly- The Node process is about to exit (
beforeExit)
If the flush HTTP call fails, the batch is re-enqueued at the head — nothing is dropped. Retries with backoff are applied per individual event request.
Types
All request/response types come from the @klent/schema package (Zod-inferred) and are
re-exported from @klent/sdk:
import type {
CreateExecutionRequest,
EvaluateActionRequest,
EvaluateActionResponse,
Event,
EventType,
Execution,
LogEventRequest,
PolicyEffect,
PolicyOperator,
} from '@klent/sdk';