블로그 목록
AI

Claude 인터리브드 사고로 툴 호출 사이에 다시 생각하게 하기 — 도구 결과 받고 추론 이어가기

툴을 서너 개 붙인 Claude 에이전트를 만들다가 이상한 걸 봤다. 확장된 사고(extended thinking)를 켜두면 맨 처음엔 꼼꼼히 계획을 세우는데, 정작 툴이 결과를 돌려준 다음에는 그걸 제대로 안 보고 바로 다음 툴을 불러버리는 경우가 있었다. 검색 결과가 비어 있는데도 그 결과를 쓴다고 가정하고 다음 단계로 넘어가는 식이다.

이유는 단순했다. 기본 확장된 사고는 첫 응답에서 한 번 생각하고 끝난다. 툴 결과를 받은 뒤의 턴에서는 다시 생각하는 블록이 안 생긴다. 그래서 도구가 돌려준 값을 보고 판단을 고쳐야 하는 에이전트엔 이게 꽤 치명적이다.

interleaved thinking 베타 켜기

이걸 해결하는 게 인터리브드 사고(interleaved thinking)다. 베타 헤더 하나만 붙이면, Claude가 툴 호출 사이사이마다 thinking 블록을 끼워넣는다. 툴 결과를 받으면 "이 결과가 내가 기대한 거 맞나?"를 먼저 추론하고, 그 다음에 행동한다.

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=4096,
    thinking={"type": "enabled", "budget_tokens": 2048},
    extra_headers={
        "anthropic-beta": "interleaved-thinking-2025-05-14"
    },
    tools=[search_tool, fetch_tool],
    messages=[{"role": "user", "content": "최신 환율 찾아서 100달러 환산해줘"}],
)

차이는 응답 블록 순서에서 바로 드러난다. 베타를 안 켜면 thinking → tool_use로 끝나지만, 켜면 툴 결과를 돌려준 뒤 턴에서 thinking → tool_use 또는 thinking → text가 또 나온다. 즉 검색 → (결과 보고 다시 생각) → 계산 → (검산) → 답변 흐름이 된다.

주의: thinking 블록을 돌려줘야 한다

한 가지 꼭 지켜야 할 게 있다. 다음 턴 요청을 보낼 때 이전 턴의 thinking 블록을 assistant 메시지에 그대로 다시 넣어야 한다. 빼먹으면 Claude가 추론 맥락을 잃어서 400 에러가 나거나 사고가 끊긴다.

messages.append({"role": "assistant", "content": response.content})  # thinking 블록 포함 전체
messages.append({"role": "user", "content": tool_results})

response.content 전체를 그대로 붙이면 thinking 블록까지 자동으로 따라간다. 직접 text만 뽑아서 재구성하면 안 된다.

결론

여러 툴을 순차로 쓰고, 중간 결과에 따라 다음 행동이 달라지는 에이전트라면 인터리브드 사고가 체감 차이가 크다. 빈 검색 결과를 무시하거나 엉뚱한 툴을 부르던 게 눈에 띄게 줄었다. 반대로 툴이 하나뿐이거나 단순 추출 작업이면 토큰만 더 먹으니 굳이 켤 필요는 없다. "결과 보고 판단을 고쳐야 하는가"가 켜고 끄는 기준이다.