# Anthropic

The Anthropic adapter provides access to Claude models, including Claude Fable 5, Claude Sonnet 5, Claude Opus 4.8, and more.

## Installation

```sh
npm i @tanstack/ai-anthropic
```

## Basic Usage

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Hello!" }],
});
```

## Basic Usage - Custom API Key

```typescript
import { chat } from "@tanstack/ai";
import { createAnthropicChat } from "@tanstack/ai-anthropic";

const adapter = createAnthropicChat("claude-sonnet-4-6", process.env.ANTHROPIC_API_KEY!, {
  // ... your config options
});

const stream = chat({
  adapter,
  messages: [{ role: "user", content: "Hello!" }],
});
```

## Bearer and OAuth tokens

Got a Bearer token instead of an API key? Pass it as the credential and set `auth: "bearer"`. The adapter sends `Authorization: Bearer <token>` and no `x-api-key` header:

```typescript
import { chat } from "@tanstack/ai";
import { createAnthropicChat } from "@tanstack/ai-anthropic";

const adapter = createAnthropicChat("claude-sonnet-5-5", process.env.MY_CLAUDE_TOKEN!, {
  auth: "bearer",
});

const stream = chat({
  adapter,
  messages: [{ role: "user", content: "Hello!" }],
});
```

`auth` takes one of three values:

- `"api-key"`: sends the `x-api-key` header. This is the default.
- `"bearer"`: sends `Authorization: Bearer <token>` and no `x-api-key` header.
- `"oauth"`: sends the token like `"bearer"`, plus the Claude Code extras below.

Got a Claude OAuth token? It contains `sk-ant-oat`, and the adapter picks `"oauth"` for you, so you can leave `auth` out. In OAuth mode, every request also gets:

- the Claude Code identity system block, before your own system prompts.
- the Claude Code CLI headers (`user-agent` and `x-app`).
- the `claude-code-20250219` and `oauth-2025-04-20` betas.

An explicit `auth` always wins. To send an `sk-ant-oat` token as a plain Bearer token, without the extras, set `auth: "bearer"`.

Is the token in your environment? Then `anthropicText` finds it and picks `auth` for you. See [Environment Variables](#environment-variables) for the order:

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

// ANTHROPIC_AUTH_TOKEN=my-token in your environment
const stream = chat({
  adapter: anthropicText("claude-sonnet-5-5"),
  messages: [{ role: "user", content: "Hello!" }],
});
```

