TypeScript Claude API 멀티턴 대화 타입 4계층 완전 정리 — Managed Agents 세션 구현 가이드

목차


title: "TypeScript Claude API 멀티턴 대화 타입 완전 정리 — Managed Agents 4계층 구조부터 과금까지" slug: "typescript-claude-api-multiturn-managed-agents" description: "Claude Managed Agents의 Agent·Environment·Session·Events 4계층 타입 구조를 TypeScript 관점에서 단계별로 정리한다. 에이전트 생성, 세션 기반 멀티턴 실행, 이벤트 스트리밍, 과금 체계, 레이트 리밋을 실전 코드와 함께 다룬다."

TypeScript Claude API 멀티턴 대화 타입 관리는 Anthropic의 Managed Agents 아키텍처 이해에서 출발한다. Claude API에서 멀티턴 대화란 단순히 메시지 배열을 주고받는 수준이 아니라, 에이전트·환경·세션·이벤트라는 4계층 타입 체계 위에서 동작하는 구조화된 대화 모델을 의미한다.

기존 Messages API 방식은 messages 배열에 role: "user"role: "assistant"를 번갈아 넣어 대화를 이어가는 구조였다. 간단하지만 대화가 길어질수록 토큰 관리, 도구 호출 상태 추적, 시스템 프롬프트 버전 관리가 복잡해지는 것이 문제다. Managed Agents는 이 전체 상태를 서버 사이드 세션으로 위임하는 접근이며, 모든 엔드포인트에 managed-agents-2026-04-01 베타 헤더가 필요하다. SDK를 사용하면 이 헤더가 자동으로 설정되므로 직접 지정할 필요는 없다.

이 글에서는 Managed Agents 아키텍처 개요를 기반으로 4가지 핵심 타입 구조부터 에이전트 생성, 세션 기반 멀티턴 실행, 이벤트 스트리밍, 과금 체계, 레이트 리밋까지 단계별로 정리한다.

Managed Agents의 4가지 핵심 타입 구조

Claude Managed Agents는 Agent, Environment, Session, Events의 4가지 핵심 개념으로 구성된다. 각 개념이 독립된 API 리소스 타입으로 존재하며, 이들의 조합으로 멀티턴 대화가 성립하는 것이다. 지원 도구로는 Bash, 파일 연산, 웹 검색/패치, MCP 서버가 있다.

Agent 타입

Agent는 모델과 시스템 프롬프트, 사용 가능한 도구를 정의하는 리소스이다. 한 번 생성하면 여러 세션에서 재사용할 수 있으므로, 대화의 “설계도” 역할을 하는 셈이다. model 필드에 claude-opus-4-7 같은 모델 식별자를 지정하고, system 필드에는 시스템 프롬프트 전체 텍스트를 설정한다. 에이전트 단위로 모델과 도구 구성이 결정되기 때문에, 용도별로 에이전트를 분리하면 관심사 분리가 자연스럽게 이루어진다.

Environment 타입

Environment는 에이전트가 실행되는 컨테이너 환경을 정의하는 리소스이다. networking 설정에 unrestricted를 지정하면 외부 네트워크 접근이 자유롭고, 제한된 설정을 적용하면 특정 도메인만 허용하는 샌드박스 형태로 운영할 수 있다. 에이전트와 환경이 독립적으로 생성되는 것이 핵심 설계 포인트인데, 같은 에이전트를 네트워크가 열린 개발 환경과 차단된 프로덕션 환경에서 각각 실행하는 시나리오가 가능해지기 때문이다.

Session 타입과 Events 타입

Session은 실제 대화가 이루어지는 실행 인스턴스이다. Agent ID와 Environment ID를 참조하여 생성하며, 하나의 세션 안에서 여러 차례의 메시지 교환이 일어나는 것이 멀티턴 대화의 본질이다. Events는 세션 내에서 주고받는 메시지 교환 단위로, user.message, agent.message, agent.tool_use, session.status_idle 등의 이벤트 타입이 SSE(Server-Sent Events) 스트림을 통해 실시간으로 전달된다.

4계층 분리의 실무적 의미
Agent와 Environment가 분리되어 있어서 동일한 코딩 어시스턴트 에이전트를 개발용 환경(unrestricted networking)과 코드 리뷰 전용 환경(제한된 networking)에서 각각 실행할 수 있다. 세션은 상태를 서버 사이드에서 관리하므로 클라이언트가 전체 대화 히스토리를 매번 전송할 필요가 없는 구조이다.
## TypeScript Claude API 멀티턴 대화 타입 — 에이전트 생성

