Skip to main content

TypeScript SDK

Overview

The iFlow SDK is an SDK for programmatic interaction with iFlow CLI. It can be quickly integrated into your business system, combining with workflow and other intelligent agent extensions to enable developers to build AI-driven applications with conversation, tool execution, and task planning capabilities, giving business systems AI capabilities. Currently supports Python, Java, TypeScript, and Android versions.

✨ Core Feature: SDK automatically manages iFlow processes - no manual configuration needed!

System Requirements

  • Node.js: 22.0 or higher
  • TypeScript: 4.5 or higher (optional, but recommended)
  • iFlow CLI: 0.2.24 or higher
  • Operating System: Windows, macOS, Linux

Installation

npm install --save @iflow-ai/iflow-cli-sdk

Quick Start

Basic Example

The SDK automatically detects and starts iFlow processes without manual configuration:

import { IFlowClient, MessageType } from "@iflow-ai/iflow-cli-sdk";

async function main() {
const client = new IFlowClient();

try {
// SDK automatically handles:
// 1. Detect if iFlow is installed
// 2. Start iFlow process (if not running)
// 3. Find available port and establish connection
await client.connect();
await client.sendMessage("Hello, iFlow!");

for await (const message of client.receiveMessages()) {
if (message.type === MessageType.ASSISTANT && message.chunk.text) {
console.log(message.chunk.text);
} else if (message.type === MessageType.TASK_FINISH) {
break;
}
}
} finally {
await client.disconnect();
}
}

main().catch(console.error);

Simple Query

The simplest way to use the SDK is through the query function:

import { query } from "@iflow-ai/iflow-cli-sdk";

async function main() {
const response = await query("What is the capital of France?");
console.log(response); // Output: The capital of France is Paris.
}

main().catch(console.error);

Core Concepts

IFlowClient

IFlowClient is the main interface for interacting with iFlow CLI, managing the WebSocket connection lifecycle:

import { IFlowClient, IFlowOptions } from "@iflow-ai/iflow-cli-sdk";

async function main() {
// Using default configuration (automatic process management)
const client = new IFlowClient();

try {
await client.connect();
await client.sendMessage("Your question");

for await (const message of client.receiveMessages()) {
// Process messages
}
} finally {
await client.disconnect();
}

// Using custom configuration
const customOptions: IFlowOptions = {
url: "ws://localhost:8090/acp", // WebSocket URL
autoStartProcess: true, // Auto-start iFlow
timeout: 30000, // Timeout in milliseconds
};
const customClient = new IFlowClient(customOptions);

try {
await customClient.connect();
await customClient.sendMessage("Your question");

for await (const message of customClient.receiveMessages()) {
// Process messages
}
} catch {
await customClient.disconnect();
}
}

main().catch(console.error);

Message Types

The SDK supports multiple message types corresponding to different iFlow protocol responses:

AssistantMessage - AI Assistant Response

Includes AgentInfo support for accessing detailed agent information:

import { IFlowClient, MessageType, AgentInfo } from "@iflow-ai/iflow-cli-sdk";

async function handleAssistantMessage() {
const client = new IFlowClient();

try {
await client.connect();
await client.sendMessage("Please introduce TypeScript");

for await (const message of client.receiveMessages()) {
if (message.type === MessageType.ASSISTANT && message.chunk.text) {
console.log(message.chunk.text);

// Access agent info (if available)
if (message.agentInfo) {
console.log(`Agent ID: ${message.agentInfo.agentId}`);
if (message.agentInfo.taskId) {
console.log(`Task ID: ${message.agentInfo.taskId}`);
}
if (message.agentInfo.agentIndex) {
console.log(`Agent Index: ${message.agentInfo.agentIndex}`);
}
}
} else if (message.type === MessageType.TASK_FINISH) {
break;
}
}
} finally {
await client.disconnect();
}
}

handleAssistantMessage().catch(console.error);

ToolCallMessage - Tool Execution

Tool call messages now include AgentInfo and tool name:

import { IFlowClient, MessageType, ToolCallStatus } from "@iflow-ai/iflow-cli-sdk";

