> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK References

<div id="functions" />

## Functions

<div id="query" />

### `query()`

The SDK's main entry function. Creates an async generator that streams `SDKMessage` in message arrival order.

```typescript theme={null}
function query(params: {
  prompt: string | AsyncIterable<SDKUserMessage>;
  options?: Options;
}): Query
```

<div id="parameters" />

#### Parameters

| Parameter | Type                                                             | Description                                                          |
| :-------- | :--------------------------------------------------------------- | :------------------------------------------------------------------- |
| `prompt`  | `string \| AsyncIterable<`[`SDKUserMessage`](#sdkusermessage)`>` | Pass a string for single-turn; pass an async iterable for multi-turn |
| `options` | [`Options`](#options)                                            | Optional session configuration                                       |

<div id="return-value" />

#### Return Value

Returns `Query` — an `AsyncGenerator<`[`SDKMessage`](#sdkmessage)`, void>`, consumed via `for await`.

<div id="types" />

## Types

<div id="options" />

### `Options`

Configuration object for `query()`.

| Field                             | Type                                                                                              | Default                      | Description                                                                                                                                                                   |
| :-------------------------------- | :------------------------------------------------------------------------------------------------ | :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `abortController`                 | `AbortController`                                                                                 | `new AbortController()`      | Controller to cancel the session                                                                                                                                              |
| `additionalDirectories`           | `string[]`                                                                                        | `[]`                         | Additional directories accessible to the AI                                                                                                                                   |
| `agent`                           | `string`                                                                                          | `undefined`                  | Agent name used by the main session; see [Agents Reference](#optionsagent)                                                                                                    |
| `agents`                          | `Record<string, AgentDefinition>`                                                                 | `undefined`                  | Programmatically defined subagents; see [Agents Reference](#optionsagents)                                                                                                    |
| `allowDangerouslySkipPermissions` | `boolean`                                                                                         | `false`                      | Allow skipping permission checks; used with `permissionMode: 'bypassPermissions'`                                                                                             |
| `allowedTools`                    | `string[]`                                                                                        | `[]`                         | Tool allowlist; listed tools are pre-authorized. Built-in tool names are listed in [Tools Reference](#built-in-tool-list)                                                     |
| `auth`                            | [`AuthOptions`](#authoptions)                                                                     | `undefined`                  | Authentication configuration, **required for `query()`**                                                                                                                      |
| `canUseTool`                      | [`CanUseTool`](#canusetool)                                                                       | `undefined`                  | Custom tool permission callback                                                                                                                                               |
| `continue`                        | `boolean`                                                                                         | `false`                      | Continue the most recent session                                                                                                                                              |
| `cwd`                             | `string`                                                                                          | `process.cwd()`              | Working directory                                                                                                                                                             |
| `disallowedTools`                 | `string[]`                                                                                        | `[]`                         | Tool blocklist; priority is higher than `allowedTools` and `permissionMode`. Built-in tool names are listed in [Tools Reference](#built-in-tool-list)                         |
| `enableFileCheckpointing`         | `boolean`                                                                                         | `false`                      | Enable file checkpointing for use with `rewindFiles()`; see [Checkpoint](/en/cli/sdk/checkpoint)                                                                              |
| `env`                             | `Record<string, string \| undefined>`                                                             | `process.env`                | Environment variables passed to the CLI process                                                                                                                               |
| `proxy`                           | `string`                                                                                          | `undefined`                  | Proxy URL for the CLI process; supports `http://`, `https://`, `socks5://`, and `socks://`                                                                                    |
| `executable`                      | `'bun' \| 'deno' \| 'node'`                                                                       | Auto-detected                | JavaScript runtime                                                                                                                                                            |
| `executableArgs`                  | `string[]`                                                                                        | `[]`                         | Arguments passed to the runtime                                                                                                                                               |
| `experimentalCloudAgent`          | [`CloudAgentOptions`](#cloudagentoptions)                                                         | `undefined`                  | Switch to the Qoder Cloud Agent runtime (experimental); see [Cloud Agent](/en/cli/sdk/cloud-agent)                                                                            |
| `extraArgs`                       | `Record<string, string \| null>`                                                                  | `{}`                         | Additional arguments passed to the CLI                                                                                                                                        |
| `fallbackModel`                   | `string`                                                                                          | `undefined`                  | Fallback model when the main model fails                                                                                                                                      |
| `forkSession`                     | `boolean`                                                                                         | `false`                      | Fork into a new session ID when used with `resume`                                                                                                                            |
| `hooks`                           | `Partial<Record<`[`HookEvent`](#hookevent)`, `[`HookCallbackMatcher`](#hookcallbackmatcher)`[]>>` | `{}`                         | Lifecycle hooks; see [Hooks](/en/cli/sdk/hooks)                                                                                                                               |
| `includeHookEvents`               | `boolean`                                                                                         | `false`                      | Include hook lifecycle events in the message stream                                                                                                                           |
| `includePartialMessages`          | `boolean`                                                                                         | `false`                      | Include `stream_event` streaming fragments; see [Streaming Output](/en/cli/sdk/streaming-output)                                                                              |
| `maxTurns`                        | `number`                                                                                          | `undefined`                  | Maximum conversation turns (tool call round-trips)                                                                                                                            |
| `mcpServers`                      | `Record<string, `[`McpServerConfig`](#mcpserverconfig)`>`                                         | `{}`                         | MCP server configuration; see [MCP](/en/cli/sdk/mcp)                                                                                                                          |
| `model`                           | `string`                                                                                          | CLI default                  | Model to use; options: `'auto'` / `'ultimate'` / `'performance'` / `'efficient'` / `'lite'`                                                                                   |
| `pathToQoderCLIExecutable`        | `string`                                                                                          | Auto-resolved bundled binary | Path to qodercli executable                                                                                                                                                   |
| `permissionMode`                  | [`PermissionMode`](#permissionmode)                                                               | `'default'`                  | Session permission mode                                                                                                                                                       |
| `permissionPromptToolName`        | `string`                                                                                          | `undefined`                  | MCP tool name for permission prompts; mutually exclusive with `canUseTool`                                                                                                    |
| `planModeInstructions`            | `string`                                                                                          | `undefined`                  | Override plan mode workflow body when `permissionMode: 'plan'`                                                                                                                |
| `plugins`                         | [`SdkPluginConfig`](#sdkpluginconfig)`[]`                                                         | `[]`                         | Load local plugins; see [Plugins](/en/cli/sdk/plugins)                                                                                                                        |
| `promptSuggestions`               | `boolean`                                                                                         | `false`                      | Emit `prompt_suggestion` messages after each turn's result                                                                                                                    |
| `resolveModel`                    | [`ModelPolicyProvider`](#modelpolicyprovider)                                                     | `undefined`                  | Dynamic model-selection callback. Passing it switches the query into dynamic-callback mode; see [Model Policy](/en/cli/sdk/model-policy)                                      |
| `resolveModelTimeoutMs`           | `number`                                                                                          | `500`                        | Callback timeout in milliseconds; only effective when `resolveModel` is passed                                                                                                |
| `resume`                          | `string`                                                                                          | `undefined`                  | Session ID to resume                                                                                                                                                          |
| `resumeSessionAt`                 | `string`                                                                                          | `undefined`                  | Resume from a specified message UUID                                                                                                                                          |
| `sandbox`                         | [`SandboxSettings`](#sandboxsettings)                                                             | `undefined`                  | Sandbox configuration                                                                                                                                                         |
| `sessionId`                       | `string`                                                                                          | Auto-generated               | Specify session UUID                                                                                                                                                          |
| `settings`                        | `string \| Settings`                                                                              | `undefined`                  | Inline settings object or settings file path                                                                                                                                  |
| `settingSources`                  | [`SettingSource`](#settingsource)`[]`                                                             | CLI default                  | Which filesystem settings to load; pass `[]` to skip user/project/local                                                                                                       |
| `skills`                          | `string[] \| 'all'`                                                                               | `undefined`                  | Enabled Skills; pass `'all'` to enable all; see [Skills](/en/cli/sdk/skills)                                                                                                  |
| `spawnQoderCLIProcess`            | `(options: SpawnOptions) => SpawnedProcess`                                                       | `undefined`                  | Custom process spawn function                                                                                                                                                 |
| `strictMcpConfig`                 | `boolean`                                                                                         | `false`                      | Strict MCP validation                                                                                                                                                         |
| `systemPrompt`                    | `string \| { type: 'preset'; preset: 'qodercli'; append?: string }`                               | `undefined`                  | System prompt. String overrides; preset form appends after qodercli preset                                                                                                    |
| `toolConfig`                      | [`ToolConfig`](#toolconfig)                                                                       | `undefined`                  | Built-in tool behavior configuration; see [Tools](/en/cli/sdk/tools)                                                                                                          |
| `tools`                           | `string[] \| { type: 'preset'; preset: 'qodercli' }`                                              | `undefined`                  | Tool set. Pass a string array to restrict available tools; pass an empty array to disable all tools. Built-in tool names are listed in [Tools Reference](#built-in-tool-list) |

<div id="authoptions" />

### `AuthOptions`

```typescript theme={null}
type AuthOptions =
  | { type: 'accessToken'; accessToken: string | { envVar: string } }
  | { type: 'qodercli' };
```

| Form                                               | Description                                                                             |
| :------------------------------------------------- | :-------------------------------------------------------------------------------------- |
| `{ type: 'accessToken'; accessToken: string }`     | Pass PAT directly                                                                       |
| `{ type: 'accessToken'; accessToken: { envVar } }` | Read PAT from specified environment variable; defaults to `QODER_PERSONAL_ACCESS_TOKEN` |
| `{ type: 'qodercli' }`                             | Reuse local `qodercli login` session                                                    |

Convenience constructors: `accessToken(token)` / `accessTokenFromEnv(envVar?)` / `qodercliAuth()`; see [SDK Authentication](/en/cli/sdk/authentication).

<div id="optionsagents" />

### `options.agents`

**Type:** `Record<string, AgentDefinition>`

Registers custom Agents available to the current `query()` session. The object key is the Agent name and the value is that Agent's definition.

> **The `Agent` tool is required**: Custom subagents require the main session to delegate through the built-in `Agent` tool. The Agent tool must be included in `allowedTools` because Qoder invokes subagents through the Agent tool.

```typescript theme={null}
const q = query({
  prompt: 'Use the reviewer agent to inspect recent changes.',
  options: {
    allowedTools: ['Agent'],
    agents: {
      reviewer: {
        description: 'Reviews code quality and reports actionable findings.',
        prompt: 'Review the requested code and report concrete issues.',
        tools: ['Read', 'Grep', 'Glob'],
      },
    },
  },
});
```

After registration, the model can invoke these subagents through the built-in `Agent` tool. The main session must include `Agent` in its tool set to delegate work; `allowedTools: ['Agent']` is the required pre-authorization form. If you use `options.tools` to narrow the main session's available tools, include `Agent` there as well.

<div id="optionsagent" />

### `options.agent`

**Type:** `string`

Specifies which Agent identity the main session should run as. The value can be a name registered in `options.agents`, or a built-in / plugin Agent name discovered by the current CLI.

```typescript theme={null}
const q = query({
  prompt: 'Plan the implementation.',
  options: {
    agents: {
      planner: {
        description: 'Plans work before implementation.',
        prompt: 'Break work into steps, risks, and validation checks.',
        tools: ['Read', 'Grep', 'Glob'],
      },
    },
    agent: 'planner',
  },
});
```

When set, the main session uses that Agent's `prompt`, `model`, and tool restrictions. When omitted, the session uses the default main-session behavior.

<div id="agentdefinition" />

### `AgentDefinition`

Definition of a custom Agent. The fields below are the stable capabilities currently covered and verified by the SDK.

```typescript theme={null}
type AgentDefinition = {
  description: string;
  prompt: string;
  tools?: string[];
  disallowedTools?: string[];
  model?: string;
  mcpServers?: AgentMcpServerSpec[];
  skills?: string[];
  initialPrompt?: string;
  maxTurns?: number;
  effort?: EffortLevel;
  permissionMode?: PermissionMode;
};
```

| Field             | Type                   | Required | Description                                                                                |
| ----------------- | ---------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `description`     | `string`               | Yes      | Agent purpose description; the model uses it to decide when to invoke the Agent            |
| `prompt`          | `string`               | Yes      | Agent system prompt                                                                        |
| `tools`           | `string[]`             | No       | Tool allowlist for this Agent                                                              |
| `disallowedTools` | `string[]`             | No       | Tools excluded from this Agent's tool set                                                  |
| `model`           | `string`               | No       | Model override; `'inherit'` means inherit the main session model                           |
| `mcpServers`      | `AgentMcpServerSpec[]` | No       | MCP server specs available to this Agent                                                   |
| `skills`          | `string[]`             | No       | Skill names preloaded into the Agent context                                               |
| `initialPrompt`   | `string`               | No       | First user input automatically submitted when this Agent is used as the main session Agent |
| `maxTurns`        | `number`               | No       | Maximum API turns for the Agent                                                            |
| `effort`          | `EffortLevel`          | No       | Reasoning effort level                                                                     |
| `permissionMode`  | `PermissionMode`       | No       | Permission mode for tool execution inside this Agent                                       |

<div id="description" />

#### `description`

Describes what tasks the Agent is suitable for. It affects whether the model chooses this Agent.

```typescript theme={null}
description: 'Runs project tests, analyzes failing output, and suggests fixes.'
```

Prefer a clear triggering scenario. Avoid broad descriptions such as `Helpful assistant`.

<div id="prompt" />

#### `prompt`

The Agent's system prompt. Use it to define the role, constraints, and output format.

```typescript theme={null}
prompt: `You are a security reviewer.
Check for authentication bypass, authorization bugs, injection risks, and secret leaks.
Return findings sorted by severity.`
```

<div id="tools" />

#### `tools`

Tool allowlist for the Agent. When set, the Agent can only use the listed tools.

```typescript theme={null}
tools: ['Read', 'Grep', 'Glob']
```

When `tools` is omitted, the subagent default tool set is used. A subagent's tool set does not inherit trimming from the main session's `allowedTools`.

<div id="disallowedtools" />

#### `disallowedTools`

Excludes specific tools from the Agent's tool set.

```typescript theme={null}
disallowedTools: ['Bash', 'Write']
```

When `disallowedTools` is omitted, the subagent does not inherit trimming from the main session's `disallowedTools`. Usually avoid setting both `tools` and `disallowedTools` unless you know the final tool set explicitly.

<div id="model" />

#### `model`

Specifies the model for the Agent. When omitted, the session default model is used. Supported model tiers include:

| Value         | Tier          | Description                                                         | Suitable for                                          | Credit cost |
| ------------- | ------------- | ------------------------------------------------------------------- | ----------------------------------------------------- | ----------- |
| `auto`        | Smart routing | Intelligently selects the best model, balancing capability and cost | Most daily development work; recommended default      | \~1.0x      |
| `ultimate`    | Ultimate      | Expert-level deep reasoning and thinking capability                 | Complex system design and difficult analysis          | \~1.6x      |
| `performance` | Performance   | Advanced reasoning and high-quality output                          | Core implementation, architecture design, refactoring | \~1.1x      |
| `efficient`   | Efficient     | Standard reasoning with good cost efficiency                        | Basic code generation, unit tests, daily Q\&A         | \~0.3x      |
| `lite`        | Lite          | Basic reasoning, free to use                                        | Quick validation, simple logic, quick questions       | 0x          |

Agents also support two special forms:

| Value         | Description                                                        |
| ------------- | ------------------------------------------------------------------ |
| `inherit`     | Inherit the main session model                                     |
| Full model ID | Directly specify a model ID supported by the current CLI / backend |

<div id="mcpservers" />

#### `mcpServers`

Limits or adds MCP servers available to this Agent.

```typescript theme={null}
type AgentMcpServerSpec =
  | string
  | Record<string, McpServerConfig>;
```

The string form references an MCP server already configured in the session. The object form configures a dedicated MCP server for this Agent. For the MCP server configuration shape, see [SDK References - McpServerConfig](#mcpserverconfig).

<div id="skills" />

#### `skills`

List of skill names to preload into the Agent context. Plain skill names and plugin-qualified names are both supported.

```typescript theme={null}
skills: ['review', 'sdk-test-plugin:sdk-echo']
```

For session-level skill behavior, see [Skills](/en/cli/sdk/skills).

<div id="initialprompt" />

#### `initialPrompt`

Automatically submitted as the first user input when this Agent becomes the main session Agent through `options.agent`.

```typescript theme={null}
initialPrompt: 'Start by scanning authentication and session management code.'
```

This field only takes effect for the main session Agent. It is ignored when the Agent is invoked as a subagent through the `Agent` tool.

<div id="maxturns" />

#### `maxTurns`

Limits the Agent's maximum API turns. Use it to control cost, execution time, and loop risk.

```typescript theme={null}
maxTurns: 6
```

<div id="effort" />

#### `effort`

```typescript theme={null}
type EffortLevel = 'low' | 'medium' | 'high' | 'max';
```

Controls the Agent's reasoning effort level. Higher `effort` is usually suitable for complex reviews, architecture analysis, and high-risk changes, but increases latency and token usage.

<div id="permissionmode" />

#### `permissionMode`

Controls the permission mode for tool execution inside this Agent. It uses the same semantics as the session-level `permissionMode`, but its scope is limited to this Agent. For the session-level permission chain, `allowedTools` / `disallowedTools` / `canUseTool` priority, and examples, see [Permission Control](/en/cli/sdk/permissions#controlling-default-policy-permissionmode).

```typescript theme={null}
type PermissionMode =
  | 'default'
  | 'acceptEdits'
  | 'bypassPermissions'
  | 'yolo'
  | 'plan'
  | 'dontAsk'
  | 'auto';
```

| Value                 | Meaning                                                                                                                            | Suitable for                                                                     |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `'default'`           | Standard permission behavior. Tool calls still pass through tool sets, allow / deny rules, runtime approval, or CLI default policy | Most interactive subagents                                                       |
| `'acceptEdits'`       | Automatically accepts file-edit operations; other sensitive operations still follow the permission flow                            | A subagent that is approved to modify workspace files                            |
| `'bypassPermissions'` | Skips permission checks. High-risk mode, usually only for trusted automation or test environments                                  | Controlled CI, temporary validation, one-off automation                          |
| `'yolo'`              | Compatibility alias for `'bypassPermissions'`; also skips permission checks                                                        | Compatibility with older configs; not recommended for new code                   |
| `'plan'`              | Plan mode. Suitable for producing a plan first; by default it does not perform real changes                                        | Planning, design, review, or cases where the subagent should not modify files    |
| `'dontAsk'`           | Does not ask interactively; operations that are not pre-authorized or allowed by rules are denied                                  | Non-interactive environments, or workflows that should fail instead of prompting |
| `'auto'`              | Runtime capability decides allow or deny automatically; safe workspace file edits may be auto-allowed                              | Reduce confirmation interruptions while retaining runtime judgment               |

For permission semantics, see [Permission Control](/en/cli/sdk/permissions).

<div id="agentinfo" />

### `AgentInfo`

Agent summary returned by `q.supportedAgents()`.

```typescript theme={null}
type AgentInfo = {
  name: string;
  description: string;
  model?: string;
};
```

| Field         | Type                  | Description                                                               |
| ------------- | --------------------- | ------------------------------------------------------------------------- |
| `name`        | `string`              | Agent name                                                                |
| `description` | `string`              | Agent purpose description                                                 |
| `model`       | `string \| undefined` | Agent model override; usually empty when unset or when `model: 'inherit'` |

```typescript theme={null}
const q = query({
  prompt: 'List agents.',
  options: {
    agents: {
      reviewer: {
        description: 'Reviews code quality.',
        prompt: 'Review code and report findings.',
      },
    },
  },
});

const agents = await q.supportedAgents();
```

The returned list may include Agents registered through `options.agents`, and may also include built-in, project, user, or plugin Agents discovered by the current CLI. The actual available entries depend on the qodercli version and current configuration.

<div id="context-and-invocation-boundaries" />

### Context and Invocation Boundaries

* Subagents use independent context and do not receive the parent session's full history.
* The main information passed from the parent session to a subagent is the task prompt supplied to the `Agent` tool.
* A subagent's intermediate tool results do not directly enter the parent session; the parent session receives the subagent's final response.
* Subagents cannot spawn their own subagents, so do not put `Agent` in a subagent's `tools`.
* `initialPrompt` only takes effect for the main session Agent specified by `options.agent`.

***

<div id="model-policy" />

### Model Policy

Dynamic model-selection capability of `query()`. Two modes: fixed-model (no `resolveModel`, uses `options.model` or backend default) and dynamic-callback (pass `resolveModel`, the callback decides the model before every LLM call). For full concepts, triggers and error handling see [Model Policy](/en/cli/sdk/model-policy).

<div id="optionsresolvemodel" />

#### `options.resolveModel`

**Type:** [`ModelPolicyProvider`](#modelpolicyprovider)

Entry point for dynamic-callback mode. Once passed, dynamic-callback mode is enabled and the SDK calls this callback before every LLM request to fetch the model. The `model` returned by the callback is the final model for that request; **there is no automatic fallback**.

<div id="optionsresolvemodeltimeoutms" />

#### `options.resolveModelTimeoutMs`

**Type:** `number`, default `500`

Callback timeout, in milliseconds. On timeout [`ModelPolicyTimeoutError`](#modelpolicytimeouterror) is thrown and the query fails (no fallback). Only effective when `resolveModel` is passed.

<div id="modelpolicyprovider" />

### `ModelPolicyProvider`

Callback function signature. May be synchronous or asynchronous.

```typescript theme={null}
type ModelPolicyProvider = (
  context: ModelPolicyContext,
) => ModelPolicyResult | Promise<ModelPolicyResult>;
```

Triggering scenarios are distinguished by [`QoderModelPurpose`](#qodermodelpurpose):

| Scenario           | `purpose`     | Notes                                                                                |
| ------------------ | ------------- | ------------------------------------------------------------------------------------ |
| Main conversation  | `'main'`      | Re-invoked between turns / tools — a session may trigger many times                  |
| Subagent           | `'subagent'`  | Subagents share the same provider                                                    |
| WebFetch tool      | `'web_fetch'` | After WebFetch retrieves content, a second LLM call summarises it                    |
| ImageGen tool      | `'image_gen'` | Used to pick the image-generation model                                              |
| Context compaction | `'compact'`   | Before compaction starts, the callback is queried for the compaction model           |
| BYOK               | any           | Set `model` to a [`CustomModel`](#custommodel) object to route via a third-party LLM |

Behavioural notes:

* The callback may be triggered many times within a single session (re-invoked before every turn / tool / sub-task).
* The `model` returned by the callback is the final model for that request; the SDK does not re-validate it.
* Throwing an exception or returning an empty `model` fails the query. See [Model Policy — Error handling](/en/cli/sdk/model-policy#error-handling).

<div id="modelpolicycontext" />

### `ModelPolicyContext`

The context passed to the callback on every invocation.

```typescript theme={null}
interface ModelPolicyContext {
  purpose: QoderModelPurpose;
  sessionId: string;
  availableModels: ModelInfo[];
}
```

| Field             | Type                                      | Required | Description                                                                                                                             |
| ----------------- | ----------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `purpose`         | [`QoderModelPurpose`](#qodermodelpurpose) | yes      | Purpose of this LLM call                                                                                                                |
| `sessionId`       | `string`                                  | yes      | Current session ID; the same value is passed across callback invocations within a session, so it can be used as a cache / telemetry key |
| `availableModels` | [`ModelInfo`](#modelinfo)`[]`             | yes      | The models currently available to the account, supplied by the CLI on every `get_model_policy` request                                  |

<div id="qodermodelpurpose" />

### `QoderModelPurpose`

```typescript theme={null}
type QoderModelPurpose =
  | 'main'
  | 'subagent'
  | 'web_fetch'
  | 'image_gen'
  | 'compact';
```

| Value         | Triggering scenario                                  |
| ------------- | ---------------------------------------------------- |
| `'main'`      | Main-conversation LLM call                           |
| `'subagent'`  | Subagent call                                        |
| `'web_fetch'` | Secondary LLM call triggered by the WebFetch tool    |
| `'image_gen'` | Image-generation call triggered by the ImageGen tool |
| `'compact'`   | Context compaction / summarisation                   |

<div id="modelpolicyresult" />

### `ModelPolicyResult`

The callback's return value.

```typescript theme={null}
interface ModelPolicyResult {
  model: string | (CustomModel & { model: string });
  parameters?: Record<string, unknown>;
}
```

| Field        | Type                                                              | Required | Description                                                           |
| ------------ | ----------------------------------------------------------------- | -------- | --------------------------------------------------------------------- |
| `model`      | `string \| (`[`CustomModel`](#custommodel)` & { model: string })` | yes      | String: model identifier; object: BYOK credentials + model identifier |
| `parameters` | `Record<string, unknown>`                                         | no       | Per-request model-parameter overrides. SDK control keys use camelCase |

Supported `parameters` keys:

| Key               | Type     | Description                                                                                                                                                                                                                                  |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `contextWindow`   | `number` | Context-window size in tokens for this LLM request. Choose a value supported by the selected model, usually from [`ModelInfo.context_config`](#modelcontextconfig)                                                                           |
| `reasoningEffort` | `string` | Thinking / reasoning depth for this LLM request. Choose a level supported by the selected model, usually from [`ModelInfo.thinking_config`](#modelthinkingconfig). Common levels include `none`, `low`, `medium`, `high`, `xhigh`, and `max` |

`model` forms:

* **String** — any model ID supported by the backend (such as `auto` / `performance` / `glm51`); the exact set of valid values is returned in real time by [`q.getAvailableModels()`](#qgetavailablemodels). Must be **non-empty**, otherwise the query fails.
* **`CustomModel` object** (BYOK) — the SDK extracts the object's `model` field as the model identifier for this call, and forwards the remaining fields as credentials to the CLI for routing to a third-party LLM.

<div id="custommodel" />

### `CustomModel`

BYOK credentials. In the `resolveModel` callback, set the `model` field to this object directly, and that LLM request will be routed to a third-party provider.

```typescript theme={null}
interface CustomModel {
  provider: string;
  model: string;
  api_key: string;
  style?: string;
}
```

| Field      | Type     | Required | Description                                                                      |
| ---------- | -------- | -------- | -------------------------------------------------------------------------------- |
| `provider` | `string` | yes      | Provider key — must match a [`BYOKProviderInfo.key`](#byokproviderinfo)          |
| `model`    | `string` | yes      | Model identifier — extracted by the SDK as the model ID for this call            |
| `api_key`  | `string` | yes      | The API Key supplied by the user                                                 |
| `style`    | `string` | no       | Upstream protocol style, e.g. `"openai"` / `"anthropic"`; defaults to `"openai"` |

Notes:

* `provider` must match a `key` in the catalog, otherwise backend authentication fails.
* A wrong `api_key` causes authentication to fail, which fails the query directly (dynamic-callback mode does not fall back).
* BYOK calls report `total_cost_usd` as 0 on the platform; token usage is reported as-is and billed by the provider.

<div id="byok-catalog-types" />

### BYOK catalog types

The provider/model catalog returned by [`q.listByokProviders()`](#qlistbyokproviders).

```typescript theme={null}
interface SDKControlGetByokConfigResponse {
  providers: BYOKProviderInfo[];
}

interface BYOKProviderInfo {
  key: string;
  display_name: string;
  api_key_url: string;
  types: BYOKModelTypeInfo[];
}

interface BYOKModelTypeInfo {
  key?: string;
  display_name: string;
  models: BYOKModelInfo[];
}

interface BYOKModelInfo {
  key: string;
  display_name: string;
  is_vl: boolean;
  is_reasoning: boolean;
  format: string;
  max_input_tokens: number;
}
```

<div id="byokproviderinfo" />

#### `BYOKProviderInfo`

| Field          | Type                  | Description                                              |
| -------------- | --------------------- | -------------------------------------------------------- |
| `key`          | `string`              | Provider key — fill into `CustomModel.provider` for BYOK |
| `display_name` | `string`              | Display name                                             |
| `api_key_url`  | `string`              | URL pointing the user where to obtain an API Key         |
| `types`        | `BYOKModelTypeInfo[]` | Model groups under this provider                         |

<div id="byokmodeltypeinfo" />

#### `BYOKModelTypeInfo`

| Field          | Type                  | Description                                  |
| -------------- | --------------------- | -------------------------------------------- |
| `key`          | `string \| undefined` | Group key, common values: `cp` / `tp` / `pg` |
| `display_name` | `string`              | Group display name                           |
| `models`       | `BYOKModelInfo[]`     | Models within the group                      |

<div id="byokmodelinfo" />

#### `BYOKModelInfo`

| Field              | Type      | Description                                     |
| ------------------ | --------- | ----------------------------------------------- |
| `key`              | `string`  | Model ID — fill into `CustomModel.model`        |
| `display_name`     | `string`  | Display name                                    |
| `is_vl`            | `boolean` | Whether vision / multi-modal input is supported |
| `is_reasoning`     | `boolean` | Whether this is a reasoning model               |
| `format`           | `string`  | Upstream protocol format (e.g. `openai`)        |
| `max_input_tokens` | `number`  | Maximum input token count                       |

<div id="modelinfo" />

### `ModelInfo`

Summary of an available model returned by [`q.getAvailableModels()`](#qgetavailablemodels). Also used as the element type of [`ModelPolicyContext.availableModels`](#modelpolicycontext).

```typescript theme={null}
interface ModelInfo {
  value: string;
  displayName: string;
  description: string;
  isEnabled: boolean;
  isNew?: boolean;
  isFree?: boolean;
  priceFactor?: number;
  context_config?: ModelContextConfig;
  thinking_config?: ModelThinkingConfig;
  promotion?: ModelPromotion;
  serverModel?: ServerModelJson;
}
```

| Field             | Type                                                         | Description                                                                                                           |
| ----------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `value`           | `string`                                                     | Model identifier — usable as [`ModelPolicyResult.model`](#modelpolicyresult) or [`q.setModel()`](#qsetmodel) argument |
| `displayName`     | `string`                                                     | Display name                                                                                                          |
| `description`     | `string`                                                     | Model description text                                                                                                |
| `isEnabled`       | `boolean`                                                    | Whether currently available                                                                                           |
| `isNew`           | `boolean \| undefined`                                       | Whether this is a newly launched model                                                                                |
| `isFree`          | `boolean \| undefined`                                       | Whether this is a free model                                                                                          |
| `priceFactor`     | `number \| undefined`                                        | Price factor                                                                                                          |
| `context_config`  | [`ModelContextConfig`](#modelcontextconfig) `\| undefined`   | Context-window configuration (tier label -> token count)                                                              |
| `thinking_config` | [`ModelThinkingConfig`](#modelthinkingconfig) `\| undefined` | Thinking / reasoning configuration                                                                                    |
| `promotion`       | [`ModelPromotion`](#modelpromotion) `\| undefined`           | Promotion / discount info from the model list API; absent means no promotion                                          |
| `serverModel`     | [`ServerModelJson`](#servermodeljson) `\| undefined`         | Raw model entry from the model list API, forwarded verbatim by the CLI                                                |

<div id="modelcontextconfig" />

### `ModelContextConfig`

Context-window configuration keyed by tier label, such as `"200K"` or `"1M"`.

```typescript theme={null}
type ModelContextConfig = Record<string, ModelContextWindowEntry>;

interface ModelContextWindowEntry {
  token_count: number;
  is_default?: boolean;
}
```

| Field         | Type                   | Description                      |
| ------------- | ---------------------- | -------------------------------- |
| `token_count` | `number`               | Token count for this tier        |
| `is_default`  | `boolean \| undefined` | Whether this is the default tier |

<div id="modelthinkingconfig" />

### `ModelThinkingConfig`

Thinking / reasoning configuration for a model.

```typescript theme={null}
interface ModelThinkingConfig {
  disabled?: ModelThinkingDisabled;
  enabled?: ModelThinkingEnabled;
}

interface ModelThinkingDisabled {
  description?: string;
}

interface ModelThinkingEnabled {
  description?: string;
  efforts?: Record<string, ModelEffortEntry>;
  is_default?: boolean;
}

interface ModelEffortEntry {
  description?: string;
  is_default?: boolean;
}
```

| Field             | Type                                            | Description                                                                      |
| ----------------- | ----------------------------------------------- | -------------------------------------------------------------------------------- |
| `disabled`        | `ModelThinkingDisabled \| undefined`            | Configuration shown when thinking is disabled                                    |
| `enabled`         | `ModelThinkingEnabled \| undefined`             | Configuration shown when thinking is enabled, including effort levels            |
| `enabled.efforts` | `Record<string, ModelEffortEntry> \| undefined` | Per-effort metadata, such as `"low"` / `"high"` descriptions and default markers |

<div id="modelpromotion" />

### `ModelPromotion`

Promotion / discount info forwarded from the model list API. Nested field names stay in the server's snake\_case form.

```typescript theme={null}
type LocalizedModelText = {
  en?: string;
  zh?: string;
} & Record<string, string | undefined>;

interface ModelPromotion {
  active: boolean;
  badge?: LocalizedModelText;
  description?: LocalizedModelText;
  discount_factor?: number;
  before_promotion_price_factor?: number;
  timezone?: string;
  rule_id?: string;
  window_start?: string;
  window_end?: string;
}
```

| Field                           | Type                              | Description                                              |
| ------------------------------- | --------------------------------- | -------------------------------------------------------- |
| `active`                        | `boolean`                         | Whether the promotion is currently active for this model |
| `badge`                         | `LocalizedModelText \| undefined` | Short localized label                                    |
| `description`                   | `LocalizedModelText \| undefined` | Longer localized description                             |
| `discount_factor`               | `number \| undefined`             | Discounted price factor while the promotion is active    |
| `before_promotion_price_factor` | `number \| undefined`             | Original price factor before the promotion               |
| `timezone`                      | `string \| undefined`             | IANA timezone used to evaluate the promotion window      |
| `rule_id`                       | `string \| undefined`             | Server rule identifier                                   |
| `window_start`                  | `string \| undefined`             | Daily window start, in `HH:mm` format                    |
| `window_end`                    | `string \| undefined`             | Daily window end, in `HH:mm` format                      |

<div id="servermodeljson" />

### `ServerModelJson`

Raw JSON-compatible model entry from the model list API. Use this when a server field is needed before it has a first-class `ModelInfo` field.

```typescript theme={null}
type ServerModelJson = Record<string, ServerModelJsonValue>;
```

<div id="usageinfo" />

### `UsageInfo`

Account quota and usage snapshot returned by [`q.getUsageInfo()`](#qgetusageinfo).

```typescript theme={null}
interface UsageInfo {
  userId?: string;
  userType?: string;
  totalUsagePercentage?: number;
  isHighestTier?: boolean;
  expiresAt?: number;
  upgradeUrl?: string;
  userQuota?: UsageQuotaBucket;
  addOnQuota?: UsageAddOnQuotaBucket;
  isQuotaExceeded?: boolean;
  isPlanQuotaProrated?: boolean;
  orgResourcePackage?: UsageOrgResourcePackage;
}

interface UsageQuotaBucket {
  total?: number;
  used?: number;
  remaining?: number;
  percentage?: number;
  unit?: string;
}

interface UsageAddOnQuotaBucket extends UsageQuotaBucket {
  detailUrl?: string;
}

interface UsageOrgResourcePackage {
  used?: number;
  cap?: number;
  remaining?: number;
  percentage?: number;
  available?: boolean;
  unit?: string;
}
```

| Field                  | Type                                   | Description                                                                                            |
| ---------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `userId`               | `string \| undefined`                  | Account identifier                                                                                     |
| `userType`             | `string \| undefined`                  | Plan tier (e.g. `free`, `pro`, `teams`)                                                                |
| `totalUsagePercentage` | `number \| undefined`                  | Overall usage across all buckets, `0`–`100`                                                            |
| `isHighestTier`        | `boolean \| undefined`                 | Whether the account is already on the highest plan                                                     |
| `expiresAt`            | `number \| undefined`                  | Current plan/quota expiry, Unix epoch milliseconds                                                     |
| `upgradeUrl`           | `string \| undefined`                  | Upgrade page URL, when an upgrade is available                                                         |
| `userQuota`            | `UsageQuotaBucket \| undefined`        | Included plan quota bucket                                                                             |
| `addOnQuota`           | `UsageAddOnQuotaBucket \| undefined`   | Purchased add-on quota bucket, when the account has add-on quota (`detailUrl` links to the usage page) |
| `isQuotaExceeded`      | `boolean \| undefined`                 | Whether all available quota is exhausted                                                               |
| `isPlanQuotaProrated`  | `boolean \| undefined`                 | Whether the plan quota is prorated for the current period                                              |
| `orgResourcePackage`   | `UsageOrgResourcePackage \| undefined` | Organization-shared resource package (`available` indicates it can be drawn from)                      |

Each bucket reports `used` / `remaining` / `percentage` against its `total` (or `cap` for the org package) in `unit` (typically `credits`).
Missing fields, or fields with an unexpected runtime type, are omitted from the returned object.

<div id="modelpolicytimeouterror" />

### `ModelPolicyTimeoutError`

```typescript theme={null}
class ModelPolicyTimeoutError extends Error {}
```

Thrown by the SDK when the `resolveModel` callback exceeds `options.resolveModelTimeoutMs` without returning. The query fails directly, with no fallback.

<div id="qsetmodel" />

### `q.setModel()`

```typescript theme={null}
setModel(model?: string): Promise<void>;
```

Switches the model for fixed-model mode at runtime. Takes effect on the next LLM call. Effective only in fixed-model mode; in dynamic-callback mode, calling it does not override the callback's result. Valid model IDs: see [`ModelInfo.value`](#modelinfo).

<div id="qgetavailablemodels" />

### `q.getAvailableModels()`

```typescript theme={null}
getAvailableModels(): Promise<ModelInfo[]>;
```

Fetches the latest model list available to the current account in real time. Always returns the latest result, no caching; returns an empty array (does not throw) when the list cannot be fetched temporarily. In dynamic-callback mode, [`ModelPolicyContext.availableModels`](#modelpolicycontext) already carries the same up-to-date list, so calling this method explicitly is unnecessary.

<div id="qlistbyokproviders" />

### `q.listByokProviders()`

```typescript theme={null}
listByokProviders(): Promise<BYOKProviderInfo[] | null>;
```

Returns the BYOK provider/model catalog available to the current account as an array:

* Returns `null`: the CLI does not support this API (graceful fallback, no exception).
* Returns an array (may be empty): the list of providers available to the current account (an empty array means the account has not enabled BYOK).

Field semantics: see [BYOK catalog types](#byok-catalog-types).

<div id="qgetusageinfo" />

### `q.getUsageInfo()`

```typescript theme={null}
getUsageInfo(): Promise<UsageInfo | null>;
```

Fetches the current account's quota and usage information from the running CLI in real time.

* Returns `null`: the CLI is unauthenticated, an older CLI version does not support this API, or the CLI did not return an object (graceful fallback, no exception).
* Returns a [`UsageInfo`](#usageinfo) object: the known account quota and usage fields whose runtime types are valid. Missing or invalid fields are omitted.

```typescript theme={null}
import { query, qodercliAuth } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: userMessages(),
  options: { auth: qodercliAuth() },
});

const usage = await q.getUsageInfo();
if (usage) {
  console.log(`Plan: ${usage.userType}, used ${usage.totalUsagePercentage}%`);
  console.log(`Plan quota: ${usage.userQuota?.remaining}/${usage.userQuota?.total} ${usage.userQuota?.unit} left`);
}
```

Return type: see [`UsageInfo`](#usageinfo).

***

<div id="canusetool" />

### `CanUseTool`

Host-defined custom tool permission approval callback.

```typescript theme={null}
type CanUseTool = (
  toolName: string,
  input: Record<string, unknown>,
  options: CanUseToolOptions,
) => Promise<PermissionResult>;
```

<div id="canusetooloptions" />

#### `CanUseToolOptions`

```typescript theme={null}
type CanUseToolOptions = {
  signal: AbortSignal;
  suggestions?: PermissionUpdate[];
  blockedPath?: string;
  decisionReason?: string;
  decisionReasonType?: PermissionDecisionReasonType;
  classifierApprovable?: boolean;
  title?: string;
  displayName?: string;
  description?: string;
  toolUseID: string;
  agentID?: string;
  exitPlanMode?: ExitPlanModeApprovalDetails;
};
```

| `options` Field                         | Type                           | Description                                                             |
| :-------------------------------------- | :----------------------------- | :---------------------------------------------------------------------- |
| `signal`                                | `AbortSignal`                  | Aborted when cancelled                                                  |
| `suggestions`                           | `PermissionUpdate[]`           | Permission update suggestions from CLI                                  |
| `blockedPath`                           | `string`                       | File path triggering authorization (file-related scenarios only)        |
| `decisionReason`                        | `string`                       | Human-readable authorization reason from CLI                            |
| `decisionReasonType`                    | `PermissionDecisionReasonType` | Permission reason classification                                        |
| `classifierApprovable`                  | `boolean`                      | Whether the current call can be auto-approved by the runtime classifier |
| `title` / `displayName` / `description` | `string`                       | Human-readable authorization text generated at runtime                  |
| `toolUseID`                             | `string`                       | This tool invocation's ID                                               |
| `agentID`                               | `string`                       | Sub-Agent ID initiating the call                                        |
| `exitPlanMode`                          | `ExitPlanModeApprovalDetails`  | Approval details for exiting plan mode                                  |

For full usage and examples, see [Permission Control](/en/cli/sdk/permissions#runtime-approval-canusetool).

<div id="permissionmode" />

### `PermissionMode`

```typescript theme={null}
type PermissionMode =
  | 'default'
  | 'acceptEdits'
  | 'bypassPermissions'
  | 'yolo'
  | 'plan'
  | 'dontAsk'
  | 'auto';
```

| Value                 | Meaning                                                                                                                  | Suitable for                                                                     |
| :-------------------- | :----------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- |
| `'default'`           | Standard permission behavior. Tool calls are handled by `tools`, allow / deny rules, dynamic approval, or runtime policy | Most interactive sessions                                                        |
| `'acceptEdits'`       | Automatically accepts file-edit operations; other sensitive operations still follow the permission flow                  | Sessions that are approved to modify workspace files                             |
| `'bypassPermissions'` | Skips permission checks; must also set `allowDangerouslySkipPermissions: true`                                           | Trusted automation or test environments                                          |
| `'yolo'`              | Compatibility alias for `'bypassPermissions'`; must also set `allowDangerouslySkipPermissions: true`                     | Compatibility with older configs; not recommended for new code                   |
| `'plan'`              | Plan mode. Suitable for producing a plan first; by default it does not perform real changes                              | Planning, design, review                                                         |
| `'dontAsk'`           | Does not ask interactively; operations that are not pre-authorized or allowed by rules are denied                        | Non-interactive environments, or workflows that should fail instead of prompting |
| `'auto'`              | Runtime capability decides allow or deny automatically; safe workspace file edits may be auto-allowed                    | Reduce confirmation interruptions while retaining runtime judgment               |

For more details, see [Permission Control](/en/cli/sdk/permissions#controlling-default-policy-permissionmode).

<div id="permissionresult" />

### `PermissionResult`

Return value of `CanUseTool`.

```typescript theme={null}
type PermissionResult =
  | {
      behavior: 'allow';
      updatedInput?: Record<string, unknown>;
      updatedPermissions?: PermissionUpdate[];
      toolUseID?: string;
      decisionClassification?: PermissionDecisionClassification;
    }
  | {
      behavior: 'deny';
      message: string;
      interrupt?: boolean;
      toolUseID?: string;
      decisionClassification?: PermissionDecisionClassification;
    };
```

`allow.updatedInput` replaces the actual parameters the tool receives when modified. `deny.interrupt: true` denies and also interrupts the Agent.

<div id="mcpserverconfig" />

### `McpServerConfig`

MCP server configuration, passed to `Options.mcpServers`.

```typescript theme={null}
type McpServerConfig =
  | McpStdioServerConfig
  | McpSSEServerConfig
  | McpHttpServerConfig
  | McpSdkServerConfigWithInstance;
```

<div id="mcpstdioserverconfig" />

#### `McpStdioServerConfig`

```typescript theme={null}
type McpStdioServerConfig = {
  type?: 'stdio';
  command: string;
  args?: string[];
  env?: Record<string, string>;
};
```

<div id="mcpsseserverconfig" />

#### `McpSSEServerConfig`

```typescript theme={null}
type McpSSEServerConfig = {
  type: 'sse';
  url: string;
  headers?: Record<string, string>;
};
```

<div id="mcphttpserverconfig" />

#### `McpHttpServerConfig`

```typescript theme={null}
type McpHttpServerConfig = {
  type: 'http';
  url: string;
  headers?: Record<string, string>;
};
```

<div id="mcpsdkserverconfigwithinstance" />

#### `McpSdkServerConfigWithInstance`

```typescript theme={null}
type McpSdkServerConfigWithInstance = {
  type: 'sdk';
  name: string;
  instance: McpServer;
};
```

Returned by the `createSdkMcpServer()` factory; see [MCP - In-Process Server](/en/cli/sdk/mcp#in-process-server-recommended).

<div id="sdkpluginconfig" />

### `SdkPluginConfig`

Load local plugins.

```typescript theme={null}
type SdkPluginConfig = {
  type: 'local';
  path: string;
};
```

| Field  | Type      | Description                                       |
| :----- | :-------- | :------------------------------------------------ |
| `type` | `'local'` | Currently only local is supported                 |
| `path` | `string`  | Absolute or relative path to the plugin directory |

<div id="cloudagentoptions" />

### `CloudAgentOptions`

Type of `Options.experimentalCloudAgent`. Configures the agent / session reference for the Cloud runtime; full usage in [Cloud Agent](/en/cli/sdk/cloud-agent).

```typescript theme={null}
type CloudAgentOptions =
  | {
      session: { id: string };
      agent?: never;
      stream?: CloudAgentStreamOptions;
    }
  | {
      agent: CloudAgentReference;
      session: { create: CloudSessionCreateParams };
      stream?: CloudAgentStreamOptions;
    };

type CloudAgentReference =
  | { id: string; create?: never }
  | { create: AgentCreateParams; id?: never };

type CloudAgentStreamOptions = {
  afterId?: string;
  deltaFlushIntervalMs?: number;
};
```

| Field                         | Type                                                    | Description                                                           |
| :---------------------------- | :------------------------------------------------------ | :-------------------------------------------------------------------- |
| `agent.id`                    | `string`                                                | Reuse an existing Cloud Agent; mutually exclusive with `agent.create` |
| `agent.create`                | [`AgentCreateParams`](#agentcreateparams)               | Create a new Cloud Agent; mutually exclusive with `agent.id`          |
| `session.id`                  | `string`                                                | Reuse an existing Cloud session; `agent` must not be passed           |
| `session.create`              | [`CloudSessionCreateParams`](#cloudsessioncreateparams) | Create a new Cloud session; `environment_id` is required              |
| `stream.afterId`              | `string`                                                | SSE replay anchor — start after this event ID                         |
| `stream.deltaFlushIntervalMs` | `number`                                                | Delta merge / flush interval, in milliseconds                         |

<div id="agentcreateparams" />

### `AgentCreateParams`

Request body for creating a new Cloud Agent, matching the agent-create fields of the Qoder Cloud OpenAPI.

```typescript theme={null}
type AgentCreateParams = {
  model: string;
  name: string;
  description?: string | null;
  system?: string | null;
  tools?: Array<{
    type: 'agent_toolset_20260401';
    enabled_tools?: Array<
      | 'bash'
      | 'write'
      | 'glob'
      | 'web_fetch'
      | 'read'
      | 'edit'
      | 'grep'
      | 'web_search'
    >;
  }>;
  mcp_servers?: Array<{ name: string; type: 'url'; url: string }>;
  skills?: Array<{ skill_id: string; type: 'custom' }>;
  metadata?: Record<string, string>;
};
```

| Field         | Type                     | Description                                                                                             |
| :------------ | :----------------------- | :------------------------------------------------------------------------------------------------------ |
| `model`       | `string`                 | Model identifier. Accepted values: `'auto'` / `'ultimate'` / `'performance'` / `'efficient'` / `'lite'` |
| `name`        | `string`                 | Human-readable agent name                                                                               |
| `description` | `string \| null`         | Description                                                                                             |
| `system`      | `string \| null`         | System prompt                                                                                           |
| `tools`       | see above                | Built-in toolset; `enabled_tools` controls the allowlist                                                |
| `mcp_servers` | see above                | URL-based MCP server connections                                                                        |
| `skills`      | see above                | User-defined custom skills                                                                              |
| `metadata`    | `Record<string, string>` | Arbitrary key-value metadata                                                                            |

<div id="cloudsessioncreateparams" />

### `CloudSessionCreateParams`

Request body for creating a new Cloud session.

```typescript theme={null}
type CloudSessionCreateParams = {
  environment_id: string;
  resources?: Array<{ type: 'file'; file_id: string; path?: string }>;
  title?: string | null;
  vault_ids?: Array<string>;
  memory_store_ids?: Array<string>;
};
```

| Field              | Type             | Description                                                          |
| :----------------- | :--------------- | :------------------------------------------------------------------- |
| `environment_id`   | `string`         | Container environment ID; **required**                               |
| `resources`        | see above        | Resources mounted into the session container (currently only `file`) |
| `title`            | `string \| null` | Session title                                                        |
| `vault_ids`        | `string[]`       | Credential vault IDs                                                 |
| `memory_store_ids` | `string[]`       | Memory store IDs                                                     |

<div id="sandboxsettings" />

### `SandboxSettings`

Sandbox behavior configuration.

```typescript theme={null}
type SandboxSettings = {
  enabled?: boolean;
  autoAllowBashIfSandboxed?: boolean;
  excludedCommands?: string[];
  allowUnsandboxedCommands?: boolean;
  network?: SandboxNetworkConfig;
  filesystem?: SandboxFilesystemConfig;
  ignoreViolations?: { file?: string[]; network?: string[] };
  enableWeakerNestedSandbox?: boolean;
};
```

| Field                      | Type                      | Default     | Description                                                                     |
| :------------------------- | :------------------------ | :---------- | :------------------------------------------------------------------------------ |
| `enabled`                  | `boolean`                 | `false`     | Enable sandbox                                                                  |
| `autoAllowBashIfSandboxed` | `boolean`                 | `true`      | Auto-allow bash when sandbox is enabled                                         |
| `excludedCommands`         | `string[]`                | `[]`        | Commands that statically bypass sandbox (e.g., `['docker']`)                    |
| `allowUnsandboxedCommands` | `boolean`                 | `true`      | Allow model to request running commands outside sandbox (falls to `canUseTool`) |
| `network`                  | `SandboxNetworkConfig`    | `undefined` | Network restrictions                                                            |
| `filesystem`               | `SandboxFilesystemConfig` | `undefined` | Filesystem restrictions                                                         |
| `ignoreViolations`         | `{ file?, network? }`     | `undefined` | Violations to ignore by pattern                                                 |

<div id="sandboxnetworkconfig" />

#### `SandboxNetworkConfig`

```typescript theme={null}
type SandboxNetworkConfig = {
  allowLocalBinding?: boolean;
  allowUnixSockets?: string[];
  allowAllUnixSockets?: boolean;
  httpProxyPort?: number;
  socksProxyPort?: number;
};
```

<div id="sandboxfilesystemconfig" />

#### `SandboxFilesystemConfig`

```typescript theme={null}
type SandboxFilesystemConfig = {
  allowWrite?: string[];
  denyWrite?: string[];
  denyRead?: string[];
  allowRead?: string[];
  allowManagedReadPathsOnly?: boolean;
};
```

<div id="settingsource" />

### `SettingSource`

Controls which filesystem settings are loaded.

```typescript theme={null}
type SettingSource = 'user' | 'project' | 'local';
```

| Value       | Meaning                                      | Location                     |
| :---------- | :------------------------------------------- | :--------------------------- |
| `'user'`    | User-level global settings                   | `~/.qoder/settings.json`     |
| `'project'` | Project shared settings (version controlled) | `.qoder/settings.json`       |
| `'local'`   | Project local settings (gitignored)          | `.qoder/settings.local.json` |

When omitted, all sources are loaded per CLI defaults; pass `[]` to skip entirely.

<div id="toolconfig" />

### `ToolConfig`

Built-in tool behavior configuration.

```typescript theme={null}
type ToolConfig = {
  askUserQuestion?: {
    previewFormat?: 'markdown' | 'html';
  };
};
```

<div id="built-in-tool-list" />

### Built-in Tool List

In `tools`, `allowedTools`, `disallowedTools`, `canUseTool`, hook matchers, and Agent tool allowlists, built-in tools use the runtime tool names in the table below.

| Category          | Tool name          | Description                      |
| ----------------- | ------------------ | -------------------------------- |
| Command execution | `Bash`             | Execute shell commands           |
| File operations   | `Read`             | Read file contents               |
| File operations   | `Edit`             | Edit files by string matching    |
| File operations   | `Write`            | Create or overwrite files        |
| Search            | `Glob`             | Search by filename pattern       |
| Search            | `Grep`             | Search by content regex          |
| Network           | `WebFetch`         | Fetch and process URL content    |
| Network           | `WebSearch`        | Web search                       |
| Agent             | `Agent`            | Invoke a subagent                |
| Interaction       | `AskUserQuestion`  | Ask the user a question          |
| Notebook          | `NotebookEdit`     | Edit notebook cells              |
| Background tasks  | `TaskOutput`       | Send output to a background task |
| Background tasks  | `TaskStop`         | Stop a background task           |
| Plan / worktree   | `ExitPlanMode`     | Exit plan mode                   |
| Plan / worktree   | `EnterWorktree`    | Enter a git worktree             |
| Plan / worktree   | `ExitWorktree`     | Exit a worktree                  |
| Config            | `Config`           | Read or write configuration      |
| Todo              | `TodoWrite`        | Manage todo items                |
| MCP resources     | `ListMcpResources` | List MCP resources               |
| MCP resources     | `ReadMcpResource`  | Read an MCP resource             |
| MCP invocation    | `Mcp`              | Generic MCP tool call            |

Custom MCP tool names use this format:

```text theme={null}
mcp__{serverName}__{toolName}
```

<div id="tool" />

### `tool()`

Creates a type-safe SDK MCP tool definition.

```typescript theme={null}
function tool<Schema extends AnyZodRawShape>(
  name: string,
  description: string,
  inputSchema: Schema,
  handler: (
    args: InferShape<Schema>,
    extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
  ) => Promise<CallToolResult>,
  extras?: ToolExtras,
): SdkMcpToolDefinition<Schema>;
```

| Parameter     | Type                                       | Required | Meaning                                                                                         | Current Qoder behavior                                                                                                                 |
| ------------- | ------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `name`        | `string`                                   | Yes      | Unique tool identifier within the current MCP server                                            | Forms the model-visible full tool name `mcp__{serverName}__{name}`; registration requires it to be non-empty                           |
| `description` | `string`                                   | Yes      | Tool description shown to the model; describe when to use it, what it does, and what it returns | Forwarded into the tool list and directly affects whether the model calls the tool correctly; registration requires it to be non-empty |
| `inputSchema` | `Schema extends AnyZodRawShape`            | Yes      | Zod raw shape defining tool input parameters                                                    | The SDK uses it to generate the MCP input schema and infer handler `args` as `InferShape<Schema>`                                      |
| `handler`     | `(args, extra) => Promise<CallToolResult>` | Yes      | Async function executed when the tool is called                                                 | Executed by the SDK when the model calls the tool; the return value is sent back to the model as a tool result                         |
| `extras`      | `ToolExtras`                               | No       | Extra tool metadata, currently used for `annotations`                                           | The SDK registers supported annotations on the MCP server; this does not replace permission configuration                              |

`tool()` itself is a factory for defining tools. Registration constraints such as non-empty `name`, non-empty `description`, and duplicate tool names are validated by `createSdkMcpServer()` when tools are registered.

<div id="anyzodrawshape" />

#### `AnyZodRawShape`

```typescript theme={null}
type AnyZodRawShape = ZodRawShapeCompat;
```

`AnyZodRawShape` is compatible with Zod 3 / Zod 4. It represents a field object, not `z.object(...)`.

<div id="infershape" />

#### `InferShape`

```typescript theme={null}
type InferShape<T extends AnyZodRawShape> = ShapeOutput<T>;
```

`InferShape` infers the handler `args` type from the Zod raw shape.

<div id="sdkmcptooldefinition" />

#### `SdkMcpToolDefinition`

```typescript theme={null}
type SdkMcpToolDefinition<
  Schema extends AnyZodRawShape = AnyZodRawShape,
> = {
  name: string;
  description: string;
  inputSchema: Schema;
  annotations?: ToolAnnotations;
  handler: (
    args: InferShape<Schema>,
    extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
  ) => Promise<CallToolResult>;
};
```

<div id="toolextras" />

#### `ToolExtras`

```typescript theme={null}
type ToolExtras = {
  annotations?: ToolAnnotations;
};
```

<div id="toolannotations" />

#### `ToolAnnotations`

```typescript theme={null}
type ToolAnnotations = {
  title?: string;
  readOnlyHint?: boolean;
  destructiveHint?: boolean;
  openWorldHint?: boolean;
};
```

| Field             | Type      | Optional | Meaning                                                       | Current Qoder behavior                                                                                                                                   |
| ----------------- | --------- | -------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`           | `string`  | Yes      | Human-readable title for the tool                             | MCP metadata; currently not documented as a verified Qoder behavioral capability                                                                         |
| `readOnlyHint`    | `boolean` | Yes      | Marks that the tool does not modify state                     | Current observable effect: read-only tools can be eligible for concurrent execution within the same batch of tool calls; this is not a permission switch |
| `destructiveHint` | `boolean` | Yes      | Marks that the tool may perform destructive updates           | Risk metadata; currently does not automatically block an authorized tool execution                                                                       |
| `openWorldHint`   | `boolean` | Yes      | Marks whether the tool interacts with the external open world | External-interaction metadata; currently does not automatically block an authorized tool execution                                                       |

These fields are metadata and scheduling hints, not permission switches. Whether execution is allowed is still determined by `tools`, `allowedTools`, `disallowedTools`, `permissionMode`, `canUseTool`, and hooks. In the feature documentation, the verified behavior capabilities are `readOnlyHint`, `destructiveHint`, and `openWorldHint`; `title` is retained here only as MCP metadata in the type reference.

<div id="createsdkmcpserver" />

### `createSdkMcpServer()`

Creates an MCP server that runs in the same process as the SDK.

```typescript theme={null}
function createSdkMcpServer(
  options: CreateSdkMcpServerOptions,
): McpSdkServerConfigWithInstance;
```

<div id="createsdkmcpserveroptions" />

#### `CreateSdkMcpServerOptions`

```typescript theme={null}
type CreateSdkMcpServerOptions = {
  name: string;
  version?: string;
  tools?: Array<SdkMcpToolDefinition<any>>;
};
```

| Field     | Default     | Description                                                         |
| --------- | ----------- | ------------------------------------------------------------------- |
| `name`    | Required    | MCP server name; it becomes part of `mcp__{serverName}__{toolName}` |
| `version` | `'1.0.0'`   | Server version information                                          |
| `tools`   | `undefined` | Tools registered to this server                                     |

<a id="createsdkmcpserver-return-value" />

<div id="return-value" />

#### Return Value

Returns `McpSdkServerConfigWithInstance`, which can be passed directly as a value in `options.mcpServers`. For the full MCP server configuration, see [McpServerConfig](#mcpserverconfig).

```typescript theme={null}
type McpSdkServerConfigWithInstance = {
  type: 'sdk';
  name: string;
  instance: McpServer;
};
```

<div id="calltoolresult" />

### `CallToolResult`

A tool handler returns the MCP protocol `CallToolResult`.

```typescript theme={null}
type CallToolResult = {
  content: McpToolResultContent[];
  isError?: boolean;
  _meta?: Record<string, unknown>;
};
```

<div id="mcptoolresultcontent" />

#### `McpToolResultContent`

```typescript theme={null}
type McpToolResultContent =
  | { type: 'text'; text: string }
  | { type: 'image'; data: string; mimeType: string }
  | { type: 'audio'; data: string; mimeType: string }
  | {
      type: 'resource_link';
      uri: string;
      name?: string;
      description?: string;
      mimeType?: string;
    }
  | {
      type: 'resource';
      resource: {
        uri: string;
        mimeType?: string;
        text?: string;
        blob?: string;
      };
    };
```

| Field     | Description                                           |
| --------- | ----------------------------------------------------- |
| `content` | Array of content blocks returned to the model         |
| `isError` | When `true`, indicates the tool failed semantically   |
| `_meta`   | Tool-result metadata, forwarded with the MCP response |

<div id="built-in-tool-input-and-output-types" />

### Built-in Tool Input and Output Types

The SDK provides input / output structures for built-in tools at the type level. Note: these are TypeScript type names; permission configuration still uses the runtime tool names above.

<div id="agentinput-agentoutput" />

#### `AgentInput` / `AgentOutput`

```typescript theme={null}
type AgentInput = {
  prompt: string;
  agent?: string;
  timeout_ms?: number;
};

type AgentOutput = {
  result: string;
  agent?: string;
  error?: string;
};
```

<div id="bashinput-bashoutput" />

#### `BashInput` / `BashOutput`

```typescript theme={null}
type BashInput = {
  command: string;
  timeout?: number;
  description?: string;
  run_in_background?: boolean;
  dangerouslyDisableSandbox?: boolean;
};

type BashOutput = {
  stdout: string;
  stderr: string;
  exitCode: number;
  interrupted?: boolean;
};
```

<div id="filereadinput-filereadoutput" />

#### `FileReadInput` / `FileReadOutput`

The runtime tool name is `Read`; the type names remain `FileReadInput` / `FileReadOutput`.

```typescript theme={null}
type FileReadInput = {
  file_path: string;
  offset?: number;
  limit?: number;
  pages?: string;
};

type FileReadOutput =
  | {
      type: 'text';
      text: string;
      file_path: string;
      totalLines?: number;
    }
  | {
      type: 'image';
      source: {
        type: 'base64';
        media_type: string;
        data: string;
      };
      file_path: string;
    }
  | {
      type: 'notebook';
      cells: Array<{
        cell_number: number;
        cell_type: 'code' | 'markdown' | 'raw';
        source: string;
        outputs?: string[];
      }>;
      file_path: string;
    }
  | {
      type: 'pdf';
      pages: Array<{
        page_number: number;
        content: string;
      }>;
      file_path: string;
      totalPages: number;
    }
  | {
      type: 'parts';
      parts: Array<
        | { type: 'text'; text: string }
        | { type: 'image'; source: { type: 'base64'; media_type: string; data: string } }
      >;
      file_path: string;
    }
  | {
      type: 'file_unchanged';
      file_path: string;
      message: string;
    };
```

<div id="fileeditinput-fileeditoutput" />

#### `FileEditInput` / `FileEditOutput`

The runtime tool name is `Edit`.

```typescript theme={null}
type FileEditInput = {
  file_path: string;
  old_string: string;
  new_string: string;
  replace_all?: boolean;
};

type FileEditOutput = {
  success: boolean;
  file_path: string;
  diff?: string;
  error?: string;
};
```

<div id="filewriteinput-filewriteoutput" />

#### `FileWriteInput` / `FileWriteOutput`

The runtime tool name is `Write`.

```typescript theme={null}
type FileWriteInput = {
  file_path: string;
  content: string;
};

type FileWriteOutput = {
  success: boolean;
  file_path: string;
  bytesWritten?: number;
  error?: string;
};
```

<div id="globinput-globoutput" />

#### `GlobInput` / `GlobOutput`

```typescript theme={null}
type GlobInput = {
  pattern: string;
  path?: string;
};

type GlobOutput = {
  files: string[];
  totalMatches: number;
  truncated?: boolean;
};
```

<div id="grepinput-grepoutput" />

#### `GrepInput` / `GrepOutput`

```typescript theme={null}
type GrepInput = {
  pattern: string;
  path?: string;
  glob?: string;
  type?: string;
  output_mode?: 'content' | 'files_with_matches' | 'count';
  head_limit?: number;
  offset?: number;
  context?: number;
  '-A'?: number;
  '-B'?: number;
  '-C'?: number;
  '-i'?: boolean;
  '-n'?: boolean;
  multiline?: boolean;
};

type GrepOutput = {
  results: string;
  matchCount: number;
  truncated?: boolean;
};
```

<div id="webfetchinput-webfetchoutput" />

#### `WebFetchInput` / `WebFetchOutput`

```typescript theme={null}
type WebFetchInput = {
  url: string;
  prompt: string;
};

type WebFetchOutput = {
  content: string;
  url: string;
  statusCode?: number;
  error?: string;
  redirectUrl?: string;
};
```

<div id="websearchinput-websearchoutput" />

#### `WebSearchInput` / `WebSearchOutput`

```typescript theme={null}
type WebSearchInput = {
  query: string;
  allowed_domains?: string[];
  blocked_domains?: string[];
};

type WebSearchOutput = {
  results: Array<{
    title: string;
    url: string;
    snippet: string;
  }>;
  query: string;
};
```

<div id="askuserquestioninput-askuserquestionoutput" />

#### `AskUserQuestionInput` / `AskUserQuestionOutput`

```typescript theme={null}
type AskUserQuestionInput = {
  question: string;
  options?: string[];
  default?: string;
};

type AskUserQuestionOutput = {
  answer: string;
};
```

<div id="notebookeditinput-notebookeditoutput" />

#### `NotebookEditInput` / `NotebookEditOutput`

```typescript theme={null}
type NotebookEditInput = {
  notebook_path: string;
  cell_id?: string;
  cell_type?: 'code' | 'markdown';
  new_source: string;
  edit_mode?: 'replace' | 'insert' | 'delete';
};

type NotebookEditOutput = {
  success: boolean;
  notebook_path: string;
  error?: string;
};
```

<div id="taskoutputinput" />

#### `TaskOutputInput`

```typescript theme={null}
type TaskOutputInput = {
  task_id: string;
  output: string;
};
```

<div id="taskstopinput-taskstopoutput" />

#### `TaskStopInput` / `TaskStopOutput`

```typescript theme={null}
type TaskStopInput = {
  task_id: string;
  reason?: string;
};

type TaskStopOutput = {
  success: boolean;
  task_id: string;
  error?: string;
};
```

<div id="exitplanmodeinput-exitplanmodeoutput" />

#### `ExitPlanModeInput` / `ExitPlanModeOutput`

```typescript theme={null}
type ExitPlanModeInput = {
  confirm?: boolean;
};

type ExitPlanModeOutput = {
  success: boolean;
  error?: string;
};
```

<div id="configinput-configoutput" />

#### `ConfigInput` / `ConfigOutput`

```typescript theme={null}
type ConfigInput = {
  action: 'get' | 'set' | 'list';
  key?: string;
  value?: unknown;
  scope?: 'user' | 'project' | 'local';
};

type ConfigOutput = {
  success: boolean;
  value?: unknown;
  values?: Record<string, unknown>;
  error?: string;
};
```

<div id="enterworktreeinput-enterworktreeoutput" />

#### `EnterWorktreeInput` / `EnterWorktreeOutput`

```typescript theme={null}
type EnterWorktreeInput = {
  name?: string;
};

type EnterWorktreeOutput = {
  worktree_path: string;
  branch_name: string;
  success: boolean;
  error?: string;
};
```

<div id="exitworktreeinput-exitworktreeoutput" />

#### `ExitWorktreeInput` / `ExitWorktreeOutput`

```typescript theme={null}
type ExitWorktreeInput = {
  action: 'keep' | 'remove';
  discard_changes?: boolean;
};

type ExitWorktreeOutput = {
  success: boolean;
  error?: string;
  uncommitted_files?: string[];
  unmerged_commits?: string[];
};
```

<div id="todowriteinput-todowriteoutput" />

#### `TodoWriteInput` / `TodoWriteOutput`

```typescript theme={null}
type TodoWriteInput = {
  todos: Array<{
    id?: string;
    content: string;
    status: 'pending' | 'in_progress' | 'completed';
    priority?: 'low' | 'medium' | 'high';
  }>;
};

type TodoWriteOutput = {
  success: boolean;
  todos: Array<{
    id: string;
    content: string;
    status: 'pending' | 'in_progress' | 'completed';
    priority?: 'low' | 'medium' | 'high';
  }>;
  error?: string;
};
```

<div id="listmcpresourcesinput-listmcpresourcesoutput" />

#### `ListMcpResourcesInput` / `ListMcpResourcesOutput`

```typescript theme={null}
type ListMcpResourcesInput = {
  server_name: string;
};

type ListMcpResourcesOutput = {
  resources: Array<{
    uri: string;
    name: string;
    description?: string;
    mimeType?: string;
  }>;
  server_name: string;
};
```

<div id="readmcpresourceinput" />

#### `ReadMcpResourceInput`

```typescript theme={null}
type ReadMcpResourceInput = {
  server_name: string;
  uri: string;
};
```

<div id="mcpinput-mcpoutput" />

#### `McpInput` / `McpOutput`

```typescript theme={null}
type McpInput = {
  server_name: string;
  tool_name: string;
  arguments?: Record<string, unknown>;
};

type McpOutput = {
  content: unknown;
  isError?: boolean;
};
```

<div id="toolinputschemas" />

#### `ToolInputSchemas`

```typescript theme={null}
type ToolInputSchemas =
  | AgentInput
  | BashInput
  | FileReadInput
  | FileEditInput
  | FileWriteInput
  | GlobInput
  | GrepInput
  | WebFetchInput
  | WebSearchInput
  | AskUserQuestionInput
  | NotebookEditInput
  | TaskOutputInput
  | TaskStopInput
  | ExitPlanModeInput
  | ConfigInput
  | EnterWorktreeInput
  | ExitWorktreeInput
  | TodoWriteInput
  | ListMcpResourcesInput
  | ReadMcpResourceInput
  | McpInput;
```

<div id="tooloutputschemas" />

#### `ToolOutputSchemas`

```typescript theme={null}
type ToolOutputSchemas =
  | AgentOutput
  | BashOutput
  | FileReadOutput
  | FileEditOutput
  | FileWriteOutput
  | GlobOutput
  | GrepOutput
  | WebFetchOutput
  | WebSearchOutput
  | AskUserQuestionOutput
  | NotebookEditOutput
  | TaskStopOutput
  | ExitPlanModeOutput
  | ConfigOutput
  | EnterWorktreeOutput
  | ExitWorktreeOutput
  | TodoWriteOutput
  | ListMcpResourcesOutput
  | McpOutput;
```

***

<div id="hooks-reference" />

## Hooks Reference

For usage guide and examples, see [Hooks](/en/cli/sdk/hooks).

<div id="event-overview" />

### Event Overview

| Event                | Trigger                       | Controllable Behavior                    |
| -------------------- | ----------------------------- | ---------------------------------------- |
| `PreToolUse`         | Before tool invocation        | Intercept / allow / modify input         |
| `PostToolUse`        | After tool succeeds           | Audit / inject context / override output |
| `PostToolUseFailure` | After tool fails              | Error handling / logging                 |
| `UserPromptSubmit`   | Before user prompt is sent    | Inject context / intercept               |
| `SessionStart`       | Session begins                | Initialize / inject context              |
| `SessionEnd`         | Session ends                  | Cleanup / logging                        |
| `Stop`               | AI stops generating           | Prevent stop, force continuation         |
| `SubagentStart`      | Subagent starts               | Observe / log                            |
| `SubagentStop`       | Subagent stops                | Observe / log                            |
| `PreCompact`         | Before context compaction     | Observe / log                            |
| `PostCompact`        | After context compaction      | Observe / log                            |
| `CwdChanged`         | Working directory changes     | Observe / log                            |
| `InstructionsLoaded` | Instruction file loaded       | Observe / log                            |
| `FileChanged`        | File created/modified/deleted | Observe / log                            |
| `PermissionRequest`  | Permission requested          | Auto-approve / deny permission requests  |

<div id="hookevent" />

### `HookEvent`

Union type of registrable hook events.

```typescript theme={null}
type HookEvent =
  | 'PreToolUse'
  | 'PostToolUse'
  | 'PostToolUseFailure'
  | 'UserPromptSubmit'
  | 'SessionStart'
  | 'SessionEnd'
  | 'Stop'
  | 'SubagentStart'
  | 'SubagentStop'
  | 'PreCompact'
  | 'PostCompact'
  | 'CwdChanged'
  | 'InstructionsLoaded'
  | 'FileChanged'
  | 'PermissionRequest';
```

<div id="hookcallback" />

### `HookCallback`

```typescript theme={null}
type HookCallback = (
  input: HookInput,
  toolUseID: string | undefined,
  options: { signal: AbortSignal }
) => Promise<HookJSONOutput>;
```

<div id="hookcallbackmatcher" />

### `HookCallbackMatcher`

```typescript theme={null}
interface HookCallbackMatcher {
  matcher?: string;
  hooks: HookCallback[];
  timeout?: number;
}
```

| Field     | Type             | Description                               |
| :-------- | :--------------- | :---------------------------------------- |
| `matcher` | `string`         | Optional regex; filters by `tool_name`    |
| `hooks`   | `HookCallback[]` | Callback list executed on match           |
| `timeout` | `number`         | Optional timeout in seconds (default: 60) |

<div id="basehookinput" />

### `BaseHookInput`

Common input fields shared by all hook events.

```typescript theme={null}
interface BaseHookInput {
  hook_event_name: string;
  session_id: string;
  transcript_path: string;
  cwd: string;
}
```

| Field             | Type     | Description                                    |
| :---------------- | :------- | :--------------------------------------------- |
| `hook_event_name` | `string` | Event type identifier (e.g. `"PreToolUse"`)    |
| `session_id`      | `string` | Unique identifier for the current session      |
| `transcript_path` | `string` | Path to session transcript file (JSONL format) |
| `cwd`             | `string` | Current working directory of the session       |

<div id="hookjsonoutput" />

### `HookJSONOutput`

Return type for hook callbacks.

```typescript theme={null}
interface HookJSONOutput {
  continue?: boolean;
  stopReason?: string;
  decision?: string;
  reason?: string;
  hookSpecificOutput?: object;
}
```

| Field                | Type      | Default | Description                                                                                                                                               |
| :------------------- | :-------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `continue`           | `boolean` | `true`  | Set to `false` to terminate the session. Only effective for `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `UserPromptSubmit`, `Stop`, `SubagentStop` |
| `stopReason`         | `string`  | —       | Human-readable reason for stopping (used with `continue: false`)                                                                                          |
| `decision`           | `string`  | —       | `"approve"` or `"block"`. `"block"` prevents tool execution; for `Stop` events, `"block"` prevents stopping and forces continuation                       |
| `reason`             | `string`  | —       | Reason for the decision (shown to the model; for `Stop` event `"block"`, injected as a continuation prompt)                                               |
| `hookSpecificOutput` | `object`  | —       | Event-specific output (see each event type)                                                                                                               |

> When multiple hooks return conflicting `decision` values, `"deny"` / `"block"` takes precedence (strictest rule wins).

***

<div id="pretoolusehookinput" />

### `PreToolUseHookInput`

```typescript theme={null}
interface PreToolUseHookInput extends BaseHookInput {
  hook_event_name: 'PreToolUse';
  permission_mode: string | undefined;
  tool_name: string;
  tool_input: unknown;
}
```

| Field             | Type                  | Description                     |
| :---------------- | :-------------------- | :------------------------------ |
| `permission_mode` | `string \| undefined` | Current session permission mode |
| `tool_name`       | `string`              | Name of the tool being called   |
| `tool_input`      | `unknown`             | Arguments passed to the tool    |

**`hookSpecificOutput`:**

| Field                      | Type                      | Description                                         |
| :------------------------- | :------------------------ | :-------------------------------------------------- |
| `hookEventName`            | `"PreToolUse"`            | Must be set                                         |
| `permissionDecision`       | `string`                  | `"allow"` / `"deny"` / `"ask"` / `"defer"`          |
| `permissionDecisionReason` | `string`                  | Reason for the permission decision                  |
| `updatedInput`             | `Record<string, unknown>` | Modified tool input, replaces original `tool_input` |
| `additionalContext`        | `string`                  | Extra context injected into the model's next turn   |

<div id="posttoolusehookinput" />

### `PostToolUseHookInput`

```typescript theme={null}
interface PostToolUseHookInput extends BaseHookInput {
  hook_event_name: 'PostToolUse';
  tool_name: string;
  tool_input: unknown;
  tool_response: unknown;
}
```

| Field           | Type      | Description                      |
| :-------------- | :-------- | :------------------------------- |
| `tool_name`     | `string`  | Name of the tool that was called |
| `tool_input`    | `unknown` | Arguments passed to the tool     |
| `tool_response` | `unknown` | Tool execution result            |

**Output behavior:**

| Field                                  | Location              | Behavior                                                            |
| :------------------------------------- | :-------------------- | :------------------------------------------------------------------ |
| `hookSpecificOutput.updatedToolOutput` | Event-specific output | **Overrides** `tool_response`; model only sees the overridden value |
| `hookSpecificOutput.additionalContext` | Event-specific output | **Appends** supplementary context without modifying original result |
| `decision: "block"` + `reason`         | Top-level output      | Prevents agent from further processing this tool result             |

**`hookSpecificOutput`:**

| Field               | Type            | Description                                  |
| :------------------ | :-------------- | :------------------------------------------- |
| `hookEventName`     | `"PostToolUse"` | Must be set                                  |
| `updatedToolOutput` | `string`        | Overrides tool response content              |
| `additionalContext` | `string`        | Extra context appended alongside tool result |

> When multiple hooks set `updatedToolOutput`, the **last non-empty value** wins. For chained transforms, execute them sequentially within a single callback.

<div id="posttoolusefailurehookinput" />

### `PostToolUseFailureHookInput`

```typescript theme={null}
interface PostToolUseFailureHookInput extends BaseHookInput {
  hook_event_name: 'PostToolUseFailure';
  tool_name: string;
  tool_input: unknown;
  error: string;
  is_interrupt: boolean | undefined;
}
```

| Field          | Type                   | Description                          |
| :------------- | :--------------------- | :----------------------------------- |
| `tool_name`    | `string`               | Name of the failed tool              |
| `tool_input`   | `unknown`              | Arguments passed to the tool         |
| `error`        | `string`               | Error message                        |
| `is_interrupt` | `boolean \| undefined` | Whether caused by an interrupt/abort |

<div id="userpromptsubmithookinput" />

### `UserPromptSubmitHookInput`

```typescript theme={null}
interface UserPromptSubmitHookInput extends BaseHookInput {
  hook_event_name: 'UserPromptSubmit';
  prompt: string;
}
```

| Field    | Type     | Description     |
| :------- | :------- | :-------------- |
| `prompt` | `string` | User input text |

**`hookSpecificOutput`:**

| Field               | Type                 | Description                               |
| :------------------ | :------------------- | :---------------------------------------- |
| `hookEventName`     | `"UserPromptSubmit"` | Must be set                               |
| `additionalContext` | `string`             | Extra context appended to the user prompt |

<div id="sessionstarthookinput" />

### `SessionStartHookInput`

```typescript theme={null}
interface SessionStartHookInput extends BaseHookInput {
  hook_event_name: 'SessionStart';
  source: string;
}
```

| Field    | Type     | Description                                                              |
| :------- | :------- | :----------------------------------------------------------------------- |
| `source` | `string` | Session start reason: `"startup"` / `"resume"` / `"clear"` / `"compact"` |

**`hookSpecificOutput`:**

| Field               | Type             | Description                       |
| :------------------ | :--------------- | :-------------------------------- |
| `hookEventName`     | `"SessionStart"` | Must be set                       |
| `additionalContext` | `string`         | Context injected at session start |

<div id="sessionendhookinput" />

### `SessionEndHookInput`

```typescript theme={null}
interface SessionEndHookInput extends BaseHookInput {
  hook_event_name: 'SessionEnd';
  reason: string;
}
```

| Field    | Type     | Description                                                                                                                   |
| :------- | :------- | :---------------------------------------------------------------------------------------------------------------------------- |
| `reason` | `string` | Session end reason: `"clear"` / `"resume"` / `"logout"` / `"prompt_input_exit"` / `"other"` / `"bypass_permissions_disabled"` |

<div id="stophookinput" />

### `StopHookInput`

```typescript theme={null}
interface StopHookInput extends BaseHookInput {
  hook_event_name: 'Stop';
  stop_hook_active: boolean;
}
```

| Field              | Type      | Description                                      |
| :----------------- | :-------- | :----------------------------------------------- |
| `stop_hook_active` | `boolean` | Whether a Stop hook is currently preventing stop |

Return `{ decision: 'block', reason: '...' }` to prevent the AI from stopping and force continuation. `reason` is injected as a continuation prompt into the model context.

<div id="subagentstarthookinput" />

### `SubagentStartHookInput`

```typescript theme={null}
interface SubagentStartHookInput extends BaseHookInput {
  hook_event_name: 'SubagentStart';
  agent_id: string;
  agent_type: string;
}
```

| Field        | Type     | Description                                |
| :----------- | :------- | :----------------------------------------- |
| `agent_id`   | `string` | Unique identifier of the subagent instance |
| `agent_type` | `string` | Type/role of the subagent                  |

<div id="subagentstophookinput" />

### `SubagentStopHookInput`

```typescript theme={null}
interface SubagentStopHookInput extends BaseHookInput {
  hook_event_name: 'SubagentStop';
  stop_hook_active: boolean;
}
```

| Field              | Type      | Description                                      |
| :----------------- | :-------- | :----------------------------------------------- |
| `stop_hook_active` | `boolean` | Whether a Stop hook is currently preventing stop |

<div id="precompacthookinput" />

### `PreCompactHookInput`

```typescript theme={null}
interface PreCompactHookInput extends BaseHookInput {
  hook_event_name: 'PreCompact';
  trigger: string;
  custom_instructions: string | null;
}
```

| Field                 | Type             | Description                                |
| :-------------------- | :--------------- | :----------------------------------------- |
| `trigger`             | `string`         | Trigger reason: `"manual"` / `"auto"`      |
| `custom_instructions` | `string \| null` | Custom instructions for compaction summary |

<div id="postcompacthookinput" />

### `PostCompactHookInput`

```typescript theme={null}
interface PostCompactHookInput extends BaseHookInput {
  hook_event_name: 'PostCompact';
  trigger: string;
  compact_summary: string;
}
```

| Field             | Type     | Description                                |
| :---------------- | :------- | :----------------------------------------- |
| `trigger`         | `string` | Trigger reason: `"manual"` / `"auto"`      |
| `compact_summary` | `string` | Summary generated after context compaction |

<div id="cwdchangedhookinput" />

### `CwdChangedHookInput`

```typescript theme={null}
interface CwdChangedHookInput extends BaseHookInput {
  hook_event_name: 'CwdChanged';
  old_cwd: string;
  new_cwd: string;
}
```

| Field     | Type     | Description                         |
| :-------- | :------- | :---------------------------------- |
| `old_cwd` | `string` | Working directory before the change |
| `new_cwd` | `string` | Working directory after the change  |

<div id="instructionsloadedhookinput" />

### `InstructionsLoadedHookInput`

```typescript theme={null}
interface InstructionsLoadedHookInput extends BaseHookInput {
  hook_event_name: 'InstructionsLoaded';
  load_reason: string;
}
```

| Field         | Type     | Description                                             |
| :------------ | :------- | :------------------------------------------------------ |
| `load_reason` | `string` | Load reason: `"nested_traversal"` / `"path_glob_match"` |

<div id="filechangedhookinput" />

### `FileChangedHookInput`

```typescript theme={null}
interface FileChangedHookInput extends BaseHookInput {
  hook_event_name: 'FileChanged';
  file_path: string;
  event: string;
}
```

| Field       | Type     | Description                                         |
| :---------- | :------- | :-------------------------------------------------- |
| `file_path` | `string` | Path of the changed file                            |
| `event`     | `string` | Filesystem event: `"change"` / `"add"` / `"unlink"` |

<div id="permissionrequesthookinput" />

### `PermissionRequestHookInput`

```typescript theme={null}
interface PermissionRequestHookInput extends BaseHookInput {
  hook_event_name: 'PermissionRequest';
  tool_name: string;
  tool_input: unknown;
  permission_suggestions: PermissionUpdate[] | undefined;
}
```

| Field                    | Type                              | Description                |
| :----------------------- | :-------------------------------- | :------------------------- |
| `tool_name`              | `string`                          | Tool requesting permission |
| `tool_input`             | `unknown`                         | Tool input arguments       |
| `permission_suggestions` | `PermissionUpdate[] \| undefined` | Suggested permission rules |

**`hookSpecificOutput`:**

| Field           | Type                  | Description                     |
| :-------------- | :-------------------- | :------------------------------ |
| `hookEventName` | `"PermissionRequest"` | Must be set                     |
| `decision`      | `object`              | Permission decision (see below) |

`decision` is one of:

* **Approve:** `{ behavior: "allow", updatedInput?: Record<string, unknown>, updatedPermissions?: PermissionUpdate[] }`
* **Deny:** `{ behavior: "deny", message?: string }`

<div id="message-types" />

## Message Types

<div id="sdkmessage" />

### `SDKMessage`

Discriminated union of all messages flowing from `Query`.

```typescript theme={null}
type SDKMessage =
  | SDKAssistantMessage
  | SDKUserMessage
  | SDKUserMessageReplay
  | SDKResultMessage
  | SDKSystemMessage
  | SDKPartialAssistantMessage
  | SDKCompactBoundaryMessage
  | SDKStatusMessage
  | SDKMcpStatusChangeMessage
  | SDKAPIRetryMessage
  | SDKLocalCommandOutputMessage
  | SDKHookStartedMessage
  | SDKHookProgressMessage
  | SDKHookResponseMessage
  | SDKTaskStartedMessage
  | SDKTaskProgressMessage
  | SDKTaskNotificationMessage
  | SDKSessionStateChangedMessage
  | SDKSessionTitleChangedMessage
  | SDKBridgeStateMessage
  | SDKFilesPersistedEvent
  | SDKElicitationCompleteMessage
  | SDKPermissionDeniedMessage
  | SDKPromptSuggestionMessage
  | SDKCloudAgentEventMessage;
```

Callers should first branch on `message.type`, then further dispatch on `subtype` (only `system` / `result` types have subtypes).

<div id="sdkassistantmessage" />

### `SDKAssistantMessage`

AI's complete reply, delivered once per turn.

```typescript theme={null}
type SDKAssistantMessage = {
  type: 'assistant';
  uuid: string;
  session_id: string;
  parent_tool_use_id: string | null;
  message: {
    role: 'assistant';
    content: Array<
      | { type: 'text'; text: string }
      | { type: 'tool_use'; id: string; name: string; input: unknown }
      | { type: 'thinking'; thinking: string }
    >;
  };
};
```

<div id="sdkusermessage" />

### `SDKUserMessage`

User message or tool result feedback.

```typescript theme={null}
type SDKUserMessage = {
  type: 'user';
  uuid?: string;
  session_id?: string;
  parent_tool_use_id: string | null;
  message: {
    role: 'user';
    content: Array<
      | { type: 'text'; text: string }
      | { type: 'image'; source: { type: 'base64'; media_type: string; data: string } }
      | { type: 'tool_result'; tool_use_id: string; content: string | unknown[]; is_error?: boolean }
    >;
  };
  isSynthetic?: boolean;
  tool_use_result?: unknown;
};
```

<div id="sdkusermessagereplay" />

### `SDKUserMessageReplay`

Historical user messages replayed during session resume.

```typescript theme={null}
type SDKUserMessageReplay = SDKUserMessage & {
  uuid: string;
  session_id: string;
  isReplay: true;
};
```

<div id="sdkresultmessage" />

### `SDKResultMessage`

Final message when the entire session ends.

```typescript theme={null}
type SDKResultMessage =
  | {
      type: 'result';
      subtype: 'success';
      uuid: string;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      result: string;
      permission_denials: SDKPermissionDenial[];
    }
  | {
      type: 'result';
      subtype:
        | 'error_max_turns'
        | 'error_during_execution'
        | 'error_max_structured_output_retries';
      // Same common fields as success
      errors: string[];
    };
```

<div id="sdksystemmessage" />

### `SDKSystemMessage`

Session initialization message (`subtype: 'init'`). Other system events are delivered via separate message types; see the various `SDK*Message` types below.

```typescript theme={null}
type SDKSystemMessage = {
  type: 'system';
  subtype: 'init';
  uuid: string;
  session_id: string;
  qodercli_version: string;
  protocol_version?: string;
  apiKeySource: 'user' | 'project' | 'org' | 'temporary';
  cwd: string;
  model: string;
  permissionMode: PermissionMode;
  tools: string[];
  slash_commands: string[];
  output_style: string;
  agents?: string[];
  skills: string[];
  plugins: { name: string; path: string; source?: string }[];
  mcp_servers: { name: string; status: string }[];
  fast_mode_state?: 'off' | 'cooldown' | 'on';
};
```

<div id="sdkpartialassistantmessage" />

### `SDKPartialAssistantMessage`

Requires `includePartialMessages: true`; streams out incrementally per token. For full usage, see [Streaming Output](/en/cli/sdk/streaming-output).

```typescript theme={null}
type SDKPartialAssistantMessage = {
  type: 'stream_event';
  uuid: string;
  session_id: string;
  parent_tool_use_id: string | null;
  event: {
    type: string;
    index?: number;
    delta?: {
      type?: string;
      text?: string;
      partial_json?: string;
      thinking?: string;
    };
    content_block?: {
      type: string;
      id?: string;
      name?: string;
      text?: string;
    };
  };
};
```

<div id="sdkcompactboundarymessage" />

### `SDKCompactBoundaryMessage`

Boundary marker for context compaction completion.

```typescript theme={null}
type SDKCompactBoundaryMessage = {
  type: 'system';
  subtype: 'compact_boundary';
  uuid: string;
  session_id: string;
  compact_metadata: {
    trigger: 'manual' | 'auto';
    pre_tokens: number;
    preserved_segment?: {
      head_uuid: string;
      anchor_uuid: string;
      tail_uuid: string;
    };
  };
};
```

<div id="sdkstatusmessage" />

### `SDKStatusMessage`

Session running state changes (e.g., compacting).

```typescript theme={null}
type SDKStatusMessage = {
  type: 'system';
  subtype: 'status';
  status: 'compacting' | null;
  permissionMode?: PermissionMode;
  uuid: string;
  session_id: string;
};
```

<div id="sdkmcpstatuschangemessage" />

### `SDKMcpStatusChangeMessage`

MCP connection pool state change.

```typescript theme={null}
type SDKMcpStatusChangeMessage = {
  type: 'system';
  subtype: 'mcp_status_change';
  servers: McpServerStatus[];
  uuid: string;
  session_id: string;
};
```

<div id="sdkapiretrymessage" />

### `SDKAPIRetryMessage`

Automatic retry on network/service errors.

```typescript theme={null}
type SDKAPIRetryMessage = {
  type: 'system';
  subtype: 'api_retry';
  attempt: number;
  max_retries: number;
  retry_delay_ms: number;
  error_status: number | null;
  error: SDKAssistantMessageError;
  uuid: string;
  session_id: string;
};
```

<div id="sdklocalcommandoutputmessage" />

### `SDKLocalCommandOutputMessage`

Output from local slash commands.

```typescript theme={null}
type SDKLocalCommandOutputMessage = {
  type: 'system';
  subtype: 'local_command_output';
  content: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkhookstartedmessage" />

### `SDKHookStartedMessage`

Hook begins execution.

```typescript theme={null}
type SDKHookStartedMessage = {
  type: 'system';
  subtype: 'hook_started';
  hook_id: string;
  hook_name: string;
  hook_event: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkhookprogressmessage" />

### `SDKHookProgressMessage`

Hook execution output in progress.

```typescript theme={null}
type SDKHookProgressMessage = {
  type: 'system';
  subtype: 'hook_progress';
  hook_id: string;
  hook_name: string;
  hook_event: string;
  stdout: string;
  stderr: string;
  output: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkhookresponsemessage" />

### `SDKHookResponseMessage`

Hook finishes.

```typescript theme={null}
type SDKHookResponseMessage = {
  type: 'system';
  subtype: 'hook_response';
  hook_id: string;
  hook_name: string;
  hook_event: string;
  output: string;
  stdout: string;
  stderr: string;
  exit_code?: number;
  outcome: 'success' | 'error' | 'cancelled';
  uuid: string;
  session_id: string;
};
```

<div id="sdktaskstartedmessage" />

### `SDKTaskStartedMessage`

Sub-Agent task starts.

```typescript theme={null}
type SDKTaskStartedMessage = {
  type: 'system';
  subtype: 'task_started';
  task_id: string;
  tool_use_id?: string;
  description: string;
  task_type?: string;
  workflow_name?: string;
  prompt?: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdktaskprogressmessage" />

### `SDKTaskProgressMessage`

Sub-Agent task progress.

```typescript theme={null}
type SDKTaskProgressMessage = {
  type: 'system';
  subtype: 'task_progress';
  task_id: string;
  tool_use_id?: string;
  description: string;
  usage: {
    total_tokens: number;
    tool_uses: number;
    duration_ms: number;
  };
  last_tool_name?: string;
  summary?: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdktasknotificationmessage" />

### `SDKTaskNotificationMessage`

Sub-Agent task finishes.

```typescript theme={null}
type SDKTaskNotificationMessage = {
  type: 'system';
  subtype: 'task_notification';
  task_id: string;
  tool_use_id?: string;
  status: 'completed' | 'failed' | 'stopped';
  output_file: string;
  summary: string;
  usage?: {
    total_tokens: number;
    tool_uses: number;
    duration_ms: number;
  };
  uuid: string;
  session_id: string;
};
```

<div id="sdksessionstatechangedmessage" />

### `SDKSessionStateChangedMessage`

Main session running state change.

```typescript theme={null}
type SDKSessionStateChangedMessage = {
  type: 'system';
  subtype: 'session_state_changed';
  state: 'idle' | 'running' | 'requires_action';
  uuid: string;
  session_id: string;
};
```

<div id="sdksessiontitlechangedmessage" />

### `SDKSessionTitleChangedMessage`

Session title change.

```typescript theme={null}
type SDKSessionTitleChangedMessage = {
  type: 'system';
  subtype: 'session_title_changed';
  title: string;
  source: 'ai' | 'custom';
  revision: number;
  uuid: string;
  session_id: string;
};
```

<div id="sdkbridgestatemessage" />

### `SDKBridgeStateMessage`

Bridge connection state change.

```typescript theme={null}
type SDKBridgeStateMessage = {
  type: 'system';
  subtype: 'bridge_state';
  state: string;
  detail?: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkfilespersistedevent" />

### `SDKFilesPersistedEvent`

File checkpoint persistence result.

```typescript theme={null}
type SDKFilesPersistedEvent = {
  type: 'system';
  subtype: 'files_persisted';
  files: { filename: string; file_id: string }[];
  failed: { filename: string; error: string }[];
  processed_at: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkelicitationcompletemessage" />

### `SDKElicitationCompleteMessage`

MCP elicitation complete.

```typescript theme={null}
type SDKElicitationCompleteMessage = {
  type: 'system';
  subtype: 'elicitation_complete';
  mcp_server_name: string;
  elicitation_id: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkpermissiondeniedmessage" />

### `SDKPermissionDeniedMessage`

Tool call short-circuited by permission policy (`dontAsk` / `auto` / deny rule, etc.).

```typescript theme={null}
type SDKPermissionDeniedMessage = {
  type: 'system';
  subtype: 'permission_denied';
  tool_name: string;
  tool_use_id: string;
  agent_id?: string;
  decision_reason_type?: string;
  decision_reason?: string;
  message: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkpromptsuggestionmessage" />

### `SDKPromptSuggestionMessage`

When `promptSuggestions: true` is enabled, next-step suggestions that may be received after each turn's result.

```typescript theme={null}
type SDKPromptSuggestionMessage = {
  type: 'prompt_suggestion';
  suggestion: string;
  uuid: string;
  session_id: string;
};
```

<div id="sdkcloudagenteventmessage" />

### `SDKCloudAgentEventMessage`

Under the Cloud runtime (`options.experimentalCloudAgent`), events forwarded from the Qoder Cloud session SSE stream. See [Cloud Agent](/en/cli/sdk/cloud-agent) for full usage.

```typescript theme={null}
type SDKCloudAgentEventMessage = {
  type: 'cloud_agent_event';
  event: string;
  id?: string;
  data: unknown;
  uuid: string;
  session_id: string;
};
```

| Field        | Type      | Description                                                                   |
| :----------- | :-------- | :---------------------------------------------------------------------------- |
| `event`      | `string`  | Cloud event name, e.g. `user.message`, `agent.message`, `session.status_idle` |
| `id`         | `string`  | SSE event ID; usable as `stream.afterId` for replay                           |
| `data`       | `unknown` | Cloud event payload (includes `turn_id` and other fields)                     |
| `session_id` | `string`  | Cloud session ID this event belongs to                                        |

<div id="sdkpermissiondenial" />

### `SDKPermissionDenial`

Element in the `SDKResultMessage.permission_denials` array.

```typescript theme={null}
type SDKPermissionDenial = {
  tool_name: string;
  tool_use_id: string;
  tool_input: Record<string, unknown>;
};
```
