JavaScript SDK

@vedika-io/agent-sdk-js is the typed JavaScript / TypeScript client for the Vedika agent harness. Streams turns over the UI Message Stream v1 wire, resumes with Last-Event-ID, and surfaces typed errors.

Install

bash
npm install @vedika-io/agent-sdk-js

In a TypeScript project, also install @types/node (npm install -D @types/node) so the quickstart's process.env type-checks.

Quickstart

ts
import { createVedikaAgent } from "@vedika-io/agent-sdk-js";

const agent = createVedikaAgent({
  baseUrl: "https://harness.example.com",
  apiKey: process.env.VEDIKA_AGENT_KEY!,
});

const thread = await agent.threads.create();
const turn = await agent.threads.sendTurn(thread.id, {
  kind: "text",
  text: "Show my kundli.",
  // A kundli or report turn needs to know whose chart it is.
  birth: { name: "Asha", dateOfBirth: "1990-06-15", timeOfBirth: "10:30", latitude: 28.6139, longitude: 77.209, timezone: "Asia/Kolkata" },
});

for await (const chunk of turn) {
  if (chunk.type === "text-delta") process.stdout.write(chunk.delta);
}
await turn.done();

API

createVedikaAgent(config)

Returns a client with a threads namespace.

FieldTypeDescription
baseUrlstringHarness base URL. Required.
apiKeystringAPI key for the harness-server. Sent as Authorization: Bearer.
fetchtypeof fetchCustom fetch implementation. Defaults to the global fetch.
defaultHeadersRecord<string,string>Default headers added to every request (after auth and idempotency).

agent.threads.create(opts?)

POST /api/v1/agent/threads. Returns a Thread.

FieldTypeDescription
idempotencyKeystringOptional. Default UUID v4.
metadataRecord<string,string>Optional. Stored on the thread.
signalAbortSignalOptional.
headersRecord<string,string>Optional extra headers.

agent.threads.sendTurn(threadId, input, opts?)

POST /threads/{id}/turns with Accept: text/event-stream. Returns a Turn you can iterate.

ts
const turn = await agent.threads.sendTurn(
  thread.id,
  { kind: "text", text: "What does my chart say about career in 2026?" },
  { model: "vedika-swift", memory: { oldMemory: true } },
);

for await (const chunk of turn) {
  if (chunk.type === "text-delta") process.stdout.write(chunk.delta);
}
await turn.done();

agent.threads.resumeTurn(turnId, opts)

GET /turns/{id}/events with Last-Event-ID. Resume a turn after a stream drop.

ts
const lastEventId = await saveCursor(); // e.g. "12.3"
const turn = await agent.threads.resumeTurn(turnId, { lastEventId });

agent.threads.cancelTurn(turnId, opts?)

POST /turns/{id}/cancel. Idempotent. 404 and 410 are treated as success (the turn already finished).

The Turn object

MemberDescription
turnIdThe server-assigned turn id.
threadIdThe thread the turn belongs to.
messageIdA promise resolving to the start.messageId when seen.
for await (chunk of turn)Async iterator over every chunk.
turn.done()Resolves on finish / abort, rejects on error.
turn.cancel()Calls the cancel endpoint.

Memory toggles

Pass memory: { oldMemory, sensitiveInfo } on sendTurn. They are sent as x-vedika-memory-old and x-vedika-memory-sensitive. Both default to false.

Errors

See Errors for the full list. The SDK exposes:

Whose chart

A turn that generates a kundli or a report ("Show my kundli") needs a subject. Send birth on the turn, as in the quickstart. Without it, and without a profile bound to the thread, the harness answers 409 SUBJECT_UNRESOLVED, surfaced as InvalidRequestError with code: "SUBJECT_UNRESOLVED". A plain astrology question needs no birth.

Idempotency

Every create and sendTurn carries an Idempotency-Key header. A fresh UUID v4 is generated when you do not pass one; pass your own to retry safely across processes.

Reserved headers

The SDK refuses to override authorization, accept, content-type, idempotency-key, last-event-id, and x-vercel-ai-ui-message-stream.