Node.js / TypeScript SDK
Installation
Section titled “Installation”npm install @flow-like/sdkbun add @flow-like/sdkpnpm add @flow-like/sdkOptional peer dependencies
Section titled “Optional peer dependencies”| Package | For | Install |
|---------|-----|---------|
| @lancedb/lancedb | createLanceConnection() | npm install @lancedb/lancedb |
| @langchain/core | LangChain wrappers | npm install @langchain/core |
Creating a Client
Section titled “Creating a Client”import { FlowLikeClient } from "@flow-like/sdk";
// From environment variables (FLOW_LIKE_BASE_URL + FLOW_LIKE_PAT or FLOW_LIKE_API_KEY)const client = new FlowLikeClient();
// Explicit PATconst client = new FlowLikeClient({ baseUrl: "https://api.flow-like.com", pat: "pat_myid.mysecret",});
// Explicit API keyconst client = new FlowLikeClient({ baseUrl: "https://api.flow-like.com", apiKey: "flk_appid.keyid.secret",});
// Auto-detect token typeconst client = new FlowLikeClient({ baseUrl: "https://api.flow-like.com", token: "pat_myid.mysecret", // or "flk_..."});Workflows
Section titled “Workflows”Trigger a workflow (streaming)
Section titled “Trigger a workflow (streaming)”Returns a Server-Sent Events stream:
for await (const event of client.triggerWorkflow( "app-id", "board-id", "start-node-id", { key: "value" },)) { console.log(event.data);}Trigger a workflow (async)
Section titled “Trigger a workflow (async)”Returns immediately with a run ID for polling:
const result = await client.triggerWorkflowAsync( "app-id", "board-id", "start-node-id", { key: "value" },);console.log(result.run_id, result.poll_token);Trigger an event
Section titled “Trigger an event”// Streamingfor await (const event of client.triggerEvent("app-id", "event-id", { key: "value" })) { console.log(event.data);}
// Asyncconst result = await client.triggerEventAsync("app-id", "event-id", { key: "value" });Execution Monitoring
Section titled “Execution Monitoring”// Check run statusconst status = await client.getRunStatus("run-id");console.log(status.status); // "running" | "completed" | "failed"
// Poll for execution eventsconst poll = await client.pollExecution("poll-token", { afterSequence: 0, timeout: 30,});for (const event of poll.events) { console.log(event);}File Management
Section titled “File Management”// List files in an app's storageconst files = await client.listFiles("app-id", { prefix: "uploads/" });
// Upload a fileawait client.uploadFile("app-id", myFile);
// Download a fileconst response = await client.downloadFile("app-id", "path/to/file.pdf");
// Delete a fileawait client.deleteFile("app-id", "path/to/file.pdf");Database / LanceDB
Section titled “Database / LanceDB”Credentials
Section titled “Credentials”// Get resolved credentials (uri + storageOptions ready for LanceDB)const info = await client.getDbCredentials("app-id", "_default", "read");console.log(info.uri, info.storageOptions);
// Get raw presign response (shared_credentials enum, db_path, etc.)const raw = await client.getDbCredentialsRaw("app-id", "_default", "write");Tables
Section titled “Tables”// List tablesconst tables = await client.listTables("app-id");
// Query a table with SQL-like filterconst rows = await client.queryTable("app-id", "my-table", { filter: "age > 25", limit: 10,});LanceDB Connection
Section titled “LanceDB Connection”// Returns a ready-to-use LanceDB Connection objectconst db = await client.createLanceConnection("app-id", "write");
// Now use it with the LanceDB APIconst table = await db.openTable("my-embeddings");const results = await table.search([0.1, 0.2, ...]).limit(10).toArray();The accessMode parameter controls whether you get read-only or read-write credentials:
"read"(default) — read-only access"write"— full read-write access
Chat Completions
Section titled “Chat Completions”Use listLlms() to discover available model bit_id values.
// Non-streamingconst result = await client.chatCompletions( [{ role: "user", content: "Explain quantum computing in one sentence." }], "bit-id-for-gpt4", { temperature: 0.7, max_tokens: 200 },);console.log(result.choices[0].message.content);Streaming
Section titled “Streaming”for await (const chunk of client.chatCompletionsStream( [{ role: "user", content: "Hello!" }], "bit-id-for-gpt4",)) { process.stdout.write(chunk.data);}Usage tracking
Section titled “Usage tracking”const usage = await client.getUsage();console.log(usage.llm_price, usage.embedding_price);Embeddings
Section titled “Embeddings”Use listEmbeddingModels() to discover available embedding model bit_id values.
const result = await client.embed("bit-id-for-embedding", [ "Hello world", "Goodbye world",]);console.log(result.embeddings); // number[][]Model Discovery
Section titled “Model Discovery”// List all remotely-available LLMsconst llms = await client.listLlms();for (const m of llms) { console.log(m.bit_id, m.name, m.provider_name, m.context_length);}
// List all remotely-available embedding modelsconst embeddings = await client.listEmbeddingModels();for (const m of embeddings) { console.log(m.bit_id, m.name, m.vector_length);}
// Search all bits by keywordconst bits = await client.searchBits({ search: "llama", bit_types: ["Llm"] });
// Get a specific bit by IDconst bit = await client.getBit("some-bit-id");Each model returns a ModelInfo object:
interface ModelInfo { bit_id: string; name: string; description: string; provider_name?: string; model_id?: string; context_length?: number; // LLMs only vector_length?: number; // Embeddings only languages?: string[]; tags: string[];}Board Management
Section titled “Board Management”// List all boards in an appconst boards = await client.listBoards("app-id");
// Get a specific boardconst board = await client.getBoard("app-id", "board-id");
// Create or update a boardconst { id } = await client.upsertBoard("app-id", "board-id", { name: "My Board", description: "Processes incoming data",});
// Delete a boardawait client.deleteBoard("app-id", "board-id");
// Pre-run analysis (discover runtime variables, validate the graph)const prerun = await client.prerunBoard("app-id", "board-id");console.log(prerun.runtime_variables);App Management
Section titled “App Management”const apps = await client.listApps();const app = await client.getApp("app-id");const newApp = await client.createApp("My App", "Description");HTTP Sinks
Section titled “HTTP Sinks”Trigger an HTTP sink endpoint on an app:
const result = await client.triggerHttpSink("app-id", "webhook/path", "POST", { event: "user.created", data: { userId: "123" },});Health Check
Section titled “Health Check”const health = await client.health();console.log(health.healthy); // trueLangChain Integration
Section titled “LangChain Integration”Factory methods (recommended)
Section titled “Factory methods (recommended)”The easiest way — creates LangChain-compatible models from your existing client:
// Chat modelconst chatModel = await client.asLangChainChat("your-model-bit-id", { temperature: 0.7, maxTokens: 1024,});
// Embeddingsconst embeddings = await client.asLangChainEmbeddings("your-embedding-bit-id");Standalone usage
Section titled “Standalone usage”import { FlowLikeChatModel, FlowLikeEmbeddings } from "@flow-like/sdk/langchain";
const chatModel = new FlowLikeChatModel({ baseUrl: "https://api.flow-like.com", token: "pat_myid.mysecret", bitId: "your-model-bit-id", temperature: 0.7,});
const embeddings = new FlowLikeEmbeddings({ baseUrl: "https://api.flow-like.com", token: "pat_myid.mysecret", bitId: "your-embedding-bit-id",});With LangChain chains
Section titled “With LangChain chains”import { ChatPromptTemplate } from "@langchain/core/prompts";import { StringOutputParser } from "@langchain/core/output_parsers";
const chatModel = await client.asLangChainChat("your-model-bit-id");
const chain = ChatPromptTemplate .fromMessages([ ["system", "You are a helpful assistant."], ["human", "{input}"], ]) .pipe(chatModel) .pipe(new StringOutputParser());
const response = await chain.invoke({ input: "What is Flow-Like?" });RAG with LangChain
Section titled “RAG with LangChain”const embeddings = await client.asLangChainEmbeddings("your-embedding-bit-id");
// Use with any LangChain vector storeconst vectors = await embeddings.embedDocuments([ "Flow-Like is a visual workflow engine.", "It runs on your device.",]);const queryVector = await embeddings.embedQuery("What runs locally?");Requirements
Section titled “Requirements”- Node.js >= 18 (uses native
fetch) - TypeScript >= 5.0 (for development)
- Module system: ESM (
"type": "module")
Type Exports
Section titled “Type Exports”The SDK exports all relevant types:
import type { Bit, BitSearchQuery, BitType, ModelInfo, SharedCredentials, AwsCredentials, AzureCredentials, GcpCredentials, DbPresignResponse, LanceConnection,} from "@flow-like/sdk";