# SDK_TOOLS_BLOCKED in Letta SDK Sessions: Why Interactive Tools Are Restricted

> Understand SDK_TOOLS_BLOCKED in Letta SDK sessions. Learn why interactive tools like AskUserQuestion are restricted to ensure deterministic, non-interactive execution and prevent hangs.

- Repository: [Letta/claude-subconscious](https://github.com/letta-ai/claude-subconscious)
- Tags: how-to-guide
- Published: 2026-03-26

---

**`SDK_TOOLS_BLOCKED`** is a constant array defined in the Letta Code SDK that explicitly prohibits `AskUserQuestion`, `EnterPlanMode`, and `ExitPlanMode` from executing during autonomous background sessions to prevent process hangs and ensure deterministic, non-interactive execution.

In the `letta-ai/claude-subconscious` repository, the Letta Code SDK imposes strict constraints on which client-side tools can run in automated environments. The `SDK_TOOLS_BLOCKED` constant serves as a critical safety mechanism that filters out interactive capabilities when Subconscious agents operate in fire-and-forget SDK sessions.

## What Is SDK_TOOLS_BLOCKED?

Defined in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts), **`SDK_TOOLS_BLOCKED`** is an exported constant containing the exact names of tools that are categorically disallowed in SDK contexts.

```typescript
// scripts/conversation_utils.ts
export const SDK_TOOLS_BLOCKED = [
  'AskUserQuestion',
  'EnterPlanMode',
  'ExitPlanMode',
];

```

The same list is hardcoded in the background worker initialization logic within [`scripts/send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/send_worker_sdk.ts), ensuring consistency across the SDK surface:

```typescript
// scripts/send_worker_sdk.ts
const blockedTools = ['AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode'];

```

## Why These Tools Are Restricted in SDK Sessions

SDK sessions are designed as **deterministic, non-interactive execution environments** launched via detached processes (`npx tsx send_worker_sdk.ts <payload>`). The three blocked tools violate this architectural constraint by requiring human intervention or UI interaction.

### AskUserQuestion: The Interactive Input Problem

**`AskUserQuestion`** prompts the user for interactive input (e.g., "What should I do next?"). SDK sessions run as background workers without a user interface or event loop for human interaction. Allowing this tool would cause the worker to block indefinitely, creating a deadlock scenario on headless servers.

### EnterPlanMode and ExitPlanMode: The Supervision Requirement

**`EnterPlanMode`** switches the agent into a planning state where it generates multi-step plans that expect user or supervising UI review. **`ExitPlanMode`** ends this state and returns to normal conversation flow. 

These modes are designed for supervised workflows where a human reviews generated plans. In autonomous SDK sessions, no such supervision exists, so allowing `EnterPlanMode` without oversight would leave the agent in an unsupported state. Blocking both tools guarantees the SDK never enters plan mode, maintaining predictable execution flow.

## How SDK Tool Restrictions Are Implemented

The restriction mechanism operates at the session initialization layer. When [`send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/send_worker_sdk.ts) creates an SDK session, it constructs a **`sessionOptions`** object that explicitly sets `disallowedTools` to the blocked list (see lines 46-53 in [`scripts/send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/send_worker_sdk.ts)).

In **read-only mode**, the SDK applies an additional filter, allowing only a curated subset of safe tools: `Read`, `Grep`, `Glob`, `web_search`, and `fetch_webpage`. All other tools—including the blocked ones—are filtered out regardless of the permission mode selected.

This dual-layer approach ensures that:
1. **Safety and resource control** prevent runaway processes or deadlocks
2. **Permission model enforcement** guarantees that even if a session is compromised, interactive tools cannot execute

## Working with SDK_TOOLS_BLOCKED in Your Code

### Checking Tool Permissions

Use the exported constant to validate tool eligibility before invoking SDK methods:

```typescript
import { SDK_TOOLS_BLOCKED } from './conversation_utils.js';

function isToolAllowed(toolName: string, mode: 'read-only' | 'full' | 'off'): boolean {
  if (mode === 'off') return false;            // no client-side tools at all
  if (SDK_TOOLS_BLOCKED.includes(toolName)) return false;
  // additional logic for read-only vs full can be added here
  return true;
}

```

### Overriding the Block List (Advanced)

If you must enable a blocked tool in a controlled environment with UI supervision, manually construct the `sessionOptions` object:

```typescript
import { resumeSession } from '@letta-ai/letta-code-sdk';

const allowedTools = ['Read', 'Grep', 'Glob', 'web_search', 'fetch_webpage', 'AskUserQuestion'];
const session = resumeSession(conversationId, {
  allowedTools,
  disallowedTools: [],                 // empty to avoid double-blocking
  permissionMode: 'bypassPermissions',
});

```

**Warning:** Enabling a blocked tool removes the safety guard and may cause the worker to hang waiting for user input that will never arrive.

## Summary

- **`SDK_TOOLS_BLOCKED`** is defined in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) and lists `AskUserQuestion`, `EnterPlanMode`, and `ExitPlanMode` as prohibited tools
- These tools are restricted because SDK sessions are fire-and-forget background processes without UI capabilities or human supervision
- The block list is enforced in [`scripts/send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/send_worker_sdk.ts) via the `sessionOptions.disallowedTools` parameter during session initialization
- Read-only mode further restricts tools to a safe subset (`Read`, `Grep`, `Glob`, `web_search`, `fetch_webpage`)
- Developers can check against the constant programmatically, though overriding the restrictions risks deadlocks and is not recommended for production environments

## Frequently Asked Questions

### What specific tools are included in SDK_TOOLS_BLOCKED?

The constant contains exactly three tools: **`AskUserQuestion`**, **`EnterPlanMode`**, and **`ExitPlanMode`**. These represent all client-side tools in the Letta Code SDK that require interactive user input or supervised planning workflows.

### Why does AskUserQuestion cause problems in SDK sessions?

SDK sessions execute as detached background processes launched via `npx tsx send_worker_sdk.ts`. There is no attached terminal or UI event loop to receive user input. Invoking `AskUserQuestion` would trigger a prompt that waits indefinitely for a response that cannot arrive, effectively deadlocking the worker process.

### Where is the blocked tool list actually enforced in the codebase?

The list is defined in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) and applied in [`scripts/send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/send_worker_sdk.ts). Specifically, lines 46-53 in the worker script construct the `sessionOptions` object that passes the `disallowedTools` array to the SDK session constructor, creating the runtime enforcement boundary.

### Can I override SDK_TOOLS_BLOCKED to enable interactive tools in my application?

Yes, by manually constructing `sessionOptions` with `permissionMode: 'bypassPermissions'` and an empty `disallowedTools` array, you can enable blocked tools. However, this is only safe if you have implemented a custom UI wrapper to handle the interactive prompts. Without such infrastructure, the SDK session will hang indefinitely, making this approach unsuitable for headless or automated deployments.