@kravalabs/api-client
v0.2.0
Published
TypeScript client for Krava — privacy-first AI agents and chat
Maintainers
Readme
@kravalabs/api-client
TypeScript SDK for Krava — privacy-first AI agents and chat. Zero dependencies, pure fetch.
Install
pnpm add @kravalabs/api-clientTwo Ways to Build on Krava
Track 1 — Chat Agent (custom AI persona)
Build a custom AI companion (therapist, coach, legal advisor, exec assistant) powered by Krava's zero-retention inference via Tinfoil.
import { createKravaClient, parseAgentChatStream } from "@kravalabs/api-client";
const client = createKravaClient({
baseUrl: "https://krava.io",
getToken: () => myAuthToken,
});
// 1. Get gateway credentials (requires an active agent)
const { gatewayToken } = await client.agent.getGatewayCredentials();
// 2. Chat with a custom persona — the `system` field is your agent's identity
const response = await client.v1.agentChat(
{
model: "claude-sonnet-4-6-20250514",
messages: [{ role: "user", content: "I'm feeling overwhelmed today" }],
system: "You are a compassionate pregnancy companion. Help with emotional support, diet planning, and wellness tracking.",
stream: true,
},
{ gatewayToken }
);
// 3. Stream the response
for await (const event of parseAgentChatStream(response)) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
process.stdout.write((event.delta as { text: string }).text);
}
}
// 4. Save a memory for continuity across sessions
await client.memory.save(
"User is in third trimester, feeling anxious about delivery",
"insight"
);
// 5. Recall memories in future conversations
const { memories } = await client.memory.search("pregnancy");Available models:
claude-sonnet-4-6-20250514,claude-haiku-4-5-20251001(Anthropic)kimi-k2-5,deepseek-r1,gpt-oss(Tinfoil — zero-retention encrypted inference)
Track 2 — OpenClaw Autonomous Bot
Provision a full autonomous agent pod with Telegram, web search, email, and calendar capabilities.
import { createKravaClient } from "@kravalabs/api-client";
const client = createKravaClient({
baseUrl: "https://krava.io",
getToken: () => myAuthToken,
});
// 1. Provision with a custom persona
const { instanceId } = await client.agent.provision({
telegramBotToken: "123456:ABC-DEF...",
promoCode: "HACKATHON2026",
region: "EU-RO-1",
persona: "You are a luxury hotel concierge. Help guests with reservations, local recommendations, and travel arrangements. Be warm, professional, and proactive.",
});
// 2. Poll until ready for pairing
let status;
do {
await new Promise((r) => setTimeout(r, 5000));
status = await client.agent.getStatus();
} while (status.status !== "none" && status.status !== "pairing" && status.status !== "ready");
// 3. Pair with Telegram
if ("status" in status && status.status === "pairing") {
await client.agent.pair({ pairingCode: "123456" });
}
// Your bot is now live on Telegram with the persona you defined!Verify your integration
The SDK ships a doctor CLI that runs a live probe — provisions a test user, streams a chat response, and prints redacted evidence:
KRAVA_APP_KEY=your_app_key npx @kravalabs/api-client doctorAPI Reference
Client Setup
const client = createKravaClient({
baseUrl: "https://krava.io", // Krava instance URL
getToken: () => token, // x-privy-token for auth
credentials: "include", // default: "include" (session cookies)
});Agent Lifecycle
| Method | Description |
|--------|-------------|
| client.agent.getStatus() | Get agent status + health |
| client.agent.provision(body) | Provision a new agent pod |
| client.agent.pair({ pairingCode }) | Complete Telegram pairing |
| client.agent.destroy() | Destroy agent pod |
| client.agent.getGatewayCredentials() | Get gateway token for chat API |
Memory (cross-session continuity)
| Method | Description |
|--------|-------------|
| client.memory.search(query?, limit?) | Search memories by keyword |
| client.memory.save(content, contentType?) | Save insight/goal/theme |
| client.memory.clear() | Delete all memories |
Chat (hosted LLM proxy)
| Method | Description |
|--------|-------------|
| client.v1.agentChat(body, { gatewayToken }) | Send message, get Response |
| parseAgentChatStream(response) | Parse SSE into async iterator |
SSE Event Types
for await (const event of parseAgentChatStream(response)) {
switch (event.type) {
case "content_block_delta":
// event.delta.type === "text_delta" → text chunk
// event.delta.type === "input_json_delta" → tool call JSON chunk
break;
case "content_block_start":
// event.content_block.type === "text" | "tool_use"
break;
case "message_delta":
// event.delta.stop_reason === "end_turn" | "tool_use" | "max_tokens"
break;
case "message_stop":
// Stream complete
break;
}
}Errors
Failed responses throw PrivyApiError:
import { PrivyApiError } from "@kravalabs/api-client";
try {
await client.agent.getStatus();
} catch (err) {
if (err instanceof PrivyApiError) {
console.error(err.status, err.code, err.message);
}
}OpenAPI
A machine-readable OpenAPI 3.1 contract ships with the package at docs/openapi.yaml.
Development
pnpm install
pnpm --filter @kravalabs/api-client build
pnpm --filter @kravalabs/api-client test