iBetter Books
수정

인식-결정-행동 사이클

루프의 한 사이클을 더 잘게 쪼개면 인식(perceive), 결정(decide), 행동(act)의 세 단계로 나뉜다. 이 세 단계는 추상적인 에이전트 이론의 용어이기도 하지만, Claude 도구 사용에서는 구체적인 메시지 구조와 일대일로 대응한다. 시험은 추상 개념과 실제 API 메시지를 연결해서 묻는 경향이 있으므로, 각 단계가 어떤 블록과 어떤 역할(role)에 대응하는지를 정확히 외워 두는 것이 유리하다.

인식 단계는 모델이 현재까지의 맥락을 받아들이는 단계다. 대화 기록(messages), 사용 가능한 도구 정의(tools), 직전 사이클에서 돌아온 도구 결과(tool_result)가 모두 입력으로 들어간다. 즉 인식은 "지금 무엇이 주어져 있는가"를 모델이 읽는 과정이다. 여기서 중요한 점은 도구 결과가 다음 사이클의 인식 입력이 된다는 것이다. 애플리케이션이 만든 tool_resultuser 역할의 메시지로 붙여서 보내며, 이것이 모델에게는 새로운 관찰(observation)로 작용한다.

결정 단계는 모델이 다음에 무엇을 할지 정하는 단계다. 모델은 이 단계에서 두 갈래 중 하나를 택한다. 도구가 더 필요하다고 판단하면 응답에 tool_use 블록을 담아 어떤 도구를 어떤 입력으로 호출할지 명시한다. 도구가 더 필요 없다고 판단하면 최종 답을 텍스트로 생성한다. 최신 모델은 이 판단 과정에서 필요에 따라 사고를 확장하는데, 사고는 adaptive로 동작하므로 별도의 토큰 예산이나 온도 같은 파라미터를 지정하지 않는다. 시험에서 사고 관련 파라미터로 budget_tokens, temperature, top_p를 설정하라는 보기가 나오면 함정이다. 최신 모델에서는 이런 수동 튜닝 파라미터를 쓰지 않는다.

행동 단계는 결정의 결과를 실제 세계에 반영하는 단계다. 모델이 tool_use를 냈다면 애플리케이션이 해당 도구를 실행한다. 파일을 읽거나, API를 호출하거나, 검색을 수행한다. 행동의 산출물은 tool_result 블록으로 정리되어 다음 사이클의 인식 입력으로 되돌아간다. 이렇게 행동의 결과가 다시 인식이 되면서 사이클이 닫히고, 작업이 끝나지 않았다면 다시 인식부터 시작된다.

아래 표는 세 단계를 API 요소와 매핑한 것이다.

단계 하는 일 대응 요소 주체
인식 맥락과 직전 결과를 읽음 messages, tools, tool_result(user) 모델 입력
결정 도구 호출 또는 최종 답을 고름 tool_use 또는 text(assistant) 모델
행동 도구를 실제로 실행 execute_tool, tool_result 생성 애플리케이션

세 단계가 어떻게 하나의 닫힌 고리를 이루는지 그림으로 보면 다음과 같다. 행동의 결과가 다시 인식으로 되돌아가며, 결정 단계에서 도구가 더 필요 없다고 판단하면 고리를 빠져나와 종료한다.

%% 인식-결정-행동 사이클 flowchart TB P["인식 Perceive\nmessages · tools · tool_result(user)"] D{"결정 Decide"} A["행동 Act\nexecute_tool 실행 후 tool_result 생성"] E["종료\nstop_reason = end_turn"] P --> D D -->|"tool_use (도구 필요)"| A D -->|"최종 텍스트 (도구 불필요)"| E A -->|"결과가 새 관찰로"| P

구조화된 출력이 필요한 경우, 결정 단계에서 모델이 내는 최종 텍스트의 형식을 강제할 수 있다. 이때는 output_config.format에 JSON 스키마를 지정한다. 도구 사용과 구조화 출력은 한 요청에서 함께 쓸 수 있어서, 모델이 먼저 도구를 호출(tool_use)한 뒤 마지막에 스키마에 맞는 JSON 텍스트로 답하는 흐름도 가능하다.

# 새 파일: agent/structured_call.pyresponse = client.messages.create(    model="claude-opus-4-8",    max_tokens=1024,    messages=messages,    output_config={        "format": {            "type": "json_schema",            "schema": {                "type": "object",                "properties": {                    "summary": {"type": "string"},                    "next_steps": {"type": "array", "items": {"type": "string"}},                },                "required": ["summary", "next_steps"],                "additionalProperties": False,            },        }    },)

자주 틀리는 지점을 정리하면 이렇다. 도구 결과는 assistant가 아니라 user 역할로 되돌려 보낸다는 점, 한 사이클에서 모델이 여러 개의 tool_use 블록을 동시에 낼 수 있고 그럴 때는 각각에 대응하는 tool_result를 모두 만들어 보내야 한다는 점, 그리고 사고는 adaptive이므로 수동 파라미터로 조절하지 않는다는 점이다. 인식-결정-행동을 막연한 비유로만 외우면 이런 세부에서 실수하기 쉬우므로, 각 단계가 어떤 블록과 역할에 대응하는지로 기억하는 편이 안전하다.

정리

  • 한 사이클은 인식, 결정, 행동으로 나뉘며 각각 모델 입력(messages·tools·tool_result), 모델 출력(tool_use 또는 text), 애플리케이션 실행(execute_tool)에 대응한다.
  • 도구 결과는 user 역할의 tool_result 블록으로 되돌려 보내며, 이것이 다음 사이클의 관찰이 된다.
  • 모델이 한 번에 여러 tool_use를 낼 수 있으므로 각 호출에 대응하는 tool_result를 모두 회신해야 한다.
  • 사고는 adaptive로 동작하며 budget_tokens, temperature, top_p 같은 수동 파라미터를 쓰지 않는다. 보기에 이런 파라미터가 나오면 함정이다.
  • 최종 출력 형식 강제는 output_config.format에 JSON 스키마를 지정해 처리하고, 도구 사용과 함께 쓸 수 있다.