To call Claude models through a GitHub Copilot plan, see [GitHub Copilot](./openai-compatible#claude-models).

## Configuration

```typescript
import { createAnthropicChat, type AnthropicTextConfig } from "@tanstack/ai-anthropic";

const config: Omit<AnthropicTextConfig, "apiKey"> = {
  baseURL: "https://api.anthropic.com", // Optional, for custom endpoints
};

const adapter = createAnthropicChat("claude-sonnet-4-6", process.env.ANTHROPIC_API_KEY!, config);
```

Need a header on each request, or a log of each model call? This adapter supports [`wrapFetch`](../advanced/middleware#change-the-http-requests-of-a-call). An adapter with your own client (Claude on Vertex, or `createAnthropicChatWithClient`) ignores it, because the adapter cannot reach the fetch of that client.

## Replay thinking through a gateway

Your gateway speaks the Anthropic protocol, but it returns thinking with no signature. By default the adapter does not send unsigned thinking back, so the next turn loses it. Turn on `allowEmptySignature`:

```typescript
import { anthropicText } from "@tanstack/ai-anthropic";

const gateway = anthropicText("claude-sonnet-5-5", {
  baseURL: "https://gateway.example.com",
  provider: "my-gateway",
  allowEmptySignature: true,
});

console.log(gateway.provider); // "my-gateway"
```

- `allowEmptySignature` is `false` by default. It sends unsigned thinking back only for history from the same source.
- Redacted thinking still needs its encrypted data.
- `provider` names the gateway. History from the gateway then counts as a different source from Anthropic itself. See [Keep saved history when you switch](../advanced/runtime-adapter-switching#keep-saved-history-when-you-switch).

## Claude on Vertex

Use `@tanstack/ai-anthropic/vertex` when Claude must run on Vertex AI. That
is the path for regional endpoints and Google Cloud credentials.

Install the Vertex SDK next to the Anthropic adapter:

```sh
npm i @tanstack/ai-anthropic @anthropic-ai/vertex-sdk
```

```typescript
import { chat } from "@tanstack/ai";
import { anthropicVertexText } from "@tanstack/ai-anthropic/vertex";

const stream = chat({
  adapter: anthropicVertexText("claude-sonnet-5", {
    project: "my-project",
    location: "europe-west1",
  }),
  messages: [{ role: "user", content: "Hello!" }],
});
```

`anthropicVertexText` accepts only the Claude models in the Vertex catalog.
It does not accept Anthropic-only ids such as `claude-opus-5-fast`.

`project` and `location` use the same names as `@tanstack/ai-vertex`, so one
auth object works for Gemini and Claude.

If you omit `project`, Application Default Credentials can still fill it.
`location` is required. You can pass it on the factory or set
`GOOGLE_CLOUD_LOCATION`, `GOOGLE_VERTEX_LOCATION`, or `CLOUD_ML_REGION`.

Gemini on Vertex lives in [`@tanstack/ai-vertex`](./vertex).

## Custom Anthropic client

Use `createAnthropicChatWithClient` when you already have an
Anthropic-compatible client. The adapter only needs `beta.messages.create`.
Message mapping, streaming, tools, media, usage, and structured output stay
on the same TanStack path.

```sh
npm i @tanstack/ai-anthropic @anthropic-ai/vertex-sdk
```

```typescript
import { AnthropicVertex } from "@anthropic-ai/vertex-sdk";
import { createAnthropicChatWithClient } from "@tanstack/ai-anthropic";

const client = new AnthropicVertex({
  projectId: "my-project",
  region: "europe-west1",
});

const adapter = createAnthropicChatWithClient("claude-sonnet-5", client);
```

The injected client must implement the Anthropic Beta Messages protocol.
Endpoint-specific model and feature support stays the caller's job.

## Example: Chat Completion

```typescript
import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

export async function POST(request: Request) {
  const { messages } = await request.json();

  const stream = chat({
    adapter: anthropicText("claude-sonnet-4-6"),
    messages,
  });

  return toServerSentEventsResponse(stream);
}
```

## Example: With Tools

```typescript
import { chat, toServerSentEventsResponse, toolDefinition } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { z } from "zod";

const searchDatabaseDef = toolDefinition({
  name: "search_database",
  description: "Search the database",
  inputSchema: z.object({
    query: z.string(),
  }),
});

const searchDatabase = searchDatabaseDef.server(async ({ query }) => {
  // Search database
  return { results: [] };
});

export async function POST(request: Request) {
  const { messages } = await request.json();

  const stream = chat({
    adapter: anthropicText("claude-sonnet-4-6"),
    messages,
    tools: [searchDatabase],
  });

  return toServerSentEventsResponse(stream);
}
```

## Model Options

Anthropic supports various provider-specific options. Sampling parameters live here too — `temperature`, `top_p`, and `max_tokens` — rather than as root-level props on `chat()`:

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Hello!" }],
  modelOptions: {
    max_tokens: 4096,
    temperature: 0.7,
    top_p: 0.9,
    top_k: 40,
    stop_sequences: ["END"],
  },
});
```

> If you previously passed `temperature` / `topP` / `maxTokens` at the root of `chat()`, see [Moving Sampling Options into modelOptions](../migration/sampling-options-to-model-options).

#### `max_tokens` default

Anthropic's Messages API _requires_ `max_tokens` on every request, so the adapter always sends a value. When you don't set `modelOptions.max_tokens`, it defaults to the selected model's full output ceiling (`max_output_tokens` from the model metadata — e.g. 64K for Sonnet, 128K for Opus), falling back to a safe constant for unrecognized models. `max_tokens` is a ceiling, not a reservation — billing is on tokens actually generated — so this default costs nothing extra and avoids the silent mid-response truncation (`stop_reason: "max_tokens"`) that a low default would cause. Set `max_tokens` explicitly only when you want to _cap_ output below the model ceiling. If a response is truncated while using the default cap, the adapter logs a warning (visible with [debug logging](../advanced/debug-logging) enabled).

A streamed response that stops at `max_tokens` ends in a `RUN_ERROR` with `code: 'max_tokens'`. Anthropic bills the tokens of that call, so this `RUN_ERROR` carries the `usage` of the call. The `onUsage` middleware hook fires only for `RUN_FINISHED`. To count these tokens too, read `usage` from the `RUN_ERROR` chunk, in the stream or in an `onChunk` middleware.

One exception: structured output (`chat({ outputSchema })`) on models that use the non-streaming finalization path clamps this default to ~21K tokens. The Anthropic SDK rejects a non-streaming request whose `max_tokens` could exceed its 10-minute timeout, so the full ceiling can't be used there. Streaming chat is unaffected. To raise the structured-output ceiling toward a model's true max, stream the response.

### Reasoning

Want Claude to think harder, or not at all? Set `reasoning` on `chat()`. The adapter turns the level into the right thinking fields for the model.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

const stream = chat({
  adapter: anthropicText("claude-opus-5-5"),
  messages: [{ role: "user", content: "Plan a database migration." }],
  reasoning: "xhigh",
});
```

What goes on the wire:

- `off` sends `thinking: { type: "disabled" }` on the models with `off` in the table below. On a model without `off`, such as `claude-fable-5`, the types reject it, and at run time it moves to the lowest level that the model has.
- Claude 4.6 and later get adaptive thinking and `output_config.effort`. With an `outputSchema`, the adapter adds `output_config.format` next to the effort.
- Budget models get `thinking: { type: "enabled", budget_tokens }`. The level picks the budget, or you set it with `budgetTokens`. The adapter raises `max_tokens` when it is below the budget.
- `summary: false` sends `display: "omitted"`, so the thinking text does not stream.

The levels of each model:

| Model | Levels | `budgetTokens` |
| --- | --- | --- |
| `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-fable-5-1`, `claude-fable-5`, `claude-opus-5`, `claude-opus-4-8`, `claude-opus-4-7` | `low` to `max` | no |
| `claude-haiku-5-5`, `claude-sonnet-5` | `off`, `low` to `max` | no |
| `claude-opus-5-fast` | `off`, `low` to `max` | yes |
| `claude-opus-4-6`, `claude-sonnet-4-6` | `low`, `medium`, `high`, `max` | yes |
| `claude-opus-4-5` | `low`, `medium`, `high` | yes |
| `claude-haiku-4-5`, `claude-sonnet-4-5`, `claude-opus-4-1` | `off` to `high` | yes |

A budget model with `budgetTokens`:

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

const stream = chat({
  adapter: anthropicText("claude-haiku-4-5"),
  messages: [{ role: "user", content: "Check this proof." }],
  reasoning: { level: "high", budgetTokens: 8000 },
});
```

Claude Sonnet 5, Claude Opus 4.7 and later, and the 5-generation models reject the sampling options (`temperature`, `top_p`, `top_k`). The types take them only on the models that accept them. See [Reasoning](../chat/reasoning) for the levels and the nearest-level rule.

Structured output forces a tool, and Claude cannot think while a tool is forced. So the structured output call sends no thinking.

### Prompt Caching

`chat()` caches Claude prompts by default. It adds `cache_control` markers to the last start tool, the last block of the last user or mid-conversation system message, and the system blocks. At most 4 markers. The last start tool is the tool before the deferred placeholder, or the last tool. Pass `promptCache: 'long'` for the 1-hour cache, or `promptCache: 'none'` to send no markers. For the key and the cost, see [Prompt Caching](../advanced/prompt-caching).

Want the markers in other places? Set `cache_control` in the `metadata` of a message part, a system prompt, or a tool. One marker of your own turns the automatic markers off for that request:

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";

const stream = chat({
  adapter: anthropicText("claude-opus-5-5"),
  messages: [
    {
      role: "user",
      content: [
        {
          type: "text",
          content: "What is the capital of France?",
          metadata: {
            cache_control: {
              type: "ephemeral",
            },
          },
        },
      ],
    },
  ],
});
```

`modelOptions.cache_control` also turns the automatic markers off.

`usage.promptTokens` counts the full input, cached tokens included. The cache reads and writes are also on `usage.promptTokensDetails`. See [Token usage](../chat/stream-events#token-usage).

#### Tools and prompts added during a conversation

On `claude-opus-4-8`, `claude-opus-5`, `claude-opus-5-5`, `claude-fable-5`, and `claude-fable-5-1`, a tool or a system prompt that you add between model calls goes into the conversation. The cached start of the request stays the same.

What the adapter sends on these models:

- `system` keeps the system prompts of the first call.
- A request with tools gets the `mid-conversation-tool-changes-2026-07-01` beta and one placeholder tool, `__tanstack_deferred_placeholder__`. The model never calls it.
- An added tool goes at the end of `tools` with `defer_loading: true`. A `system` message names it in a `tool_addition` block.
- An added system prompt goes into a `system` message, before the next assistant message or at the end.
- With a provider tool such as `webSearchTool()`, `tools` is the full list and has no placeholder.

The automatic tool marker stays on the last tool of the first call, so the marked start does not move.

The channels are on by default with Anthropic's own API. A custom `baseURL`, a custom `fetch`, `ANTHROPIC_BASE_URL`, or your own client turns them off. Set `midConversationChannels` to choose:

```typescript
import { anthropicText } from "@tanstack/ai-anthropic";

export const fullLists = anthropicText("claude-opus-5-5", {
  midConversationChannels: false,
});

export const throughProxy = anthropicText("claude-opus-5-5", {
  baseURL: "https://llm-proxy.example.com",
  midConversationChannels: true,
});
```

If that endpoint sends the request and the `anthropic-beta` header on to Anthropic as they are, set `true`. See [Mid-Conversation Changes](../advanced/mid-conversation-changes).

## Summarization

Anthropic supports text summarization:

```typescript
import { summarize } from "@tanstack/ai";
import { anthropicSummarize } from "@tanstack/ai-anthropic";

const result = await summarize({
  adapter: anthropicSummarize("claude-sonnet-4-6"),
  text: "Your long text to summarize...",
  maxLength: 100,
  style: "concise", // "concise" | "bullet-points" | "paragraph"
});

console.log(result.summary);
```

## Environment Variables

Set one of these. `anthropicText`, `anthropicSummarize`, and `anthropicFiles` use the first one that is set:

1. `ANTHROPIC_AUTH_TOKEN`: sent as a Bearer token. An `sk-ant-oat` token here turns on OAuth mode.
2. `ANTHROPIC_OAUTH_TOKEN`: sent as a Bearer token, in OAuth mode.
3. `ANTHROPIC_API_KEY`: sent as `x-api-key`.

```bash
ANTHROPIC_API_KEY=sk-ant-...
```

If none of them is set, these factories throw. An `auth` in the config wins over the kind that the adapter picks. See [Bearer and OAuth tokens](#bearer-and-oauth-tokens) for what OAuth mode adds.

The `create*` factories (`createAnthropicChat`, `createAnthropicSummarize`, `createAnthropicFiles`) never read a credential from the environment. They use only the credential that you pass.

## API Reference

Every factory pair has the same shape. The short factory (`anthropicText`, `anthropicSummarize`) reads the credential from the [environment](#environment-variables). `createAnthropicChat` / `createAnthropicSummarize` take an explicit credential and never read one from the environment. Both take `model` as the first argument. For Claude on Vertex, use `anthropicVertexText` from `@tanstack/ai-anthropic/vertex`. For any other custom transport, `createAnthropicChatWithClient` accepts an Anthropic-compatible Messages client.

### `anthropicText(model, config?)` / `createAnthropicChat(model, apiKey, config?)`

Creates an Anthropic chat adapter.

`adapter.inputModalities` lists the input kinds of the selected model. It is `undefined` for a model that this package does not know. See [Check what a model accepts](../advanced/extend-adapter#check-what-a-model-accepts).

**Parameters:**

- `model` - Claude model id (e.g. `"claude-sonnet-5"`, `"claude-fable-5"`, `"claude-opus-4-8"`)
- `apiKey` - API key, Bearer token, or Claude OAuth token (`createAnthropicChat` only)
- `config?.baseURL` - Custom base URL (optional)
- `config?.auth` - How to send the credential: `"api-key"`, `"bearer"`, or `"oauth"` (optional, see [Bearer and OAuth tokens](#bearer-and-oauth-tokens))
- `config?.allowEmptySignature` - Send unsigned thinking back to the same source (optional, default `false`, see [Replay thinking through a gateway](#replay-thinking-through-a-gateway))
- `config?.provider` - The source name for a gateway (optional, default `"anthropic"`)

### `anthropicVertexText(model, config?)`

Creates an Anthropic chat adapter on Vertex. Import it from
`@tanstack/ai-anthropic/vertex`.

**Parameters:**

- `model` - Claude model id
- `config.project` - GCP project id (optional if ADC can resolve it)
- `config.location` - Vertex region (or set `GOOGLE_CLOUD_LOCATION`)

### `createAnthropicChatWithClient(model, client)`

Creates an Anthropic chat adapter using an injected client.

**Parameters:**

- `model` - Claude model id
- `client` - Client exposing `beta.messages.create`

### `anthropicSummarize(model, config?)` / `createAnthropicSummarize(model, apiKey, config?)`

Creates an Anthropic summarization adapter.

## Limitations

- **Image Generation**: Anthropic does not support image generation. Use OpenAI or Gemini for image generation.

## Next Steps

- [Getting Started](../getting-started/quick-start) - Learn the basics
- [Tools Guide](../tools/tools) - Learn about tools
- [Other Adapters](./openai) - Explore other providers

## Provider Tools

Anthropic exposes several native tools beyond user-defined function calls.
Import them from `@tanstack/ai-anthropic/tools` and pass them into
`chat({ tools: [...] })`.

> For the full concept, a comparison matrix, and type-gating details, see
> [Provider Tools](../tools/provider-tools.md).

### `webSearchTool`

Enables Claude to run Anthropic's native web search with inline citations.
Scope the search with `allowed_domains` or `blocked_domains` (mutually
exclusive); set `max_uses` to cap per-turn cost.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { webSearchTool } from "@tanstack/ai-anthropic/tools";

const stream = chat({
  adapter: anthropicText("claude-opus-4-7"),
  messages: [{ role: "user", content: "What's new in AI this week?" }],
  tools: [
    webSearchTool({
      name: "web_search",
      type: "web_search_20250305",
      max_uses: 2,
    }),
  ],
});
```

**Supported models:** every registered Claude model. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).

### `webFetchTool`

Lets Claude fetch the contents of a URL directly, useful when you want the
model to read a specific page rather than run a search. Takes no required
arguments — pass an optional config object to override defaults.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { webFetchTool } from "@tanstack/ai-anthropic/tools";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Summarise https://example.com" }],
  tools: [webFetchTool()],
});
```

**Supported models:** Claude Sonnet 4.x and above. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).

### `codeExecutionTool`

Gives Claude a sandboxed code-execution environment so it can run Python
snippets, analyse data, and return results inline. Choose the version string
that matches your desired API revision.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { codeExecutionTool } from "@tanstack/ai-anthropic/tools";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Plot a histogram of [1,2,2,3,3,3]" }],
  tools: [
    codeExecutionTool({ name: "code_execution", type: "code_execution_20250825" }),
  ],
});
```

**Supported models:** Claude Sonnet 4.x and above. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).

#### Attaching hosted skills

Pass a `skills` array as the second argument to load provider-managed skill
bundles into the sandbox. The adapter auto-lifts them into the API's
`container.skills` param and adds the required beta headers for you.

```typescript
import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { codeExecutionTool } from "@tanstack/ai-anthropic/tools";

export async function POST(request: Request) {
  const { messages } = await request.json();

  const stream = chat({
    adapter: anthropicText("claude-sonnet-4-5"),
    messages,
    tools: [
      codeExecutionTool(
        { type: "code_execution_20250825", name: "code_execution" },
        {
          skills: [{ type: "anthropic", skill_id: "pptx", version: "latest" }],
        },
      ),
    ],
  });

  return toServerSentEventsResponse(stream);
}
```

For the full reference — skill shape, constraints, scope, and the OpenAI
equivalent — see [Provider Skills](../tools/provider-skills.md).

### `computerUseTool`

Allows Claude to observe a virtual desktop (screenshots) and interact with it
via keyboard and mouse events. Provide the screen resolution so Claude can
calculate accurate coordinates.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { computerUseTool } from "@tanstack/ai-anthropic/tools";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Open the browser and go to example.com" }],
  tools: [
    computerUseTool({
      type: "computer_20250124",
      name: "computer",
      display_width_px: 1024,
      display_height_px: 768,
    }),
  ],
});
```

**Supported models:** Claude Sonnet 3.5 and above, with two exceptions. `claude-opus-5-fast` takes no provider tools. Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5 accept only the `computer_toolset_20260801` toolset, which the adapter does not offer yet. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).

### `bashTool`

Provides Claude with a persistent bash shell session, letting it run arbitrary
commands, install packages, or manipulate files on the host. Choose the type
string that matches your API revision.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { bashTool } from "@tanstack/ai-anthropic/tools";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "List all TypeScript files in src/" }],
  tools: [bashTool({ name: "bash", type: "bash_20250124" })],
});
```

**Supported models:** Claude Sonnet 3.5 and above. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).

### `textEditorTool`

Gives Claude a structured text-editor interface for viewing and modifying files
using `str_replace`, `create`, `view`, and `undo_edit` commands. Choose the
type string for the API revision you target.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { textEditorTool } from "@tanstack/ai-anthropic/tools";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Fix the bug in src/index.ts" }],
  tools: [
    textEditorTool({ type: "text_editor_20250124", name: "str_replace_editor" }),
  ],
});
```

**Supported models:** Claude Sonnet 3.5 and above. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).

### `memoryTool`

Enables Claude to store and retrieve information across conversation turns
using Anthropic's managed memory service. Call with no arguments to use
default configuration.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { memoryTool } from "@tanstack/ai-anthropic/tools";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Remember that I prefer metric units" }],
  tools: [memoryTool()],
});
```

**Supported models:** Claude Sonnet 4.x and above. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).

### `customTool`

Creates a tool with an inline JSON Schema input definition instead of going
through `toolDefinition()`. Useful when you need fine-grained control over the
schema shape or want to add `cache_control`. Unlike branded provider tools,
`customTool` returns a plain `Tool` and is accepted by any chat model.

```typescript
import { chat } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { customTool } from "@tanstack/ai-anthropic/tools";
import { z } from "zod";

const stream = chat({
  adapter: anthropicText("claude-sonnet-4-6"),
  messages: [{ role: "user", content: "Look up user 42" }],
  tools: [
    customTool(
      "lookup_user",
      "Look up a user by ID and return their profile",
      z.object({ userId: z.number() }),
    ),
  ],
});
```

**Supported models:** all current Claude models. See [Provider Tools](../tools/provider-tools.md#which-models-support-which-tools).