에이전트 생성은 POST /v1/agents 엔드포인트로 수행한다. name, model, system, tools 필드를 전달하며, tools 배열에 {"type": "agent_toolset_20260401"}을 지정하면 bash 실행, 파일 읽기/쓰기, 웹 검색, 웹 페이지 패치 등 전체 내장 도구가 한 번에 활성화된다.

다음은 Managed Agents 퀵스타트 가이드에서 제공하는 에이전트 생성 코드이다.

from anthropic import Anthropic

client = Anthropic()

agent = client.beta.agents.create(
    name="Coding Assistant",
    model="claude-opus-4-7",
    system="You are a helpful coding assistant. Write clean, well-documented code.",
    tools=[
        {"type": "agent_toolset_20260401"},
    ],
)

print(f"Agent ID: {agent.id}, version: {agent.version}")

이 코드에서 주목할 부분은 tools 배열이다. agent_toolset_20260401이라는 단일 타입 식별자만 지정하면 bash, 파일 연산, 웹 검색, 웹 패치까지 모든 내장 도구가 활성화되는 구조이다. 도구를 개별적으로 나열하지 않아도 되므로 설정이 간결해지는 반면, 불필요한 도구까지 활성화될 수 있다는 트레이드오프가 존재한다. 웹 검색이 필요 없는 에이전트라면 개별 도구만 지정하는 방식을 검토하는 편이 비용 면에서 유리하다.

agent_toolset_20260401 식별자의 버전 의미
도구 타입 식별자의 날짜 부분(20260401)은 API 버전을 나타낸다. 향후 새 버전의 도구셋이 추가되더라도 기존 식별자는 하위 호환을 유지할 것으로 예상되므로, 프로덕션 코드에서는 이 식별자를 상수로 관리하는 것이 안전하다.
에이전트 생성 응답에는 `id`와 `version` 필드가 포함된다. `id`는 이후 세션 생성 시 필수 참조값이고, `version`은 에이전트 설정이 변경될 때마다 증가하는 불변 식별자이다. 에이전트 설정을 업데이트하면 새 version이 생성되므로, 특정 버전의 설정으로 세션을 고정 실행하는 것도 가능한 구조인 셈이다.

환경 생성은 POST /v1/environments 엔드포인트로 별도 수행한다. networking 필드에 unrestricted를 지정하면 에이전트가 외부 API를 자유롭게 호출할 수 있고, 보안 요구사항이 높은 프로덕션 환경이라면 허용 도메인을 명시적으로 제한하는 설정이 적절하다.

세션 생성과 멀티턴 대화 실행

세션은 POST /v1/sessions 엔드포인트에 agent ID와 environment_id를 전달하여 생성한다. 세션이 만들어지면 그 안에서 여러 차례의 메시지 교환이 가능한 멀티턴 대화 컨텍스트가 유지되는 것이다. 기존 Messages API처럼 전체 대화 히스토리를 매번 재전송하지 않아도 서버가 세션 상태를 관리하므로, 클라이언트 측 코드가 상당히 단순해진다.

메시지 전송은 POST /v1/sessions/{id}/events에 user.message 타입 이벤트를 보내는 방식이다. 응답은 GET /v1/sessions/{id}/stream으로 SSE 스트림을 열어 수신하며, agent.message, agent.tool_use, session.status_idle 이벤트가 순차적으로 전달된다.

다음은 세션 생성부터 이벤트 스트리밍까지의 전체 흐름 코드이다.

session = client.beta.sessions.create(
    agent=agent.id,
    environment_id=environment.id,
    title="Quickstart session",
)

with client.beta.sessions.events.stream(session.id) as stream:
    client.beta.sessions.events.send(
        session.id,
        events=[{
            "type": "user.message",
            "content": [{"type": "text", "text": "Create a Python script..."}],
        }],
    )
    for event in stream:
        match event.type:
            case "agent.message":
                for block in event.content:
                    print(block.text, end="")
            case "session.status_idle":
                break

이 코드의 핵심은 match event.type 패턴 매칭이다. 이벤트 타입 문자열에 따라 분기 처리하는 구조로, TypeScript의 discriminated union 패턴과 동일한 개념이다. event.type"agent.message"일 때만 event.content 블록을 순회하고, "session.status_idle"이면 루프를 종료하는 식이다.

