# Extracting Thinking or Reasoning Content from LLM Model Responses in aisuite

> Learn how aisuite extracts thinking or reasoning content from LLM responses. It automatically parses thinking tags, storing internal reasoning separately for clear analysis.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: how-to-guide
- Published: 2026-08-04

---

**aisuite automatically parses `<thinking>` tags from LLM responses, storing internal reasoning in `Message.reasoning_content` while keeping the final answer in `Message.content`.**

aisuite provides a unified interface for multiple large language model providers, standardizing how developers interact with diverse APIs. When models return hidden chain-of-thought or reasoning steps wrapped in special tags, aisuite offers a built-in mechanism to extract and isolate this content from the final user-facing output.

## How aisuite Extracts Reasoning Content

### The `<thinking>` Tag Convention

aisuite looks for content wrapped in `<thinking>` tags at the start of a model's response. When the raw content begins with `<thinking>`, the framework treats everything between the opening and closing tags as internal reasoning to be separated from the public answer.

### The Four-Step Extraction Process

According to the source code in [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py), the `_extract_thinking_content` method implements a lightweight parsing pipeline:

1. **Detect the tag** – Checks if the response content starts with `<thinking>`.
2. **Isolate reasoning** – Extracts the string between `<thinking>` and `</thinking>` tags.
3. **Store separately** – Assigns the extracted text to the `reasoning_content` attribute of the `Message` object, defined in [`aisuite/framework/message.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/message.py) (lines 29-31).
4. **Clean visible output** – Rewrites the `content` attribute to contain only the text appearing after the closing `</thinking>` tag.

After extraction, the normal response-handling pipeline emits a `model.response` event via `_handle_model_response`, making the reasoning available for tracing sinks and observability tools.

## Accessing Reasoning Content in Your Code

After calling `client.chat.completions.create()`, you can inspect both the reasoning and the final answer through the response object's `Message` instance.

```python
import aisuite

client = aisuite.Client()

response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=[{"role": "user", "content": "Explain the steps to solve this problem"}],
)

# Access the hidden reasoning

reasoning = response.choices[0].message.reasoning_content
print(f"Internal reasoning: {reasoning}")

# Access the final user-facing answer

answer = response.choices[0].message.content
print(f"Final answer: {answer}")

```

When a model returns content formatted as `<thinking>The model's internal chain-of-thought...</thinking>\nHere is the final answer...`, the `reasoning_content` field receives `"The model's internal chain-of-thought..."` while `content` becomes `"Here is the final answer..."`.

## Implementation Architecture

### Message Model Extension

The `Message` class in [`aisuite/framework/message.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/message.py) (lines 29-31) defines the `reasoning_content` attribute alongside the standard `content` field. This design keeps reasoning separate from public output while preserving it for downstream processing, debugging, or auditing.

### Client-Side Processing

The extraction logic resides in [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py) within the `_extract_thinking_content` helper. This method modifies the response object in-place before it returns to the caller, ensuring that `Message.reasoning_content` contains the parsed reasoning and `Message.content` contains the sanitized visible text.

## Testing the Extraction Logic

The test suite validates this behavior in [`tests/client/test_client.py`](https://github.com/andrewyng/aisuite/blob/main/tests/client/test_client.py) (lines 18-33) through the `test_chat_completions_extracts_thinking_content` test case. This test verifies that when a mock response contains `<thinking>private reasoning</thinking>\nFinal answer`, the resulting `Message` object correctly stores `"private reasoning"` in `reasoning_content` and `"Final answer"` in `content`.

## Summary

- aisuite automatically extracts text wrapped in `<thinking>` tags from LLM responses when the content starts with the opening tag.
- Extracted reasoning is stored in `Message.reasoning_content`, defined in [`aisuite/framework/message.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/message.py) (lines 29-31).
- The visible `content` field contains only the text after the closing `</thinking>` tag, hiding the reasoning from end users.
- The extraction logic is implemented in `_extract_thinking_content` within [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py).
- Tracing events include the reasoning content via the standard `model.response` event pipeline.

## Frequently Asked Questions

### What tag format does aisuite use for reasoning extraction?

aisuite specifically looks for `<thinking>` tags at the beginning of the response content. The opening tag must appear immediately at the start of the text, with the reasoning content between `<thinking>` and `</thinking>`, followed by the final answer. Content not starting with `<thinking>` passes through unchanged with `reasoning_content` set to `None`.

### How do I access the reasoning content after a chat completion?

Access the `reasoning_content` attribute on the `Message` object returned in the response choices: `response.choices[0].message.reasoning_content`. This field contains the extracted text from between the thinking tags, or `None` if no reasoning was detected during the extraction process.

### Does aisuite modify the original response content when extracting reasoning?

Yes, aisuite rewrites the `content` field to remove the thinking tags and their contents. The `content` attribute will contain only the text that appeared after the closing `</thinking>` tag, ensuring end-users see only the final answer without the intermediate reasoning steps.

### Can I manually inject reasoning content using this mechanism?

Yes, you can manually format your message content with `<thinking>` tags. If you construct a response or prompt with content formatted as `<thinking>your reasoning here</thinking>\nyour final answer`, aisuite will automatically parse and separate these components into the respective `reasoning_content` and `content` attributes.