tuul-sdk-ts
v0.2.6
Published
TypeScript SDK for Tuul agent runtime, SSE streaming, triggers, and embed helpers.
Readme
Tuul SDK TS
TypeScript-first SDK for Tuul agent runtimes, streaming responses, local tool orchestration, widget configuration, and React integration.
Install
npm install tuul-sdk-ts
# or
pnpm add tuul-sdk-ts
# or
yarn add tuul-sdk-tsFor React apps,
react18+ must also be installed.
Package entry points
- Core SDK:
tuul-sdk-ts - React support:
tuul-sdk-ts/react
Quick start
import { TuulClient } from "tuul-sdk-ts";
const client = new TuulClient({
agentId: "your-agent-id",
apiKey: "your-sdk-api-key",
defaultSessionId: "browser-session-1",
});
const response = await client.generate({
input: "Summarize the latest customer support queue in three bullets.",
});
console.log(response.text);Core usage
Create a client
const client = new TuulClient({
agentId: "your-agent-id",
apiKey: "your-sdk-api-key",
widgetKey: "your-widget-key", // optional
defaultSessionId: "browser-session-1",
});Generate text
const response = await client.generate({
input: "Write a short product update for our engineering team.",
stream: false,
});
console.log(response.text);Stream responses
for await (const event of client.stream({
input: "Write a launch announcement and think step by step.",
localTools: [
{
name: "local_weather_lookup",
description: "Looks up locally cached weather data on the client.",
inputSchema: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"],
},
async execute(input) {
const args = input as { city: string };
return { city: args.city, forecast: "Sunny" };
},
},
],
})) {
if (event.type === "delta" && event.text) {
process.stdout.write(event.text);
}
if (event.type === "tool-call") {
console.log("Tool call requested:", event.toolName, event.input);
}
if (event.type === "tool-result") {
console.log("Tool result received:", event.toolName, event.output);
}
if (event.type === "finish") {
console.log("Finish reason:", event.finishReason);
}
}When localTools are provided, the SDK executes the matching local tool and sends the result back to the runtime automatically. The stream will continue once the local result is delivered.
Prompt helper
Use prompt() to automatically select streaming or non-streaming behavior.
const result = await client.prompt({
input: "Create a short summary.",
stream: false,
});Local tools
Local tools let your application execute client-side logic when the model requests it. The SDK now supports seamless local-tool streaming: the runtime emits a tool-call, the client executes the local tool, and the SDK submits the result back to the runtime automatically.
const response = await client.generate({
input: "Use the local weather lookup tool for Lagos and tell me what to wear.",
stream: false,
localTools: [
{
name: "local_weather_lookup",
description: "Looks up locally cached weather data on the client.",
inputSchema: {
type: "object",
properties: {
city: { type: "string" },
},
required: ["city"],
},
async execute(input) {
const args = input as { city: string };
return {
city: args.city,
forecast: "Humid with scattered clouds",
temperatureC: 30,
};
},
},
],
});
console.log(response.text);When the model emits a recognized tool call, the SDK executes the tool and continues the request automatically.
Orchestrated local tools example
const response = await client.generate({
input: "Check the ticket queue, get customer health, and draft a priority summary.",
stream: false,
localTools: [
{
name: "queue_snapshot",
description: "Returns the latest support queue grouped by severity.",
inputSchema: { type: "object", properties: {} },
async execute() {
return { open: 14, urgent: 3 };
},
},
{
name: "customer_health_lookup",
description: "Looks up CRM health signals for a customer id.",
inputSchema: {
type: "object",
properties: {
customerId: { type: "string" },
},
required: ["customerId"],
},
async execute(input) {
const args = input as { customerId: string };
return { customerId: args.customerId, plan: "enterprise", renewalRisk: "medium" };
},
},
],
});
console.log(response.text);Direct tool calls
The SDK also supports explicit tool execution with callTool().
const result = await client.callTool("weather.lookup", {
params: {
city: "Lagos",
units: "metric",
},
});
console.log(result.toolName, result.result);Widget support
The same client can fetch public widget information.
const widgetConfig = await client.getWidgetConfig();
const widgetTheme = await client.getWidgetTheme();
const widgetEmbed = await client.getWidgetEmbed();
console.log(widgetConfig.launcherLabel);
console.log(widgetTheme.primaryAccentToken);
console.log(widgetEmbed.snippet);React integration
import { TuulAgentProvider, useTuulChat, TuulAgentFab, TuulAgentWidget } from "tuul-sdk-ts/react";
function App() {
return (
<TuulAgentProvider
config={{
agentId: "your-agent-id",
apiKey: "your-sdk-api-key",
defaultSessionId: "browser-session-1",
}}
>
<ConversationPanel />
</TuulAgentProvider>
);
}useTuulChat() example
import { useTuulChat } from "tuul-sdk-ts/react";
function ConversationPanel() {
const { messages, conversations, send, loadConversations, renameConversation, deleteConversation } = useTuulChat({
sessionId: "browser-session-1",
autoLoadConversations: true,
});
return (
<div>
<button onClick={() => void loadConversations()}>Refresh conversations</button>
<button onClick={() => void send("Hello from React")}>Send greeting</button>
<pre>{JSON.stringify(messages, null, 2)}</pre>
</div>
);
}JavaScript / CommonJS usage
This package publishes both ESM and CommonJS builds.
const { TuulClient } = require("tuul-sdk-ts");
const client = new TuulClient({
agentId: "your-agent-id",
apiKey: "your-sdk-api-key",
defaultSessionId: "browser-session-1",
});Additional helpers
The SDK exports low-level streaming helpers:
collectRuntimeStreamcollectStreamTextparseSseStream
Use these when you need manual SSE handling or a custom streaming pipeline.
Error handling
import { TuulSdkError } from "tuul-sdk-ts";Handle API errors consistently using the SDK error type.
Included examples
The repository contains example files in examples/:
01-basic-generate.ts02-stream-runtime.ts03-local-tools.ts04-widget-and-security.ts05-conversations-and-react.tsx06-tool-call-basic.ts07-tool-call-session.ts
Notes
- Use
defaultSessionIdto keep requests in the same session. widgetKeyis required for widget endpoint access.- Local tools run only when the model emits a matching tool call.
- This SDK is built for both TypeScript and JavaScript consumers.