멀티턴 대화를 이어가려면 session.status_idle 이벤트를 수신한 뒤 같은 세션에 새로운 user.message를 보내면 된다. 세션 상태가 서버에 유지되므로 이전 대화 맥락이 자동으로 이어지는 것이다. 클라이언트가 메시지 히스토리 배열을 직접 관리할 필요가 사라지는 셈이다.

스트림 연결 순서 주의
코드에서 `stream`을 먼저 열고 나서 `send`로 메시지를 보내는 순서를 반드시 지켜야 한다. 순서가 뒤바뀌면 에이전트의 응답 이벤트를 놓칠 수 있다. SSE 스트림은 연결 시점 이후의 이벤트만 수신하기 때문이다.
## 이벤트 타입 시스템과 분기 처리 패턴

멀티턴 대화에서 타입 안전성이 가장 중요한 지점은 이벤트 타입별 분기 처리이다. Claude Managed Agents의 이벤트는 4가지 타입으로 구분되며, 전송 방향과 처리 주체가 각각 다르다.

이벤트 타입방향설명처리 방법
user.message클라이언트 → 서버사용자 메시지 전송send 엔드포인트로 전송
agent.message서버 → 클라이언트에이전트 텍스트 응답content 블록 배열 순회
agent.tool_use서버 → 클라이언트내장 도구 호출 실행서버 사이드 자동 처리
session.status_idle서버 → 클라이언트턴 처리 완료 신호루프 종료 또는 다음 턴 시작

이벤트의 content 필드는 블록 배열로 구성된다. user.message에서 content는 [{"type": "text", "text": "..."}] 형태이고, agent.message에서도 동일한 블록 구조를 따르는 것이다. 이 일관된 블록 타입 구조 덕분에 클라이언트 측 파싱 로직을 단일화할 수 있다.

session.status_idle 이벤트의 역할은 한 턴의 종료 지점을 명확히 알리는 것이다. 에이전트가 도구를 여러 번 호출하고 최종 응답까지 마친 후에야 이 이벤트가 발생한다. 멀티턴 대화 루프에서 이 이벤트를 턴 경계로 사용하면, 에이전트가 아직 처리 중인데 다음 메시지를 보내는 실수를 방지할 수 있게 되는 것이다.

도구 호출 이벤트의 서버 사이드 처리

agent.tool_use 이벤트 처리 방식이 기존 Messages API와 Managed Agents에서 근본적으로 다르다. 기존 Messages API에서는 tool_use 응답을 받으면 클라이언트가 직접 도구를 실행하고 tool_result를 다시 보내는 왕복 루프가 필요했다. 이 루프가 멀티턴 대화를 복잡하게 만드는 주요 원인이었다.

Managed Agents에서는 도구 실행이 서버 사이드 컨테이너(Environment)에서 자동으로 이루어진다. bash 명령 실행, 파일 읽기/쓰기, 웹 검색 결과 수집까지 전부 서버에서 처리한 뒤 결과를 이벤트 스트림으로 전달하는 구조이다. 클라이언트는 도구 실행 결과를 모니터링만 하면 되므로, 멀티턴 대화 로직이 크게 단순화되는 편이다.

이 차이는 TypeScript 타입 설계에도 영향을 준다. Messages API 기반이라면 ToolUseRequest → ToolResult → AssistantMessage 순환 타입이 필요하지만, Managed Agents 기반이라면 이벤트 스트림의 단방향 수신 타입만 정의하면 되기 때문이다.

MCP 서버 연동 현황
Managed Agents의 지원 도구 목록에 MCP 서버가 포함되어 있다. 다만 MCP 서버 연동의 상세 설정 예제는 공식 문서에 충분히 다루어지지 않은 상태이므로, bash·파일·웹 검색 등 기본 내장 도구부터 활용하는 것이 현실적이다.
## Claude API 멀티턴 대화 타입의 과금 체계

Managed Agents의 과금은 세션 런타임 비용과 토큰 비용, 두 축으로 구성된다. 멀티턴 대화를 설계할 때 비용 구조를 이해하지 않으면 예상치 못한 청구가 발생할 수 있으므로, 타입 구조만큼이나 과금 체계가 중요한 고려 대상이 되는 것이다.

세션 런타임 과금

세션 런타임은 $0.08/session-hour로 과금된다. running 상태인 시간만 밀리초 단위로 정밀 측정하며, idle, rescheduling, terminated 상태의 시간은 과금 대상이 아니다. 멀티턴 대화에서 사용자 입력을 기다리는 idle 구간이 과금되지 않는다는 점은 비용 관리에 유리한 구조이다. 다만 에이전트가 도구를 실행하는 동안은 running 상태이므로, 복잡한 도구 체인을 실행하는 에이전트일수록 런타임 비용이 증가하기도 한다.