async function handleToolCalls() {
const client = new IFlowClient();

try {
await client.connect();
// Note: This example demonstrates how to view tool call messages
// iFlow will request full path and content to create files
await client.sendMessage("List files in current directory");

for await (const message of client.receiveMessages()) {
if (message.type === MessageType.TOOL_CALL) {
console.log(`Status: ${message.status}`);

// New: Tool name
if (message.toolName) {
console.log(`Tool Name: ${message.toolName}`);
}

// Access agent info
if (message.agentInfo) {
console.log(`Agent ID: ${message.agentInfo.agentId}`);
}
} else if (message.type === MessageType.TASK_FINISH) {
break;
}
}
} finally {
await client.disconnect();
}
}

handleToolCalls().catch(console.error);

PlanMessage - Task Planning

import { IFlowClient, MessageType } from "@iflow-ai/iflow-cli-sdk";

async function showPlan() {
const client = new IFlowClient();

try {
await client.connect();
await client.sendMessage("Help me create a TypeScript project structure");

for await (const message of client.receiveMessages()) {
if (message.type === MessageType.PLAN) {
console.log("Execution plan:");
for (const entry of message.entries) {
const statusIcon = entry.status === "completed" ? "✅" : "⏳";
console.log(`${statusIcon} [${entry.priority}] ${entry.content}`);
}
} else if (message.type === MessageType.TASK_FINISH) {
break;
}
}
} finally {
await client.disconnect();
}
}

showPlan().catch(console.error);

TaskFinishMessage - Task Completion

import { IFlowClient, MessageType, StopReason } from "@iflow-ai/iflow-cli-sdk";

async function checkCompletion() {
const client = new IFlowClient();

try {
await client.connect();
await client.sendMessage("Calculate 1+1");

for await (const message of client.receiveMessages()) {
if (message.type === MessageType.ASSISTANT && message.chunk.text) {
process.stdout.write(message.chunk.text);
} else if (message.type === MessageType.TASK_FINISH) {
console.log(); // New line
if (message.stopReason === StopReason.END_TURN) {
console.log("Task completed normally");
} else if (message.stopReason === StopReason.MAX_TOKENS) {
console.log("Reached maximum token limit");
}
break; // TaskFinishMessage indicates conversation end
}
}
} finally {
await client.disconnect();
}
}

checkCompletion().catch(console.error);

Common Use Cases

Interactive Chatbot

import * as readline from "readline";
import { IFlowClient, MessageType } from "@iflow-ai/iflow-cli-sdk";

async function chatbot() {
console.log("iFlow Chatbot (type 'quit' to exit)");
console.log("-".repeat(50));

const client = new IFlowClient();

try {
await client.connect();

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

while (true) {
const userInput = await new Promise<string>((resolve) => {
rl.question("\nYou: ", resolve);
});

if (userInput.toLowerCase() === "quit" || userInput.toLowerCase() === "exit" || userInput.toLowerCase() === "q") {
console.log("Goodbye!");
break;
}

await client.sendMessage(userInput);

process.stdout.write("iFlow: ");
for await (const message of client.receiveMessages()) {
if (message.type === MessageType.ASSISTANT && message.chunk.text) {
process.stdout.write(message.chunk.text);
} else if (message.type === MessageType.TASK_FINISH) {
console.log(); // New line
break;
}
}
}

rl.close();
} finally {
await client.disconnect();
}
}

chatbot().catch(console.error);

Advanced Configuration

Manual Process Management

If you need to manually manage the iFlow process:

import { IFlowClient, MessageType } from "@iflow-ai/iflow-cli-sdk";

async function manualProcessExample() {
const client = new IFlowClient({
autoStartProcess: false, // Disable automatic process management
url: "ws://localhost:8090/acp", // Connect to existing iFlow
});

try {
await client.connect();
await client.sendMessage("Your question");

for await (const message of client.receiveMessages()) {
if (message.type === MessageType.ASSISTANT && message.chunk.text) {
process.stdout.write(message.chunk.text);
} else if (message.type === MessageType.TASK_FINISH) {
break;
}
}
} finally {
await client.disconnect();
}
}

manualProcessExample().catch(console.error);

Note Manual mode requires you to start iFlow separately:

iflow --experimental-acp --port 8090

Error Handling

The SDK provides detailed error handling mechanisms:

import { IFlowClient, ConnectionError, TimeoutError, MessageType } from "@iflow-ai/iflow-cli-sdk";

