# How the Letta Code SDK Grants the Subconscious Agent Access to Read, Grep, and Glob Tools

> Discover how the Letta Code SDK empowers your Subconscious agent with Read, Grep, and Glob tools. Learn to configure access via sessionOptions and environment variables for enhanced functionality.

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

---

**The Letta Code SDK grants the Subconscious agent access to Read, Grep, and Glob tools by configuring a `sessionOptions` object with `allowedTools` or `disallowedTools` arrays based on the `LETTA_SDK_TOOLS` environment variable, which defaults to a read-only whitelist defined in [`conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/conversation_utils.ts).**

The `letta-ai/claude-subconscious` repository implements a secure mechanism for controlling which client-side tools the Subconscious agent can invoke during a Letta Code SDK session. This system ensures that file-system and search operations are explicitly permitted through environment-based configuration, preventing unauthorized tool execution while allowing the agent to read and analyze codebases safely.

## Understanding the SDK Tool Access Mechanism

Tool access is governed by the **`LETTA_SDK_TOOLS`** environment variable, which supports three distinct permission modes. The function **`getSdkToolsMode()`** in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) parses this variable and returns either `'read-only'`, `'full'`, or `'off'`.

```ts
export function getSdkToolsMode(): SdkToolsMode {
  const mode = process.env.LETTA_SDK_TOOLS?.toLowerCase();
  if (mode === 'full' || mode === 'off') return mode;
  return 'read-only';
}

```

The default **read-only** mode restricts the agent to a predefined whitelist of safe, non-destructive operations. In **full** mode, the SDK removes all restrictions, enabling access to potentially destructive tools like `Bash`, `Edit`, and `Write`. The **off** mode blocks all client-side tools entirely, forcing the agent to rely solely on memory operations.

## The Read-Only Tool Whitelist in conversation_utils.ts

The specific tools available in read-only mode are declared in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) as the **`SDK_TOOLS_READ_ONLY`** constant. This array defines exactly which tool names the SDK will execute when the session operates under restricted permissions.

```ts
export const SDK_TOOLS_READ_ONLY = ['Read', 'Grep', 'Glob', 'web_search', 'fetch_webpage'];

```

These five tools provide the Subconscious agent with capabilities to inspect files (`Read`), search file contents (`Grep`), match file patterns (`Glob`), and retrieve web resources without modifying the local filesystem. According to the source code at lines 71–87, this whitelist serves as the authoritative list of permitted operations when the SDK runs in its default protective state.

## Session Initialization and Tool Filtering in send_worker_sdk.ts

The actual enforcement of tool permissions occurs in [`scripts/send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/send_worker_sdk.ts) during SDK session creation. The code constructs a **`sessionOptions`** object that passes the selected tool mode to the underlying Letta Code SDK.

When initializing the session, the worker distinguishes between three configuration paths based on `payload.sdkToolsMode`:

- **Read-only mode**: Sets `sessionOptions.allowedTools` to the `readOnlyTools` array
- **Full mode**: Leaves `allowedTools` undefined, implicitly permitting all available tools
- **Off mode**: Populates `sessionOptions.disallowedTools` with every client-side tool name, effectively blocking execution

```ts
const readOnlyTools = ['Read', 'Grep', 'Glob', 'web_search', 'fetch_webpage'];
const blockedTools = ['AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode'];

const sessionOptions: Record<string, unknown> = {
  disallowedTools: blockedTools,
  permissionMode: 'bypassPermissions',
  cwd: payload.cwd,
  // …
};

if (payload.sdkToolsMode === 'off') {
  sessionOptions.disallowedTools = [
    ...blockedTools,
    ...readOnlyTools,
    'Bash', 'Edit', 'Write', 'Task', 'Glob', 'Grep', 'Read',
  ];
} else if (payload.sdkToolsMode === 'read-only') {
  sessionOptions.allowedTools = readOnlyTools;
}
// 'full' mode leaves `allowedTools` undefined → all tools available

```