토큰 과금과 추가 비용

토큰은 표준 모델 요금이 적용된다. 멀티턴 대화가 길어질수록 컨텍스트 윈도우 내 누적 토큰이 증가하므로, 세션당 턴 수를 적절히 제한하는 설계가 비용 효율적이다.

과금 항목단가과금 조건
세션 런타임$0.08/시간running 상태만 밀리초 단위 측정
Opus 4.7 입력 토큰$5/MTok표준 모델 요금 적용
Opus 4.7 출력 토큰$25/MTok표준 모델 요금 적용
웹 검색 도구$10/1,000회검색 호출 시에만 발생
Batch API 할인 미적용
Batch API 할인, Fast mode, Data residency 배수는 Managed Agents에 적용되지 않는다. 대량 처리 시나리오에서 Messages API의 Batch 할인을 받다가 Managed Agents로 전환하면 비용이 증가할 수 있으므로 사전 산정이 필수이다.
### 비용 최적화 패턴

멀티턴 대화의 비용을 최적화하려면 세 가지 패턴을 고려할 필요가 있다.

첫째, 세션 재사용이다. 같은 맥락의 대화라면 새 세션을 만들지 않고 기존 세션에 메시지를 추가하는 방식이 토큰 효율적이다. idle 상태의 세션을 유지하는 데 런타임 비용이 들지 않으므로, 세션을 열어두고 필요할 때 다음 턴을 실행하는 패턴이 가능한 것이다.

둘째, 모델 선택의 분리이다. 모든 멀티턴 대화에 Opus 4.7을 사용할 필요는 없다. 단순 질의응답 세션은 경량 모델로 에이전트를 구성하고, 복잡한 코드 생성 세션에만 상위 모델을 적용하는 전략이 토큰 비용을 낮춘다. 에이전트와 세션이 분리된 구조이므로, 모델별 에이전트를 미리 생성해두고 용도에 따라 다른 에이전트로 세션을 생성하면 된다.

셋째, 웹 검색 도구의 선택적 활성화이다. 1,000회당 $10 추가 과금이 발생하므로, 웹 검색이 불필요한 에이전트에서는 agent_toolset_20260401 전체 활성화 대신 필요한 도구만 개별 지정하는 방식이 비용 절감에 기여하는 편이다.

레이트 리밋과 운영 제약 사항

Managed Agents 엔드포인트의 레이트 리밋은 조직(Organization) 단위로 적용된다. 엔드포인트 유형에 따라 제한이 상이하므로 멀티턴 대화 시스템 설계 시 이 수치를 미리 파악해야 한다.

엔드포인트 유형제한대상 API
생성(create)60 req/분agents, sessions, environments 생성
읽기(retrieve/list/stream)600 req/분retrieve, list, stream 조회

생성 엔드포인트가 분당 60요청으로 제한되어 있으므로, 동시에 대량의 세션을 생성하는 시나리오에서는 병목이 될 수 있다. 반면 읽기 엔드포인트는 분당 600요청이라 여러 세션의 이벤트 스트림을 동시에 구독하는 데는 비교적 여유가 있는 것이다.

실무적으로 중요한 패턴은 에이전트 재사용이다. 에이전트를 한 번 생성해두고 여러 세션에서 참조하면 생성 엔드포인트 호출 횟수를 크게 줄일 수 있다. 에이전트 ID를 환경 변수나 설정 파일에 저장해두고, 세션 생성 시에만 새 요청을 보내면 분당 60 요청 제한 안에서 운용할 수 있다.

Research Preview 단계 기능

outcomes, multiagent, memory 기능은 현재 research preview 단계로 별도 접근 신청이 필요하다. 이 기능들의 세부 API 스펙은 공식 문서에도 명시되어 있지 않다. 프로덕션 설계에서 이 기능에 의존하는 것은 시기상조인 셈이다.

멀티에이전트 기능이 정식 출시되면 여러 에이전트가 하나의 세션 안에서 협업하는 구조가 가능해질 전망이다. 메모리 기능은 세션 간 컨텍스트를 영속적으로 유지하는 역할을 할 것으로 예상되지만, 구체적인 API 형태는 현재 확인할 수 없다.

TypeScript 프로젝트에서 멀티턴 대화 타입 활용 전략

