Dependency | Version Requirement |
Node.js | >= 18.0.0 |
TypeScript | >= 5.0.0 (recommended) |
npm install @tencent-ai/agent-sdk
yarn add @tencent-ai/agent-sdkpnpm add @tencent-ai/agent-sdk
Variable Name | Description | Required |
CODEBUDDY_CODE_PATH | CodeBuddy CLI executable file path | Optional |
function query(params: {prompt: string | AsyncIterable<UserMessage>;options?: Options;}): Query;
Parameter | Type | Description |
prompt | string | AsyncIterable<UserMessage> | Query prompt or user message stream |
options | Options | Configuration options (optional) |
Query - an interface that extends AsyncGenerator<Message, void>interface Query extends AsyncGenerator<Message, void> {// Interrupt the current executioninterrupt(): Promise<void>;// Dynamically modify the permission modesetPermissionMode(mode: PermissionMode): Promise<void>;// Dynamically modify the modelsetModel(model?: string): Promise<void>;// Set the maximum number of thinking tokenssetMaxThinkingTokens(tokens: number | null): Promise<void>;// Get the list of available permission modesgetAvailableModes(): Promise<ModeInfo[]>;// Get the list of available modelsgetAvailableModels(): Promise<ModelInfo[]>;// Get the supported slash commandssupportedCommands(): Promise<SlashCommand[]>;// Get the list of supported modelssupportedModels(): Promise<ModelInfo[]>;// Get the MCP server statusmcpServerStatus(): Promise<McpServerStatus[]>;// Get account informationaccountInfo(): Promise<AccountInfo>;// Stream user messages as inputstreamInput(stream: AsyncIterable<UserMessage>): Promise<void>;}
// All supported Hook eventsconst HOOK_EVENTS: readonly ['PreToolUse','PostToolUse','PostToolUseFailure','Notification','UserPromptSubmit','SessionStart','SessionEnd','Stop','SubagentStart','SubagentStop','PreCompact','PermissionRequest','WorktreeCreate','WorktreeRemove'];// All exit reasonsconst EXIT_REASONS: readonly ['user_cancelled','tool_error','max_turns','max_budget_usd','completed','interrupted','hook_blocked'];
class AbortError extends Error {// Thrown when the operation is aborted}
function unstable_v2_createSession(options: SessionOptions): Session;
function unstable_v2_resumeSession(sessionId: string,options: SessionOptions): Session;
function unstable_v2_prompt(message: string,options: SessionOptions): Promise<Message[]>;
function unstable_v2_authenticate(options: AuthenticateOptions): Promise<AuthenticateResponse>;
Field | Type | Description |
onAuthUrl | (authState: AuthState) => Promise<void> | Authentication URL callback for opening a browser or displaying a 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 file path (optional) |
env | Record<string, string> | Environment variables (optional) |
Promise<AuthenticateResponse>userinfo - The user information object, which contains fields such as userId, userName, userNickname, and token.import { unstable_v2_authenticate } from '@tencent-ai/agent-sdk';import open from 'open';// Log in to the overseas edition.const result = await unstable_v2_authenticate({environment: 'external',onAuthUrl: async (authState) => {console.log('Please log in:', authState.authUrl);await open(authState.authUrl);}});console.log('Login successful:', result.userinfo.userName);// Log in to a self-hosted deployment.const result2 = await unstable_v2_authenticate({endpoint: 'https://your-company.com',onAuthUrl: async (authState) => {console.log('Please log in:', authState.authUrl);await open(authState.authUrl);}});
onAuthUrl callback.authenticate() will trigger a new login.function unstable_v2_logout(options?: LogoutOptions): Promise<void>;
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 file path (optional) |
env | Record<string, string> | Environment variables (optional) |
import { unstable_v2_authenticate, unstable_v2_logout } from '@tencent-ai/agent-sdk';// Log in.const result = await unstable_v2_authenticate({environment: 'external',onAuthUrl: (authState) => console.log('Login:', authState.authUrl),});// Log outawait unstable_v2_logout({ environment: 'external' });// Log in again as a different user.const newUser = await unstable_v2_authenticate({environment: 'external',onAuthUrl: (authState) => console.log('Login:', authState.authUrl),});
interface Session {// Session ID (available after initialization).readonly sessionId: string;// Send a message.send(message: string | UserMessage): Promise<void>;// Get the response stream.stream(): AsyncGenerator<Message, void>;// Close the session.close(): void;// Release asynchronously.[Symbol.asyncDispose](): Promise<void>;}
type SessionOptions = {model: string;pathToCodebuddyCode?: string;executable?: 'node' | 'bun';executableArgs?: string[];env?: Record<string, string | undefined>;canUseTool?: CanUseTool;};
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 Variable |
model | string | Specify the 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[] | Allowlist of Allowed Tools |
disallowedTools | string[] | Blocklist of Disallowed Tools |
canUseTool | CanUseTool | Permission callback function |
permissionMode | PermissionMode | Permission Mode |
allowDangerouslySkipPermissions | boolean | Allow skipping permissions |
permissionPromptToolName | string | Permission prompt tool name |
continue | boolean | Continue the most recent session |
resume | string | Session ID to resume |
resumeSessionAt | string | Resume from a specific message position |
persistSession | boolean | Whether to persist session records. Defaults to true. When set to false, sessions are kept only in memory and are not written to local transcripts, and file checkpoints are also skipped. Existing sessions can still be resumed, but they are no longer written. Requires CLI >= 2.125.1. |
forkSession | boolean | Fork session |
agents | Record<string, AgentDefinition> | Custom Agent |
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 number of conversation turns |
mcpServers | Record<string, McpServerConfig> | MCP server configuration |
strictMcpConfig | boolean | Strict MCP configuration |
sandbox | SandboxSettings | Sandbox settings |
settingSources | SettingSource[] | Setting sources control which file system configurations to load. By default, no configurations are loaded. |
type SettingSource = 'user' | 'project' | 'local';
Value | Description | Position |
'user' | Global user settings | ~/.codebuddy/settings.json |
'project' | Project-shared settings | .codebuddy/settings.json |
'local' | Project-local settings | .codebuddy/settings.local.json |
settingSources is not specified, the SDK does not load any file system configuration. This provides a completely clean runtime environment.// Default: Do not load any configuration (clean environment).const q = query({ prompt: '...' });// Load project configuration.const q = query({prompt: '...',options: { settingSources: ['project'] }});// Load all configuration (similar to CLI behavior).const q = query({prompt: '...',options: { settingSources: ['user', 'project', 'local'] }});
type PermissionMode =| 'default' // Default mode. All operations require confirmation.| 'acceptEdits' // Automatically approve file edits.| 'bypassPermissions' // Skip all permission checks.| 'plan' // Plan mode. Read-only access.
type PermissionResult =| {behavior: 'allow';updatedInput: Record<string, unknown>;updatedPermissions?: PermissionUpdate[];toolUseID?: string;}| {behavior: 'deny';message: string;interrupt?: boolean;toolUseID?: string;};
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;};
type AgentDefinition = {description: string; // Agent descriptionprompt: string; // System prompttools?: string[]; // Allowed toolsdisallowedTools?: string[]; // Disallowed toolsmodel?: string; // Model used};
interface ModeInfo {id: string; // Mode IDname: string; // Display namedescription: string; // Mode description}
interface ModelInfo {modelId: string; // Model IDname: string; // Display namedescription?: string; // Model description}
// Stdio typetype McpStdioServerConfig = {type?: 'stdio';command: string;args?: string[];env?: Record<string, string>;};// SSE typetype McpSSEServerConfig = {type: 'sse';url: string;headers?: Record<string, string>;};// HTTP typetype McpHttpServerConfig = {type: 'http';url: string;headers?: Record<string, string>;};type McpServerConfig =| McpStdioServerConfig| McpSSEServerConfig| McpHttpServerConfig;
type HookEvent =| 'PreToolUse'| 'PostToolUse'| 'PostToolUseFailure'| 'Notification'| 'UserPromptSubmit'| 'SessionStart'| 'SessionEnd'| 'Stop'| 'SubagentStart'| 'SubagentStop'| 'PreCompact'| 'PermissionRequest'| 'WorktreeCreate'| 'WorktreeRemove';
type HookCallback = (input: HookInput,toolUseID: string | undefined,options: { signal: AbortSignal }) => Promise<HookJSONOutput>;interface HookCallbackMatcher {matcher?: string; // Matching pattern (regex supported)hooks: HookCallback[]; // List of callback functionstimeout?: number; // Timeout in milliseconds}
// Output synchronously.type SyncHookJSONOutput = {continue?: boolean;suppressOutput?: boolean;stopReason?: string;decision?: 'approve' | 'block';systemMessage?: string;reason?: string;hookSpecificOutput?: Record<string, unknown>;};// Output asynchronously.type AsyncHookJSONOutput = {async: true;asyncTimeout?: number;};type HookJSONOutput = SyncHookJSONOutput | AsyncHookJSONOutput;
type Message =| SystemMessage| UserMessage| AssistantMessage| PartialAssistantMessage| ResultMessage| CompactBoundaryMessage| StatusMessage| TaskStartedMessage| TaskNotificationMessage| ToolProgressMessage;
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 }>;};
system event emitted when a background task (Bash / PowerShell / Workflow / Agent, 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.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;}
task_progress / task_notification (aligned with Claude Code's TaskUsage). This field has a value for sub-agent (task_type: 'Agent') background tasks, while it is typically omitted for background shell (Bash/PowerShell) tasks.interface TaskUsage {total_tokens: number;tool_uses: number;duration_ms: number;}
usage.tool_uses increases), carrying cumulative usage and the most recent tool name last_tool_name. Background shell tasks do not emit progress (aligned with CC, where only sub-agent/workflow tasks emit progress).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;}
patch carries the fields changed in this update (at least status, and end_time is added for terminal states).task_updated (patch.status is terminal) without a corresponding task_notification. Consumers tracking "active tasks" should clean up the terminal status of both TaskNotificationMessage and TaskUpdatedMessage equally, including completed / failed / stopped / killed.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;}
stream-json long-connection mode, if a task completes after the result of the turn that triggered it, this message is actively pushed back to the same output stream. Consumers must continuously read to receive it. It is routed by task_id, and output_file points to the complete output saved to disk. usage is carried on sub-agent tasks and omitted for shell tasks.query() breaks at the first ResultMessage and closes the child process, missing background completion events that are pushed back only after that result. To receive cross-turn completion events, use a V2 Session (unstable_v2_createSession) and repeatedly call stream() after send() to continuously consume subsequent turns triggered by background task completion (corresponding to the continuous read semantics of receive_messages() in the Python SDK).query() automatically disables background tasks: due to the structural limitation described above, the SDK automatically injects CODEBUDDY_CODE_DISABLE_BACKGROUND_TASKS=1 in the query() path (the run_in_background option for Bash / PowerShell / Agent is hidden or downgraded to foreground) to prevent background tasks from being silently dropped by query(). If you have a valid reason to keep background tasks under query(), explicitly set this variable in options.env or the process environment (any value, including 0) to override this default. The V2 Session path is not affected.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;}
task_id and receiving notifications after overall completion):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 they finish');// stream() returns at each result (but does not close the child process). Call it repeatedly to continue consuming messages pushed back by background// Subsequent drain-run turns triggered by task completion, until all task_notification messages are 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; // The child process is already closed, so break to avoid spinning.}session.close();
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;};
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;};
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>;};
// Text content blockinterface TextContentBlock {type: 'text';text: string;}// Tool call blockinterface ToolUseContentBlock {type: 'tool_use';id: string;name: string;input: Record<string, unknown>;}// Tool result blockinterface ToolResultContentBlock {type: 'tool_result';tool_use_id: string;content?: string | ContentBlock[];is_error?: boolean;}type ContentBlock =| TextContentBlock| ToolUseContentBlock| ToolResultContentBlock;
interface Usage {input_tokens: number;output_tokens: number;cache_read_input_tokens?: number | null;cache_creation_input_tokens?: number | null;}
interface AskUserQuestionInput {// List of questions to ask (1-4 questions)questions: AskUserQuestionQuestion[];// User answers (collected by the permission component)answers?: Record<string, string>;}
interface AskUserQuestionQuestion {// Complete question text (should end with ?)question: string;// Short tag (up to 12 characters)header: string;// Available options (2-4 options)options: AskUserQuestionOption[];// Whether to allow multiple selectionsmultiSelect: boolean;}
interface AskUserQuestionOption {// Display text (1-5 words)label: string;// Option descriptiondescription: string;}
interface ToolInputMap {AskUserQuestion: AskUserQuestionInput;}type KnownToolName = keyof ToolInputMap;
Was this page helpful?
You can also Contact sales or Submit a Ticket for help.
Help us improve! Rate your documentation experience in 5 mins.
Feedback