DEV Community

shashank ms
shashank ms

Posted on

Introduction to Chain-of-Thought Reasoning Architecture

We will build a lightweight chain-of-thought research agent that breaks complex questions into explicit reasoning steps before committing to an answer. This architecture improves accuracy on multi-step analytical problems, and because Oxlo.ai uses flat per-request pricing, long reasoning traces do not inflate your bill.

What you will need

Step 1: Scaffold the project and test the connection

First, I verify that the Oxlo.ai client is configured correctly and that I can reach the API. I will use the DeepSeek V3.2 model because it handles reasoning well and is available on the free tier.

from openai import OpenAI

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

response = client.chat.completions.create(
    model="deepseek-v3.2",
    messages=[
        {"role": "user", "content": "Say hello"}
    ],
)

print(response.choices[0].message.content)

Step 2: Write the chain-of-thought system prompt

The core of this architecture is the system prompt. It forces the model to emit a reasoning trace inside <think> tags before giving the final answer. I store this as a module-level constant so I can iterate on it without touching the calling code.

SYSTEM_PROMPT = '''You are a research analyst that solves problems through explicit chain-of-thought reasoning.

When you receive a question, follow these rules strictly:
1. First, analyze what the question is asking and identify the key facts and sub-problems.
2. Second, reason through each sub-problem step by step inside <think>...</think> tags.
3. Third, verify your intermediate results and note any uncertainties.
4. Finally, provide the concise final answer outside of the <think> tags.

Always include the reasoning trace. Do not skip the <think> block.'''

Step 3: Call the model with the CoT prompt

Now I wire the system prompt into the chat completion. I send a multi-step math problem that is easy to get wrong if you rush to the answer.

USER_QUESTION = (
    "A bat and a ball cost $110 in total. "
    "The bat costs $100 more than the ball. "
    "How much does the ball cost? "
    "Think carefully and show your reasoning."
)

response = client.chat.completions.create(
    model="deepseek-v3.2",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": USER_QUESTION},
    ],
)

raw_output = response.choices[0].message.content
print(raw_output)

Step 4: Parse reasoning and final answer

Raw text is not enough for a production agent. I need to separate the reasoning trace from the answer so I can log the chain of thought or surface it in a UI. I will use a small parser with a regular expression.

import re

def parse_cot(response_text: str):
    think_match = re.search(r"<think>(.*?)</think>", response_text, re.DOTALL)
    reasoning = think_match.group(1).strip() if think_match else ""
    
    answer = re.sub(r"<think>.*?</think>", "", response_text, flags=re.DOTALL).strip()
    return reasoning, answer

reasoning, answer = parse_cot(raw_output)

print("=== REASONING ===")
print(reasoning)
print("\n=== ANSWER ===")
print(answer)

Step 5: Add a self-check loop

A strong CoT architecture does not stop at one pass. I add a verification step where the model critiques its own answer. If it detects a mistake, it regenerates. This costs only one more request on Oxlo.ai because pricing is per request, not per token.

VERIFY_PROMPT = (
    "You just answered a question. Review your previous reasoning and answer below. "
    "If you find an error, say CORRECTION_NEEDED and provide the corrected answer. "
    "If the answer is correct, say VERIFIED.\n\n"
    f"Previous reasoning:\n{reasoning}\n\n"
    f"Previous answer:\n{answer}"
)

verify_response = client.chat.completions.create(
    model="deepseek-v3.2",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": USER_QUESTION},
        {"role": "assistant", "content": raw_output},
        {"role": "user", "content": VERIFY_PROMPT},
    ],
)

print(verify_response.choices[0].message.content)

Step 6: Wrap everything in a reusable agent class

To make this shippable, I package the parser and the verification logic into a small class. This is the architecture I would actually import into a larger service.

class CoTAgent:
    def __init__(self, client: OpenAI, model: str = "deepseek-v3.2"):
        self.client = client
        self.model = model
        self.system_prompt = SYSTEM_PROMPT

    def ask(self, question: str, verify: bool = True):
        messages = [
            {"role": "system", "content": self.system_prompt},
            {"role": "user", "content": question},
        ]
        
        resp = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
        )
        raw = resp.choices[0].message.content
        reasoning, answer = parse_cot(raw)
        
        if verify:
            messages.append({"role": "assistant", "content": raw})
            messages.append({"role": "user", "content": (
                "Review your reasoning and answer for errors. "
                "Say VERIFIED if correct, otherwise give the correction."
            )})
            v_resp = self.client.chat.completions.create(
                model=self.model,
                messages=messages,
            )
            verification = v_resp.choices[0].message.content
            return reasoning, answer, verification
        
        return reasoning, answer, None

agent = CoTAgent(client)
r, a, v = agent.ask(
    "Roger has 5 tennis balls. He buys 2 more cans of tennis balls. "
    "Each can has 3 balls. How many does he have now?"
)

print("Reasoning:\n", r)
print("\nAnswer:\n", a)
print("\nVerification:\n", v)

Run it

Save the complete script as cot_agent.py, export your key, and run it.

export OXLO_API_KEY="your-key-here"
python cot_agent.py

When I run this against the bat-and-ball problem, the agent outputs something like the following. Notice how the reasoning trace catches the intuitive but wrong answer of $10 and corrects it to $5.

=== REASONING ===
The total cost is $110. The bat costs $100 more than the ball.
If the ball cost $10, the bat would cost $110, and the total would be $120.
That is too high. Let the ball cost x. Then the bat costs x + 100.
x + (x + 100) = 110
2x + 100 = 110
2x = 10
x = 5
So the ball costs $5.

=== ANSWER ===
The ball costs $5.

=== VERIFICATION ===
VERIFIED. The algebra checks out and the total is $110.

Wrap-up and next steps

You now have a working chain-of-thought agent that separates reasoning from answers and can self-verify. Two concrete next steps: wire the reasoning trace into a structured logging pipeline so you can audit failures, or swap in kimi-k2.6 or deepseek-r1-671b on Oxlo.ai for harder reasoning benchmarks without worrying about token costs on long context windows. See https://oxlo.ai/pricing for plan details.

Top comments (0)