# How to Enable and Configure Thinking Capabilities for LLM Models in OpenMAIC

> Learn how to enable and configure thinking capabilities for LLM models in OpenMAIC. Understand the automatic activation and configuration process using createPartMapper and ThinkingBarState.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: how-to-guide
- Published: 2026-08-30

---

**OpenMAIC automatically activates thinking capabilities when your LLM provider emits reasoning parts, which are mapped through `createPartMapper` in [`lib/agent/runtime/stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent/runtime/stream-fn.ts) and rendered via the `ThinkingBarState` component.**

OpenMAIC treats a model's reasoning process as a separate content stream called **thinking**, providing real-time visibility into the LLM's internal deliberation. Unlike static feature toggles, thinking capabilities require no manual activation; they engage automatically when you configure a provider that streams reasoning deltas. This guide explains the three-layer architecture—stream mapping, state management, and UI rendering—and provides the exact configuration steps to integrate thinking into your workspace.

## Understanding the Thinking Architecture

OpenMAIC implements thinking capabilities through a three-tier pipeline that transforms raw provider streams into visible UI elements.

### Stream Function Mapping

At the ingestion layer, the **`createPartMapper`** function in **[`lib/agent/runtime/stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent/runtime/stream-fn.ts)** intercepts AI-SDK v6 parts such as `reasoning-delta`, `reasoning-start`, and `reasoning-end`. According to the OpenMAIC source code, this mapper translates provider-specific reasoning events into internal thinking events (`thinking_start`, `thinking_delta`, `thinking_end`) between lines 63-66 and 202-215, while isolating the final textual answer into a distinct content block.

### State Management

The mapped events fold into the workbench state at `state.chat`. When the first reasoning part arrives, OpenMAIC instantiates a thinking node with `kind: 'thinking'`. Subsequent deltas update this node until a `thinking_end` event fires, at which point the node closes and its total duration is calculated from the attached timestamps.

### UI Rendering

The **`ThinkingBarState`** component located in **[`components/workbench/chat/thinking-bar-state.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/workbench/chat/thinking-bar-state.ts)** consumes the node’s `streaming` flag and optional `duration` field. While the model deliberates, the bar displays "思考中…" (thinking…); upon completion, it shows "已思考 <duration>". This component is exercised by the test suite in **[`tests/workbench/thinking-stream-seam.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/workbench/thinking-stream-seam.test.ts)** (lines 53-67), ensuring the thinking bar appears before the assistant message finalizes.

## Enabling Thinking Capabilities

Thinking is not a binary toggle. It activates automatically when your chosen LLM model streams reasoning parts. Follow these steps to ensure your provider emits the necessary events.

### Select a Compatible Provider

Choose an LLM provider that supports the reasoning channel. Compatible options include:

- **Google Gemini** (`gemini-1.5-flash`)
- **Anthropic Claude** (`claude-3-haiku`)
- **OpenAI** models configured with `response_format: {type: "json_object"}` and `stream_options: {include_reasoning: true}`

These providers emit `reasoning-*` parts that `createPartMapper` recognizes and translates.

### Configure Provider Options