This logic appears at lines 46–66 of [`send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/send_worker_sdk.ts). When the Subconscious agent subsequently calls `session.send(payload.message)`, the SDK inspects any tool invocations in the LLM's response against these allowlists or blocklists before execution.

## Propagating Configuration from Environment to Session

The tool mode flows through multiple orchestration layers before reaching the session initializer. The entry point in [`scripts/session_start.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/session_start.ts) reads the environment variable and passes it through the payload chain:

```ts
const sdkTools = process.env.LETTA_SDK_TOOLS || 'read-only';

```

This value propagates through [`scripts/send_messages_to_letta.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/send_messages_to_letta.ts) (lines 209–214) and ultimately arrives as `payload.sdkToolsMode` in the worker script. This architecture ensures that the environment configuration controls the security boundary at the outermost layer of the application.

## Practical Configuration Examples

### Enable Default Read-Only Access

Setting the environment variable to `read-only` (or leaving it unset) grants the Subconscious agent access to file inspection and search tools while blocking modifications:

```bash
export LETTA_SDK_TOOLS=read-only
npx tsx send_messages_to_letta.ts

```

The agent can now execute:

```ts
await session.runTool('Read', { path: 'src/index.ts' });
await session.runTool('Grep', { pattern: 'function', path: 'src/**/*.ts' });
await session.runTool('Glob', { pattern: '**/*.md' });

```

### Grant Full Tool Access

To allow the agent to use `Bash`, `Edit`, `Write`, and other unrestricted tools:

```bash
export LETTA_SDK_TOOLS=full
npx tsx send_messages_to_letta.ts

```

### Disable All Client-Side Tools

To prevent any tool execution and restrict the agent to memory operations only:

```bash
export LETTA_SDK_TOOLS=off
npx tsx send_messages_to_letta.ts

```

## Summary

- **Tool access is environment-driven**: The `LETTA_SDK_TOOLS` variable selects between `read-only`, `full`, and `off` modes via `getSdkToolsMode()` in [`conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/conversation_utils.ts).
- **Read-only mode uses a whitelist**: The `SDK_TOOLS_READ_ONLY` array explicitly permits `Read`, `Grep`, `Glob`, `web_search`, and `fetch_webpage` while blocking destructive operations.
- **Session options enforce restrictions**: [`send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/send_worker_sdk.ts) translates the mode into `sessionOptions.allowedTools` or `disallowedTools` at lines 46–66.
- **Configuration propagates through the orchestration layer**: [`session_start.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/session_start.ts) reads the environment variable and passes it through [`send_messages_to_letta.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/send_messages_to_letta.ts) to the worker.

## Frequently Asked Questions

### What is the default tool mode for the Letta Code SDK?

The default mode is **read-only**. If the `LETTA_SDK_TOOLS` environment variable is not set, the `getSdkToolsMode()` function in [`conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/conversation_utils.ts) returns `'read-only'`, restricting the Subconscious agent to the `SDK_TOOLS_READ_ONLY` whitelist.

### Can I allow the Subconscious agent to use Bash or Edit tools?

Yes. Set the environment variable to `full` mode before running the session. This leaves `allowedTools` undefined in the session options, permitting access to all SDK-provided tools including `Bash`, `Edit`, `Write`, and `Task` as implemented in [`send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/send_worker_sdk.ts).

### Where is the LETTA_SDK_TOOLS environment variable read?

The variable is first read in [`scripts/session_start.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/session_start.ts) at line 298, where the code executes `const sdkTools = process.env.LETTA_SDK_TOOLS || 'read-only'`. This value is then passed through the messaging pipeline to [`send_worker_sdk.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/send_worker_sdk.ts) via the payload object.

### What happens when sdkToolsMode is set to 'off'?

In **off** mode, the SDK session is configured with an expanded `disallowedTools` list that includes all client-side tools—both the read-only set (`Read`, `Grep`, `Glob`) and the full toolset (`Bash`, `Edit`, `Write`). Any tool calls in the LLM's response are rejected, forcing the agent to operate using only memory blocks and internal reasoning.