TypeScript SDK Reference
Version Requirements: This documentation is for CodeBuddy Agent SDK v0.1.0 and above.
This document provides a complete API reference for the TypeScript SDK. For quick start and usage examples, please refer to SDK Overview.
Requirements
| Dependency | Version Requirement |
|---|---|
| Node.js | >= 18.0.0 |
| TypeScript | >= 5.0.0 (Recommended) |
Runtime Support:
- Node.js (Recommended)
- Bun
- Deno
Installation
bash
npm install @tencent-ai/agent-sdkOr use other package managers:
bash
yarn add @tencent-ai/agent-sdk
pnpm add @tencent-ai/agent-sdkEnvironment Variables
| Variable Name | Description | Required |
|---|---|---|
CODEBUDDY_CODE_PATH | CodeBuddy CLI executable path | Optional |
Authentication Configuration
The SDK supports authentication using existing login credentials, API Key, or OAuth Client Credentials. See SDK Overview - Authentication Configuration for details.
Functions
query()
Main API entry point that creates a query and returns a message stream.
typescript
function query(params: {
prompt: string | AsyncIterable<UserMessage>;
options?: Options;
}): Query;Parameters:
| Parameter | Type | Description |
|---|---|---|
prompt | string | AsyncIterable<UserMessage> | Query prompt or user message stream |
options | Options | Configuration options (optional) |
Return Value: Query - Interface that extends AsyncGenerator<Message, void>
Query Interface
typescript
interface Query extends AsyncGenerator<Message, void> {
// Interrupt current execution
interrupt(): Promise<void>;
// Dynamically modify permission mode
setPermissionMode(mode: PermissionMode): Promise<void>;
// Dynamically modify model
setModel(model?: string): Promise<void>;
// Set maximum thinking tokens
setMaxThinkingTokens(tokens: number | null): Promise<void>;
// Get available permission modes list
getAvailableModes(): Promise<ModeInfo[]>;
// Get available models list
getAvailableModels(): Promise<ModelInfo[]>;
// Get supported slash commands
supportedCommands(): Promise<SlashCommand[]>;
// Get supported models list
supportedModels(): Promise<ModelInfo[]>;
// Get MCP server status
mcpServerStatus(): Promise<McpServerStatus[]>;
// Get account information
accountInfo(): Promise<AccountInfo>;
// Stream input user messages
streamInput(stream: AsyncIterable<UserMessage>): Promise<void>;
}Constants
typescript
// All supported Hook events
const HOOK_EVENTS: readonly [
'PreToolUse',
'PostToolUse',
'PostToolUseFailure',
'Notification',
'UserPromptSubmit',
'SessionStart',
'SessionEnd',
'Stop',
'SubagentStart',
'SubagentStop',
'PreCompact',
'PermissionRequest',
'WorktreeCreate',
'WorktreeRemove'
];
// All exit reasons
const EXIT_REASONS: readonly [
'user_cancelled',
'tool_error',
'max_turns',
'max_budget_usd',
'completed',
'interrupted',
'hook_blocked'
];Errors
typescript
class AbortError extends Error {
// Thrown when operation is aborted
}Unstable V2 API
Warning: The following APIs are experimental and may change in future versions.
unstable_v2_createSession()
Create a new interactive session.
typescript
function unstable_v2_createSession(options: SessionOptions): Session;unstable_v2_resumeSession()
Resume an existing session.
typescript
function unstable_v2_resumeSession(
sessionId: string,
options: SessionOptions
): Session;unstable_v2_prompt()
Convenience function for single query.
typescript
function unstable_v2_prompt(
message: string,
options: SessionOptions
): Promise<Message[]>;unstable_v2_authenticate()
Initiate an interactive login flow with support for multi-environment authentication (international, China, etc.).
typescript
function unstable_v2_authenticate(options: AuthenticateOptions): Promise<AuthenticateResponse>;Parameters:
| Field | Type | Description |
|---|---|---|
onAuthUrl | (authState: AuthState) => Promise<void> | Authentication URL callback, used to open a browser or display the link |
environment | 'external' | 'internal' | 'ioa' | 'cloudhosted' | Predefined environment (mutually exclusive with endpoint) |
endpoint | string | Custom endpoint URL (for selfhosted, mutually exclusive with environment) |
methodId | string | Authentication method ID, default 'external' |
timeout | number | Timeout in milliseconds, default 300000 |
pathToCodebuddyCode | string | CLI executable path (optional) |
env | Record<string, string> | Environment variables (optional) |
Returns: Promise<AuthenticateResponse>
userinfo- User info object containing userId, userName, userNickname, token, and other fields
Example:
typescript
import { unstable_v2_authenticate } from '@tencent-ai/agent-sdk';
import open from 'open';
// International login
const result = await unstable_v2_authenticate({
environment: 'external',
onAuthUrl: async (authState) => {
console.log('Please login:', authState.authUrl);
await open(authState.authUrl);
}
});
console.log('Login successful:', result.userinfo.userName);
// Self-hosted login
const result2 = await unstable_v2_authenticate({
endpoint: 'https://your-company.com',
onAuthUrl: async (authState) => {
console.log('Please login:', authState.authUrl);
await open(authState.authUrl);
}
});Behavior:
- If a valid token already exists, returns user info directly without triggering the login flow
- Otherwise, notifies the user to open the login link via the
onAuthUrlcallback - After successful login, the token is cached and automatically reused on the next call
unstable_v2_logout()
Log out and clear the cached authentication token. The next call to authenticate() will trigger a fresh login.
typescript
function unstable_v2_logout(options?: LogoutOptions): Promise<void>;Parameters:
| Field | Type | Description |
|---|---|---|
environment | 'external' | 'internal' | 'ioa' | 'cloudhosted' | Predefined environment (mutually exclusive with endpoint) |
endpoint | string | Custom endpoint URL (mutually exclusive with environment) |
pathToCodebuddyCode | string | CLI executable path (optional) |
env | Record<string, string> | Environment variables (optional) |
Example:
typescript
import { unstable_v2_authenticate, unstable_v2_logout } from '@tencent-ai/agent-sdk';
// Login
const result = await unstable_v2_authenticate({
environment: 'external',
onAuthUrl: (authState) => console.log('Login:', authState.authUrl),
});
// Logout
await unstable_v2_logout({ environment: 'external' });
// Re-login with a different user
const newUser = await unstable_v2_authenticate({
environment: 'external',
onAuthUrl: (authState) => console.log('Login:', authState.authUrl),
});Session Interface
typescript
interface Session {
// Session ID (available after initialization)
readonly sessionId: string;
// Send message
send(message: string | UserMessage): Promise<void>;
// Get response stream
stream(): AsyncGenerator<Message, void>;
// Close session
close(): void;
// Async disposal
[Symbol.asyncDispose](): Promise<void>;
}SessionOptions
typescript
type SessionOptions = {
model: string;
pathToCodebuddyCode?: string;
executable?: 'node' | 'bun';
executableArgs?: string[];
env?: Record<string, string | undefined>;
canUseTool?: CanUseTool;
};Types
Options
Complete configuration options:
| Field | Type | Description |
|---|---|---|
abortController | AbortController | Used to cancel requests |
executable | 'bun' | 'deno' | 'node' | Runtime |
executableArgs | string[] | Runtime arguments |
pathToCodebuddyCode | string | CLI path |
cwd | string | Working directory |
additionalDirectories | string[] | Additional directories |
env | Record<string, string | undefined> | Environment variables |
model | string | Specify model |
fallbackModel | string | Fallback model |
maxThinkingTokens | number | Maximum thinking tokens (deprecated, use thinking instead) |
thinking | ThinkingConfig | Thinking mode configuration: { type: 'adaptive' }, { type: 'enabled', budgetTokens: N }, or { type: 'disabled' } |
effort | 'low' | 'medium' | 'high' | 'xhigh' | Model reasoning effort level |
allowedTools | string[] | Allowed tools whitelist |
disallowedTools | string[] | Disallowed tools blacklist |
canUseTool | CanUseTool | Permission callback function |
permissionMode | PermissionMode | Permission mode |
allowDangerouslySkipPermissions | boolean | Allow skipping permissions |
permissionPromptToolName | string | Permission prompt tool name |
continue | boolean | Continue recent session |
resume | string | Session ID to resume |
resumeSessionAt | string | Resume at specific message position |
persistSession | boolean | Persist session |
forkSession | boolean | Fork session |
agents | Record<string, AgentDefinition> | Custom agents |
hooks | Partial<Record<HookEvent, HookCallbackMatcher[]>> | Hook configuration |
outputFormat | OutputFormat | Output format |
systemPrompt | string | { append: string } | System prompt |
includePartialMessages | boolean | Include partial messages |
maxTurns | number | Maximum conversation turns |
mcpServers | Record<string, McpServerConfig> | MCP server configuration |
strictMcpConfig | boolean | Strict MCP configuration |
sandbox | SandboxSettings | Sandbox settings |
settingSources | SettingSource[] | Setting sources, controls which filesystem configurations are loaded. Default: no configurations are loaded |
SettingSource
Controls which filesystem locations the SDK loads configurations from.
typescript
type SettingSource = 'user' | 'project' | 'local';| Value | Description | Location |
|---|---|---|
'user' | Global user settings | ~/.codebuddy/settings.json |
'project' | Project shared settings | .codebuddy/settings.json |
'local' | Project local settings | .codebuddy/settings.local.json |
Default Behavior: When settingSources is not specified, the SDK does not load any filesystem configurations. This provides a completely clean runtime environment.
typescript
// Default: no configurations loaded (clean environment)
const q = query({ prompt: '...' });
// Load project configuration
const q = query({
prompt: '...',
options: { settingSources: ['project'] }
});
// Load all configurations (similar to CLI behavior)
const q = query({
prompt: '...',
options: { settingSources: ['user', 'project', 'local'] }
});PermissionMode
typescript
type PermissionMode =
| 'default' // Default mode, all operations require confirmation
| 'acceptEdits' // Automatically approve file edits
| 'bypassPermissions' // Skip all permission checks
| 'plan' // Plan mode, read-only operations allowedPermissionResult
typescript
type PermissionResult =
| {
behavior: 'allow';
updatedInput: Record<string, unknown>;
updatedPermissions?: PermissionUpdate[];
toolUseID?: string;
}
| {
behavior: 'deny';
message: string;
interrupt?: boolean;
toolUseID?: string;
};CanUseTool
typescript
type CanUseTool = (
toolName: string,
input: Record<string, unknown>,
options: CanUseToolOptions
) => Promise<PermissionResult>;
type CanUseToolOptions = {
signal: AbortSignal;
suggestions?: PermissionUpdate[];
blockedPath?: string;
decisionReason?: string;
toolUseID: string;
agentID?: string;
};AgentDefinition
typescript
type AgentDefinition = {
description: string; // Agent description
prompt: string; // System prompt
tools?: string[]; // Allowed tools
disallowedTools?: string[]; // Disallowed tools
model?: string; // Model to use
};ModeInfo
typescript
interface ModeInfo {
id: string; // Mode ID
name: string; // Display name
description: string; // Mode description
}ModelInfo
typescript
interface ModelInfo {
modelId: string; // Model ID
name: string; // Display name
description?: string; // Model description
}McpServerConfig
typescript
// Stdio type
type McpStdioServerConfig = {
type?: 'stdio';
command: string;
args?: string[];
env?: Record<string, string>;
};
// SSE type
type McpSSEServerConfig = {
type: 'sse';
url: string;
headers?: Record<string, string>;
};
// HTTP type
type McpHttpServerConfig = {
type: 'http';
url: string;
headers?: Record<string, string>;
};
type McpServerConfig =
| McpStdioServerConfig
| McpSSEServerConfig
| McpHttpServerConfig;HookEvent
typescript
type HookEvent =
| 'PreToolUse'
| 'PostToolUse'
| 'PostToolUseFailure'
| 'Notification'
| 'UserPromptSubmit'
| 'SessionStart'
| 'SessionEnd'
| 'Stop'
| 'SubagentStart'
| 'SubagentStop'
| 'PreCompact'
| 'PermissionRequest'
| 'WorktreeCreate'
| 'WorktreeRemove';HookCallback
typescript
type HookCallback = (
input: HookInput,
toolUseID: string | undefined,
options: { signal: AbortSignal }
) => Promise<HookJSONOutput>;
interface HookCallbackMatcher {
matcher?: string; // Match pattern (supports regex)
hooks: HookCallback[]; // Callback function list
timeout?: number; // Timeout (milliseconds)
}HookJSONOutput
typescript
// Sync output
type SyncHookJSONOutput = {
continue?: boolean;
suppressOutput?: boolean;
stopReason?: string;
decision?: 'approve' | 'block';
systemMessage?: string;
reason?: string;
hookSpecificOutput?: Record<string, unknown>;
};
// Async output
type AsyncHookJSONOutput = {
async: true;
asyncTimeout?: number;
};
type HookJSONOutput = SyncHookJSONOutput | AsyncHookJSONOutput;Message Types
Message
Union of all message types:
typescript
type Message =
| SystemMessage
| UserMessage
| AssistantMessage
| PartialAssistantMessage
| ResultMessage
| CompactBoundaryMessage
| StatusMessage
| TaskStartedMessage
| TaskNotificationMessage
| ToolProgressMessage;SystemMessage
typescript
type SystemMessage = {
type: 'system';
subtype: 'init';
uuid: string;
session_id: string;
apiKeySource?: string;
cwd?: string;
tools: string[];
mcp_servers?: Array<{ name: string; status: string }>;
model: string;
permissionMode: PermissionMode;
slash_commands?: string[];
codebuddy_code_version?: string;
skills?: string[];
plugins?: Array<{ name: string; path: string }>;
};TaskStartedMessage
A system event emitted when a background task (Bash / PowerShell / Workflow / Agent with run_in_background: true) enters the running state. Concurrent tasks are distinguished by task_id, and tool_use_id links back to the tool_use that initiated the task.
typescript
interface TaskStartedMessage {
type: 'system';
subtype: 'task_started';
task_id: string;
tool_use_id?: string;
description: string;
task_type?: string; // "Bash" / "PowerShell" / "Workflow" / "Agent"
uuid: string;
session_id: string;
}TaskUsage
Usage statistics carried by task_progress / task_notification (aligned with Claude Code's TaskUsage). Sub-agent (task_type: 'Agent') background tasks have values; background shell (Bash/PowerShell) tasks typically omit usage.
typescript
interface TaskUsage {
total_tokens: number;
tool_uses: number;
duration_ms: number;
}TaskProgressMessage
Background task progress event. Event-driven (not periodic): emitted each time a tool_use completes (usage.tool_uses increments), carrying cumulative usage and the most recent tool name last_tool_name. Background shell tasks do not emit progress (aligned with CC — only sub-agent/workflow tasks emit progress).
typescript
interface TaskProgressMessage {
type: 'system';
subtype: 'task_progress';
task_id: string;
tool_use_id?: string;
description: string;
usage: TaskUsage;
last_tool_name?: string;
uuid: string;
session_id: string;
}TaskUpdatedMessage
Background task state transition event. patch carries the fields changed in this update (at least status; terminal states also include end_time).
Lifecycle note: Background task terminal states sometimes arrive only as
task_updated(withpatch.statusbeing a terminal state) without a matchingtask_notification. Consumers tracking "active tasks" should treat terminal status values (completed/failed/stopped/killed) from bothTaskNotificationMessageandTaskUpdatedMessageequally when cleaning up.
typescript
interface TaskUpdatedMessage {
type: 'system';
subtype: 'task_updated';
task_id: string;
patch: Record<string, unknown>; // e.g. { status, end_time }
status?: 'pending' | 'running' | 'paused' | 'completed' | 'failed' | 'killed';
uuid?: string;
session_id?: string;
}TaskNotificationMessage
Emitted when a background task completes, fails, or is stopped. In stdio stream-json long-connection mode, if a task completes after the result of the turn that triggered it, this message is proactively pushed back to the same output stream — consumers must keep reading to receive it. Routed by task_id; output_file points to the persisted full output. usage is present for sub-agent tasks and omitted for shell tasks.
⚠️
query()breaks at the firstResultMessageand closes the subprocess, which means it will miss background completion events pushed after thatresult. To receive cross-turn completion events, use a V2 Session (unstable_v2_createSession) and repeatedly callstream()aftersend()to continue consuming subsequent turns triggered by background task completions (corresponding to the continuous-read semantics of the Python SDK'sreceive_messages()).
query()automatically disables background tasks: Due to the structural limitation above, the SDK automatically injectsCODEBUDDY_CODE_DISABLE_BACKGROUND_TASKS=1on thequery()path (Bash / PowerShell / Agentrun_in_backgroundis hidden/degraded to foreground), preventing background tasks from being silently dropped byquery(). If you have a specific reason to keep background tasks underquery(), explicitly set this variable inoptions.envor the process environment (any value, including0) to override this default. The V2 Session path is unaffected.
typescript
interface TaskNotificationMessage {
type: 'system';
subtype: 'task_notification';
task_id: string;
tool_use_id?: string;
status: 'completed' | 'failed' | 'stopped';
summary: string;
output_file?: string;
output_stderr_file?: string;
usage?: TaskUsage;
uuid: string;
session_id: string;
}Usage example (concurrent background tasks, distinguished by task_id and receiving notifications upon overall completion):
typescript
import { unstable_v2_createSession, type Message } from '@tencent-ai/agent-sdk';
const session = unstable_v2_createSession({ permissionMode: 'bypassPermissions' });
const started = new Map<string, Message>();
const notified = new Map<string, Message>();
await session.send('Run two background commands in parallel and tell me the results when done');
// stream() returns at each turn's result (but does not close the subprocess). Calling it
// repeatedly continues consuming subsequent drain-run turns triggered by background task
// completions, until all task_notifications have been collected.
while (notified.size < 2) {
let sawResult = false;
for await (const message of session.stream()) {
if (message.type === 'system' && message.subtype === 'task_started') {
started.set(message.task_id, message);
console.log('started', message.task_id, message.description);
} else if (message.type === 'system' && message.subtype === 'task_notification') {
notified.set(message.task_id, message);
console.log('done', message.task_id, message.status, message.output_file);
} else if (message.type === 'result') {
sawResult = true;
}
}
if (!sawResult) break; // Subprocess closed, avoid spinning
}
session.close();UserMessage
typescript
type UserMessage = {
type: 'user';
uuid?: string;
session_id: string;
message: {
role: 'user';
content: string | ContentBlock[];
};
parent_tool_use_id: string | null;
isSynthetic?: boolean;
tool_use_result?: unknown;
};AssistantMessage
typescript
type AssistantMessage = {
type: 'assistant';
uuid: string;
session_id: string;
message: {
id: string;
type: 'message';
role: 'assistant';
model: string;
content: ContentBlock[];
stop_reason: StopReason | null;
stop_sequence: string | null;
usage: Usage;
};
parent_tool_use_id: string | null;
error?: string;
};ResultMessage
typescript
type ResultMessage =
| {
type: 'result';
subtype: 'success';
uuid: string;
session_id: string;
duration_ms: number;
duration_api_ms: number;
is_error: boolean;
num_turns: number;
result: string;
total_cost_usd: number;
usage: Usage;
permission_denials: PermissionDenial[];
structured_output?: unknown;
}
| {
type: 'result';
subtype: 'error_during_execution' | 'error_max_turns' | 'error_max_budget_usd';
uuid: string;
session_id: string;
duration_ms: number;
duration_api_ms: number;
is_error: boolean;
num_turns: number;
total_cost_usd: number;
usage: Usage;
permission_denials: PermissionDenial[];
errors?: string[];
/**
* Structured error info aligned with `errors[]` by index.
* - Length always equals `errors.length` when present
* - `errors_info[i]` describes `errors[i]`; `null` if no structured dimension could be extracted
* - Entire field is omitted when all entries are null (backward compatible: legacy consumers reading only `errors` are unaffected)
* - `category` values align with ACP error categories: `network` / `quota` / `auth` / `model_service` / `cancelled` / `internal`
*/
errors_info?: Array<
| {
/** HTTP status code (e.g. 502, 429, 401) */
status?: number;
/** SDK/business error code (number like 10006 or string like `ECONNRESET`) */
code?: string | number;
/** Error category — same taxonomy as ACP `classifyErrorAsRequestError` */
category?: string;
/** Human-readable, sanitised error message */
details?: string;
}
| null
>;
};ContentBlock
typescript
// Text content block
interface TextContentBlock {
type: 'text';
text: string;
}
// Tool use block
interface ToolUseContentBlock {
type: 'tool_use';
id: string;
name: string;
input: Record<string, unknown>;
}
// Tool result block
interface ToolResultContentBlock {
type: 'tool_result';
tool_use_id: string;
content?: string | ContentBlock[];
is_error?: boolean;
}
type ContentBlock =
| TextContentBlock
| ToolUseContentBlock
| ToolResultContentBlock;Usage
typescript
interface Usage {
input_tokens: number;
output_tokens: number;
cache_read_input_tokens?: number | null;
cache_creation_input_tokens?: number | null;
}Input Types
AskUserQuestionInput
typescript
interface AskUserQuestionInput {
// List of questions to ask (1-4 questions)
questions: AskUserQuestionQuestion[];
// User answers (collected by permission component)
answers?: Record<string, string>;
}AskUserQuestionQuestion
typescript
interface AskUserQuestionQuestion {
// Complete question text (should end with ?)
question: string;
// Short label (max 12 characters)
header: string;
// Available options (2-4 options)
options: AskUserQuestionOption[];
// Allow multiple selections
multiSelect: boolean;
}AskUserQuestionOption
typescript
interface AskUserQuestionOption {
// Display text (1-5 words)
label: string;
// Option description
description: string;
}ToolInputMap
typescript
interface ToolInputMap {
AskUserQuestion: AskUserQuestionInput;
}
type KnownToolName = keyof ToolInputMap;Related Documentation
- SDK Overview - Quick start and usage examples
- Hook Reference Guide - Detailed Hook configuration instructions
- MCP Integration - MCP server configuration guide