Instantiate your LLM connector with provider-specific reasoning flags. In your workspace entry point (such as **[`app/workspace/page.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/app/workspace/page.tsx)**), pass the appropriate options to **`createCallLlmStreamFn`**:

```typescript
import { createCallLlmStreamFn } from '@/lib/agent/runtime/stream-fn';

const streamFn = createCallLlmStreamFn({
  model: 'gemini-1.5-flash',
  // Requests the reasoning channel from the provider
  extraProviderOptions: { includeReasoning: true },
});

```

When you invoke the session, the connector forwards the reasoning flag to the underlying SDK, ensuring the stream contains the required `reasoning-*` parts:

```typescript
await session.run({
  messages: [{ role: 'user', content: 'Explain the algorithm step by step.' }],
  streamFn,
});

```

### Verify UI Activation

The UI reads `state.thinkingKey`, which is set automatically when a `thinking_start` event arrives. No additional code is required for standard operation. However, for debugging purposes, you can force the thinking bar to appear by manually setting `state.thinkingKey = Symbol();` in a custom hook, guaranteeing visibility even if the provider fails to emit reasoning parts.

## Configuring the Thinking Display

Once thinking is active, you can customize how duration appears in the interface.

### Customizing Duration Text

The display logic resides in the helper functions within **[`components/workbench/chat/thinking-bar-state.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/workbench/chat/thinking-bar-state.ts)**. To modify the label or localization, edit the **`thinkingBarSummary`** function:

```typescript
export const thinkingBarSummary = ({ streaming, duration }: { streaming: boolean; duration?: string }) =>
  streaming ? '思考中…' : `已思考${duration ? ` ${duration}` : ''}`;

```

Adjust the string literals or implement internationalization logic as needed. The duration calculation itself occurs in [`stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stream-fn.ts) around line 2062, where timestamps from `thinking_start` and `thinking_end` events determine the elapsed time.

## Complete Implementation Example

Combine provider selection, stream configuration, and optional UI customization in a single implementation:

```typescript
// lib/agent/config.ts
import { createCallLlmStreamFn } from '@/lib/agent/runtime/stream-fn';

export function initializeThinkingStream() {
  return createCallLlmStreamFn({
    model: 'gemini-1.5-flash',
    extraProviderOptions: { includeReasoning: true },
  });
}

```

```tsx
// components/CustomThinkingBar.tsx
import { thinkingBarSummary } from '@/components/workbench/chat/thinking-bar-state';

interface ThinkingBarProps {
  streaming: boolean;
  duration?: string;
}

export function CustomThinkingBar({ streaming, duration }: ThinkingBarProps) {
  return (
    <span className="my-thinking-indicator">
      {thinkingBarSummary({ streaming, duration })}
    </span>
  );
}

```

The `ThinkingBarState` component automatically manages the rendering lifecycle according to the events processed in **[`lib/agent/runtime/stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent/runtime/stream-fn.ts)**.

## Key Files and References

- **[`lib/agent/runtime/stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent/runtime/stream-fn.ts)** – Core mapper that translates `reasoning-*` parts into `thinking_*` events (lines 63-66, 202-215).
- **[`components/workbench/chat/thinking-bar-state.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/workbench/chat/thinking-bar-state.ts)** – UI helpers including `thinkingBarSummary` for rendering the thinking bar and duration text.
- **[`tests/workbench/thinking-stream-seam.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/workbench/thinking-stream-seam.test.ts)** – Integration tests verifying that the thinking bar appears before the assistant message completes (lines 53-67).
- **[`tests/workbench/thinking-bar-state.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/workbench/thinking-bar-state.test.ts)** – Unit tests for UI summary functions and state transitions.
- **[`app/workspace/page.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/app/workspace/page.tsx)** – Typical location where `createCallLlmStreamFn` is instantiated with model-specific options.

## Summary

- **Thinking capabilities activate automatically** when you use a provider that streams reasoning parts; no manual toggle exists in OpenMAIC.
- **Stream mapping** occurs in [`lib/agent/runtime/stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent/runtime/stream-fn.ts) via `createPartMapper`, which converts `reasoning-delta` events into `thinking_start`, `thinking_delta`, and `thinking_end` events.
- **Provider configuration** requires passing `extraProviderOptions: { includeReasoning: true }` (or equivalent) to `createCallLlmStreamFn` in your workspace initialization.
- **State management** creates a `kind: 'thinking'` node in `state.chat` that tracks duration from start to end timestamps.
- **UI rendering** is handled by `ThinkingBarState` in [`components/workbench/chat/thinking-bar-state.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/workbench/chat/thinking-bar-state.ts), displaying real-time status and final duration.

## Frequently Asked Questions

### Is thinking enabled by default in OpenMAIC?

No explicit enablement is required. Thinking capabilities are **automatically available** whenever your configured LLM provider emits reasoning parts such as `reasoning-delta`. If the provider does not support or is not configured to stream reasoning content, the thinking UI will not appear, and the assistant's response will stream as plain text only.

### Which LLM providers support thinking capabilities?

OpenMAIC supports any provider that implements AI-SDK v6 reasoning parts. Verified compatible providers include **Google Gemini** (e.g., `gemini-1.5-flash`), **Anthropic Claude** (e.g., `claude-3-haiku`), and **OpenAI** models when configured with `stream_options: {include_reasoning: true}`. The specific option names vary by provider, but all are passed through `extraProviderOptions` in `createCallLlmStreamFn`.

### How can I customize the thinking duration display format?

Edit the **`thinkingBarSummary`** function in [`components/workbench/chat/thinking-bar-state.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/workbench/chat/thinking-bar-state.ts). This helper receives `streaming` (boolean) and `duration` (string) parameters, allowing you to modify the returned string literals or implement localization logic. The underlying duration calculation is performed in [`stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stream-fn.ts) based on timestamps attached to `thinking_start` and `thinking_end` events.

### What happens if my model doesn't emit reasoning parts?

If the LLM provider does not stream `reasoning-start`, `reasoning-delta`, or `reasoning-end` parts, the `createPartMapper` in [`lib/agent/runtime/stream-fn.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent/runtime/stream-fn.ts) will never generate thinking events. Consequently, no `kind: 'thinking'` node is created in `state.chat`, and the `ThinkingBarState` UI component remains hidden. The assistant's response will appear as a standard text stream without any thinking indicator.