async function errorHandlingExample() {
const client = new IFlowClient();

try {
await client.connect();
await client.sendMessage("Test");

for await (const message of client.receiveMessages()) {
if (message.type === MessageType.ASSISTANT && message.chunk.text) {
console.log(message.chunk.text);
} else if (message.type === MessageType.TASK_FINISH) {
break;
}
}
} catch (error) {
if (error instanceof ConnectionError) {
console.error(`Connection error: ${error.message}`);
} else if (error instanceof TimeoutError) {
console.error(`Timeout error: ${error.message}`);
} else {
console.error(`Unknown error: ${error}`);
}
} finally {
await client.disconnect();
}
}

errorHandlingExample().catch(console.error);

API Reference

Core Classes

Class NameDescription
IFlowClientMain client class for managing iFlow connections
RawDataClientClient for accessing raw protocol data

Message Types

Message TypeDescriptionMain Properties
AssistantMessageAI assistant text responsechunk.text, agentId, agentInfo
ToolCallMessageTool execution request and statuslabel, status, toolName, agentInfo
PlanMessageStructured task planentries (containing content, priority, status)
TaskFinishMessageTask completion signalstopReason
UserMessageUser messagechunks
ErrorMessageError messagecode, message

AgentInfo - Agent Information

The AgentInfo type shows detailed information parsed from iFlow agent IDs:

interface AgentInfo {
agentId: string; // Complete agent ID
agentIndex?: number; // Agent index in task
taskId?: string; // Task or instance ID
timestamp?: number; // Creation timestamp
}

Configuration Options

The IFlowOptions interface provides rich configuration options:

interface IFlowOptions {
url?: string; // WebSocket URL
cwd?: string; // Working directory
timeout?: number; // Timeout in milliseconds
logLevel?: "DEBUG" | "INFO" | "WARN" | "ERROR"; // Log level

processStartPort?: number; // Process start port
autoStartProcess?: boolean; // Auto-start process

authMethodId?: string; // Authentication method ID
authMethodInfo?: AuthMethodInfo; // Authentication info

mcpServers?: MCPServerConfig[]; // MCP server configuration
hooks?: HookConfigs; // Hook configuration
commands?: CommandConfig[]; // Command configuration
agents?: SubAgentConfig[]; // Sub-agent configuration
sessionSettings?: SessionSettings; // Session settings

permissionMode?: "auto" | "manual" | "selective"; // Permission mode
autoApproveTypes?: string[]; // Auto-approve types

fileAccess?: boolean; // File access permission
fileMaxSize?: number; // Maximum file size
fileReadOnly?: boolean; // Read-only mode
fileAllowedDirs?: string[]; // Allowed directories
}

interface AuthMethodInfo {
apiKey?: string;
baseUrl?: string;
modelName?: string;
}

interface MCPServerConfig {
name: string;
command: string;
args: string[];
env: { name: string; value: string }[];
}

interface CommandConfig {
name: string;
content: string;
}

interface SubAgentConfig {
agentType: string;
whenToUse: string;
allowedTools: string[];
systemPrompt: string;
name?: string;
description?: string;
allowedMcps?: string[];
proactive?: boolean;
location?: "global" | "project";
model?: string;
isInheritTools?: boolean;
isInheritMcps?: boolean;
}

interface SessionSettings {
system_prompt?: string;
append_system_prompt?: string;
allowed_tools?: string[];
disallowed_tools?: string[];
permission_mode?: "default" | "autoEdit" | "yolo" | "plan";
max_turns?: number;
add_dirs?: string[];
}

Troubleshooting

Connection Issues

If you encounter connection errors, check:

  1. Is iFlow installed

    iflow --version
  2. Is the port occupied

    # Linux/Mac
    lsof -i :8090

    # Windows
    netstat -an | findstr :8090
  3. Manually test connection

    iflow --experimental-acp --port 8090

Timeout Issues

For long-running tasks, increase the timeout:

import { IFlowClient, IFlowOptions } from "@iflow-ai/iflow-cli-sdk";

const options: IFlowOptions = {
timeout: 600000, // 10 minute timeout
};

const client = new IFlowClient(options);

Debug Logging

Enable detailed logging for debugging:

import { IFlowClient, IFlowOptions } from "@iflow-ai/iflow-cli-sdk";

const options: IFlowOptions = {
logLevel: "DEBUG",
};

const client = new IFlowClient(options);