TypeScript Claude API 멀티턴 대화 타입을 실제 프로젝트에 적용할 때 가장 중요한 것은 이벤트 타입의 discriminated union 패턴이다. 앞서 살펴본 Python 코드의 match event.type 구문은 TypeScript에서 switch 문과 타입 가드로 동일하게 구현할 수 있는 구조이다.

Anthropic SDK는 Python과 TypeScript(@anthropic-ai/sdk) 두 언어로 제공된다. TypeScript SDK를 사용하면 managed-agents-2026-04-01 베타 헤더가 자동 설정되며, 이벤트 타입에 대한 타입 정의도 SDK 패키지에 포함되어 있다.

멀티턴 대화 시스템에서 타입 안전성이 특히 중요한 지점은 세 가지로 정리할 수 있다.

첫째, 이벤트 타입 분기이다. user.message, agent.message, agent.tool_use, session.status_idle 각각에 대해 정확한 페이로드 타입을 보장해야 런타임 에러를 방지할 수 있게 되는 것이다. event.type 필드가 리터럴 타입으로 좁혀지면 해당 이벤트의 content 구조까지 자동으로 추론되는 것이 discriminated union의 핵심이다.

둘째, content 블록 타입이다. 이벤트의 content 필드가 {"type": "text", "text": "..."} 형태의 블록 배열이므로, 블록 타입에 따른 분기 처리가 필요하다. 텍스트 블록과 도구 사용 블록의 구조가 다르기 때문에, 블록 레벨에서도 discriminated union 패턴을 적용해야 타입 안전성을 확보할 수 있는 셈이다.

셋째, 에이전트·세션 간 ID 참조 체이닝이다. Agent 생성 응답의 id가 Session 생성의 필수 파라미터이고, Session의 id가 Event 전송·수신의 경로 파라미터인 구조이다. 이 체이닝을 제네릭 타입이나 브랜드 타입(branded type)으로 표현하면 잘못된 ID 참조를 컴파일 타임에 차단할 수 있다.

에이전트 생성 → 환경 생성 → 세션 생성 → 메시지 전송 → 이벤트 수신
   Agent          Env         Session      Event(send)    Event(stream)
   (id,ver)      (id,net)    (id,agent)   user.message   agent.message
                                                          agent.tool_use
                                                          session.status_idle

이 흐름에서 각 단계의 출력 타입이 다음 단계의 입력 타입에 직접 연결된다. TypeScript의 제네릭과 조건부 타입을 활용하면 이 파이프라인 전체를 타입 레벨에서 검증하는 것이 가능하기도 하다.

프로덕션 환경 적용과 에러 핸들링

Managed Agents를 프로덕션에 적용할 때 가장 먼저 부딪히는 문제는 에러 핸들링이다. 현재 공식 문서에서 에러 핸들링과 재시도 패턴에 대한 가이드가 제공되지 않는 상태이므로, 자체적으로 방어 로직을 구성해야 하는 것이다.

SSE 스트림 연결이 끊어지는 경우를 대비한 재연결 로직은 필수이다. 네트워크 불안정이나 서버 측 타임아웃으로 스트림이 중단될 수 있으므로, 지수 백오프(exponential backoff) 방식의 재연결 전략을 구현해야 한다. 재연결 후에는 세션 상태를 확인하고, 마지막으로 수신한 이벤트 이후의 데이터를 복구하는 로직도 필요한 경우가 있다.

세션 상태 관리 역시 중요한 영역이다. 세션이 running, idle, rescheduling, terminated 중 어떤 상태인지에 따라 클라이언트 동작이 달라져야 한다. terminated 상태의 세션에 메시지를 보내면 에러가 발생할 것이므로, 메시지 전송 전 세션 상태를 검증하는 가드 로직을 배치하는 것이 안전하다.

한국어 공식 가이드가 없다는 점도 실무 제약이다. 전체 문서가 영어로만 제공되므로, 팀 내 온보딩 자료를 별도로 작성하거나 API 타입 정의에 한국어 JSDoc 주석을 추가하면 팀 온보딩 비용이 줄어든다.

TypeScript Claude API 멀티턴 대화 타입 설계가 어느 정도 잡혔다면, 다음 단계는 에이전트의 도구 사용 패턴을 세밀하게 제어하는 것이다. bash나 파일 시스템을 자율적으로 사용하는 에이전트에서 보안 경계를 어떻게 설정할지가 프로덕션의 핵심 과제이며, 멀티에이전트 협업이 정식 출시되면 세션 간 메시지 라우팅과 에이전트 간 타입 계약(contract) 설계도 고려해야 할 영역이 된다.

관련 글

이 글 공유하기