SDK

TypeScript SDK

The @klent/sdk package — types, methods, and the batching model.

npm install @klent/sdk

The 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

OptionDefaultDescription
apiKeyrequiredA ak_live_… or ak_test_… key for a project.
baseUrlhttps://api.klent.dev/v1Override the API endpoint (e.g. a regional host).
fetchglobalThis.fetchSwap the fetch implementation (tests, polyfills).
maxBatchSize50Events buffered before a flush.
flushIntervalMs2000Time window before flushing a partial batch.
maxRetries3Retries 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 }
ParamTypeNotes
agent_idstringYour identifier for the agent. Free-form.
metadataobject (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 typeWhen to use
decisionAn agent's internal reasoning step (also written by the policy engine on allow/modify).
action_requestedThe LLM has asked to call a tool.
action_executedA tool call completed successfully.
action_blockedEmitted by Klent automatically when evaluateAction denies.
action_steeredEmitted by Klent automatically when a steer policy redirects the action.
pending_approvalEmitted by Klent when an approve policy parks the action for human review.
approval_voteEmitted by Klent on each individual reviewer vote (only meaningful for multi-approver policies).
approval_resolvedEmitted by Klent when a pending action reaches its terminal state (approved or rejected).
errorA 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 flushIntervalMs has 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';