목차
- Claude Managed Agents 핵심 개념과 타입 설계 기준
- Agent 생성 스키마의 TypeScript 타입 정의
- 퀵스타트 워크플로와 단계별 타입 매핑
- SSE 스트리밍 이벤트의 판별 유니온 타입
- 커스텀 도구 호출·응답 TypeScript 타입 패턴
- TypeScript 타입 정의와 Python SDK 비교
- MCP 서버 연동 타입 확장
- 타입 안전한 에이전트 아키텍처 조합 전략
title: "Claude Managed Agents TypeScript 타입 정의: 도구 호출 컴파일 타임 안전성 확보" slug: "claude-managed-agents-typescript-type-definition" meta_description: "Claude Managed Agents API의 도구 호출 구조를 TypeScript 타입으로 감싸 컴파일 타임 안전성을 확보하는 설계 패턴을 정리한다."
Anthropic의 Managed Agents API는 9개 리소스 그룹, 최대 50개 도구, 분당 60회 생성 호출이라는 수치로 규모를 드러낸다. TypeScript AI Function Calling 타입 정의 없이 이 스키마를 다루면 런타임 에러가 배포 후에야 드러나는 경우가 빈번하다. agent_toolset_20260401이라는 도구 타입 문자열 하나가 오타 나도 컴파일 단계에서 잡히지 않는 셈이다. 이 글은 Claude Managed Agents의 도구 호출 구조를 TypeScript 타입으로 감싸 컴파일 타임 안전성을 확보하는 설계 패턴을 정리한다.
Claude Managed Agents 핵심 개념과 타입 설계 기준
Claude Managed Agents는 사전 구축된 설정 가능한 에이전트 하니스로, 관리형 인프라에서 실행되는 구조다. 자체 에이전트 루프·도구 실행·런타임을 직접 구축할 필요 없이, Claude가 파일 읽기/쓰기, 셸 명령 실행, 웹 검색, 코드 실행을 수행할 수 있는 완전 관리형 환경을 제공한다. Managed Agents 개요 문서에서 이 아키텍처의 전체 그림을 확인할 수 있다.
4가지 핵심 개념이 TypeScript AI Function Calling 타입 정의의 기반이 된다:
| 개념 | 역할 | 타입 설계 포인트 |
|---|---|---|
| Agent | 모델·시스템 프롬프트·도구·MCP 서버·스킬 설정 | 제네릭 도구 배열 타입 필요 |
| Environment | 컨테이너 템플릿 | 네트워킹 설정 유니온 타입 |
| Session | 실행 중인 에이전트 인스턴스 | 상태 머신 타입 |
| Events | 애플리케이션과 에이전트 간 메시지 | 판별 유니온(discriminated union) |
현재 모든 API 계정에서 기본적으로 Managed Agents 접근이 가능하지만, outcomes(결과 정의), multiagent(멀티에이전트), memory(메모리) 기능은 research preview 상태로 별도 액세스 요청이 필요하다. 공식 문서에도 이 세 기능의 상세 설명은 미제공 상태다.
Agent 생성 스키마의 TypeScript 타입 정의
Managed Agents API에서 Agent 생성 시 model(필수), system, tools(최대 50개), skills(최대 64개), mcp_servers(최대 20개)를 설정한다. Agent는 archive만 가능하고 delete는 불가하며, 버전 관리가 적용되는 구조다. Create 엔드포인트는 분당 60회, 읽기 엔드포인트는 분당 600회로 속도 제한이 걸려 있다.
실제 API 요청 본문 구조는 다음과 같다:
{
"name": "string (required, 1-256 chars)",
"model": "claude-opus-4-7",
"system": "string (optional, up to 100,000 chars)",
"tools": [
{ "type": "agent_toolset_20260401" }
],
"mcp_servers": [
{
"type": "url",
"name": "github",
"url": "https://api.githubcopilot.com/mcp/"
}
]
}
이 JSON 구조를 TypeScript 인터페이스로 표현하면, 각 필드의 제약 조건이 타입 레벨에서 강제되는 셈이다. name 필드가 1~256자라는 제한은 런타임 검증으로 보완하되, model 필드의 리터럴 타입은 컴파일 단계에서 잘못된 모델명 사용을 차단하는 역할을 한다.
type ClaudeModel = "claude-opus-4-7" | "claude-sonnet-4-5" | "claude-haiku-4-5";
type BuiltinToolType = "agent_toolset_20260401";
interface AgentToolConfig {
type: BuiltinToolType;
}
interface McpServerUrl {
type: "url";
name: string;
url: string;
}
interface CreateAgentRequest {
name: string; // 1–256자
model: ClaudeModel;
system?: string; // 최대 100,000자
tools?: AgentToolConfig[];
mcp_servers?: McpServerUrl[];
}
TypeScript AI Function Calling 타입 정의에서 도구 배열이 핵심인데, tools 필드가 최대 50개까지 허용되므로 배열 길이 제한은 런타임 가드로 처리하는 편이 현실적이다. 타입 수준에서는 각 도구 항목의 type 필드를 유니온으로 좁히는 데 집중해야 한다.
`mcp_servers` 배열은 최대 20개로 제한되며, 각 서버의 `type`이 `”url”`로 고정된다. 이 필드를 리터럴 타입으로 고정하면 향후 `”local”` 같은 새 타입이 추가될 때 컴파일 에러로 감지할 수 있게 된다.
Managed Agents 퀵스타트는 Agent 생성 → Environment 생성 → Session 시작 → 이벤트 전송·스트리밍 4단계로 진행되는 흐름이다. 모든 엔드포인트에 anthropic-beta: managed-agents-2026-04-01 베타 헤더가 필요하며, SDK는 이를 자동으로 설정한다. agent_toolset_20260401 도구 타입을 지정하면 bash, 파일 조작, 웹 검색 등 전체 빌트인 도구가 활성화된다.
Python SDK 기준 퀵스타트 코드:
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"},
],
)
environment = client.beta.environments.create(
name="quickstart-env",
config={
"type": "cloud",
"networking": {"type": "unrestricted"},
},
)
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
title="Quickstart session",
)
이 3단계 호출 각각이 독립된 타입을 반환한다. agent.id가 session 생성의 인자로 전달되는 의존성 체인이 존재하므로, 제네릭을 사용해 ID 타입을 전파하는 설계가 유효하기도 하다. Environment의 config 객체는 type과 networking 두 레벨의 중첩 유니온을 갖는 점이 특징적이다.
단계별 반환 타입 의존 관계
4단계 워크플로를 타입 관점에서 보면:
createAgent→AgentResponse(id 포함)createEnvironment→EnvironmentResponse(id 포함)createSession→SessionResponse(agent.id + environment.id 필요)sendEvents→ void,streamEvents→EventStream
3단계에서 1·2단계의 ID가 필요하다는 점은 타입 시스템으로 강제할 수 있는 영역이다. 브랜드 타입(branded type)으로 AgentId와 EnvironmentId를 구분하면 두 ID를 뒤바꿔 넣는 실수가 컴파일 단계에서 잡히는 것이다.
SSE 스트리밍 이벤트의 판별 유니온 타입
Python SDK에서 SSE 스트리밍은 stream-first 패턴을 따르는 구조다. client.beta.sessions.stream()으로 스트림을 먼저 열고, 그 안에서 events.send()로 메시지를 보낸다. 처리해야 할 이벤트 타입은 agent.message, agent.custom_tool_use, session.status_idle, session.status_terminated 4가지가 핵심이다.
with client.beta.sessions.stream(
session_id=session.id,
) as stream:
client.beta.sessions.events.send(
session_id=session.id,
events=[{"type": "user.message", "content": [{"type": "text", "text": "..."}]}],
)
for event in stream:
if event.type == "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="", flush=True)
elif event.type == "agent.custom_tool_use":
print(f"\nCustom tool call: {event.tool_name}")
이벤트 타입 분기가 if event.type == 패턴으로 이루어지는데, TypeScript에서는 판별 유니온(discriminated union)으로 이 패턴을 타입 안전하게 구현할 수 있다. type 필드를 판별자로 두면 각 분기 내부에서 해당 이벤트의 고유 필드(content, tool_name 등)에 자동 접근이 가능해진다.
이벤트 타입별 페이로드 차이
| 이벤트 타입 | 고유 필드 | 용도 |
|---|---|---|
agent.message | content: ContentBlock[] | 모델 응답 텍스트 |
agent.custom_tool_use | tool_name, custom_tool_use_id | 커스텀 도구 호출 요청 |
session.status_idle | — | 응답 완료 신호 |
session.status_terminated | — | 세션 종료 |
user.message | content: ContentBlock[] | 사용자 입력 |
user.custom_tool_result | custom_tool_use_id | 도구 결과 반환 |
커스텀 도구 결과는 `user.custom_tool_result` 이벤트로 `custom_tool_use_id`를 포함하여 반환해야 한다. 이 ID를 누락하면 에이전트가 어떤 도구 호출에 대한 응답인지 매칭하지 못해 무한 대기 상태에 빠지는 경우가 있다. 타입 시스템에서 이 필드를 required로 강제하는 것이 핵심이다.
커스텀 도구 호출·응답 TypeScript 타입 패턴
TypeScript AI Function Calling 타입 정의의 가장 까다로운 부분이 커스텀 도구다. agent.custom_tool_use 이벤트가 발생하면 외부 시스템을 호출하고, 그 결과를 user.custom_tool_result로 돌려보내야 하는 양방향 흐름이기 때문이다.
지원 도구로 Bash, File operations(read/write/edit/glob/grep), Web search and fetch, MCP servers가 포함되며, 이들은 빌트인으로 agent_toolset_20260401 하나에 모두 묶여 있다. 커스텀 도구는 이와 별개로 개발자가 직접 정의하는 영역이다.
타입 설계 시 고려할 점:
- 요청-응답 쌍 매칭 —
custom_tool_use_id로 연결되므로, 제네릭으로 도구 이름과 파라미터·결과 타입을 한 번에 묶는 방식이 효과적이다 - 도구 파라미터 JSON Schema 매핑 — API가 JSON Schema로 파라미터를 정의하므로,
zod나io-ts같은 런타임 스키마 라이브러리와 타입 추론을 결합하는 접근이 현실적인 셈이다 - 에러 응답 타입 — 도구 실행 실패 시에도 결과를 반환해야 하므로
Result<T, E>패턴 적용이 자연스럽다
빌트인 도구 vs 커스텀 도구 타입 분리
tools/
├── builtin/
│ └── agent_toolset_20260401 ← 리터럴 타입 1개로 충분
└── custom/
├── weather_lookup ← 개별 파라미터·결과 타입 필요
└── database_query ← 개별 파라미터·결과 타입 필요
빌트인 도구는 { type: "agent_toolset_20260401" } 하나로 활성화되기에 타입이 단순하다. 반면 커스텀 도구는 각각의 입출력 스키마가 다르므로, 제네릭 매핑 타입으로 도구 이름을 키, 파라미터·결과 쌍을 값으로 두는 레지스트리 패턴이 확장성 면에서 유리한 것이다.
TypeScript 타입 정의와 Python SDK 비교
Managed Agents Python SDK 가이드를 보면, Python에서는 딕셔너리 기반으로 이벤트를 처리한다. event.type == "agent.custom_tool_use" 같은 문자열 비교가 런타임에 이루어지므로 오타가 있어도 실행 전까지 모르는 구조다.
| 비교 항목 | Python SDK | TypeScript 타입 설계 |
|---|---|---|
| 도구 타입 식별 | 문자열 비교 (런타임) | 리터럴 유니온 (컴파일) |
| 이벤트 분기 | if/elif 체인 | switch + 판별 유니온 (자동 좁힘) |
| ID 혼동 방지 | 없음 (모두 string) | 브랜드 타입으로 분리 가능 |
| 도구 파라미터 검증 | 런타임 dict 접근 | 제네릭 추론 + JSON Schema 연동 |
| 자동 완성 | IDE 지원 제한적 | 전체 필드 자동 완성 |
| 리팩토링 안전성 | grep 의존 | 컴파일러가 참조 추적 |
TypeScript AI Function Calling 타입 정의의 핵심 가치가 이 표에 드러난다. Python에서 event.tool_name을 오타 내면 AttributeError가 프로덕션에서 터지지만, TypeScript에서는 빌드 자체가 실패하기 때문이다.
모든 엔드포인트에 `anthropic-beta: managed-agents-2026-04-01` 헤더가 필요하지만, SDK가 자동으로 설정해주므로 타입 정의에서 헤더를 직접 다룰 필요는 없다. 클라이언트 인스턴스 생성 시점에 한 번만 설정되는 것이다.
MCP 서버 연동 타입 확장
Managed Agents API에서 MCP 서버는 최대 20개까지 연결할 수 있으며, 각 서버 설정은 type, name, url 3개 필드로 구성되는 구조다. 현재 type은 "url"만 지원되지만, 향후 로컬 프로세스 기반 MCP가 추가될 가능성을 고려하면 타입을 확장 가능하게 설계해두는 것이 합리적이다.
MCP 서버 타입 구조:
┌────────────────────────────┐
│ McpServerConfig │
├────────────────────────────┤
│ type: "url" │ ← 현재 유일한 리터럴
│ name: string (1-256 chars) │
│ url: string (valid URL) │
└────────────────────────────┘
Agent 생성 시 tools와 mcp_servers가 동시에 지정되면, 빌트인 도구 + MCP 서버 제공 도구가 합쳐져 에이전트가 사용할 수 있는 전체 도구 세트를 구성하게 된다. 타입 레벨에서 이 두 배열을 합산해 50개 제한을 체크하는 것은 불가능하므로, 런타임 검증 레이어를 별도로 두는 것이 현실적인 접근이다.
속도 제한과 타입 안전한 재시도
API 속도 제한(Create 분당 60회, 읽기 분당 600회)을 타입으로 표현할 수는 없지만, 재시도 로직의 설정값을 타입으로 구조화하면 잘못된 재시도 간격이나 최대 횟수 설정을 방지하는 것이 가능해진다.
interface RateLimitConfig {
createRpm: 60; // Agent 생성 분당 한도 (고정)
readRpm: 600; // 읽기 분당 한도 (고정)
}
interface RetryConfig {
maxAttempts: number;
baseDelayMs: number;
maxDelayMs: number;
jitter: boolean;
}
type RateLimitedRequest<T> = {
execute: () => Promise<T>;
retry: RetryConfig;
};
RateLimitConfig의 두 필드를 숫자 리터럴(60, 600)로 고정하면 잘못된 한도를 코드에 하드코딩하는 실수가 컴파일 단계에서 차단된다. 에러 핸들링·재시도 패턴에 대한 실전 예제는 공식 문서에도 상세히 다루어지지 않은 상태다.
세션 시간 관리와 토큰 절약에 대한 공식 가이드는 현재 부재한 상태다. 세션을 열어두면 과금이 지속되므로, `session.status_idle` 이벤트 수신 후 일정 시간 내 응답이 없으면 세션을 종료하는 타임아웃 로직을 타입 안전하게 구성해두는 것이 비용 관리의 핵심이 된다.
각 단계에서 정의한 타입들을 조합하면 전체 워크플로가 하나의 타입 체인으로 연결된다. Agent 생성부터 이벤트 스트리밍까지, 각 단계의 출력 타입이 다음 단계의 입력 타입과 정확히 맞물리는 것이 목표인 셈이다.
Managed Agents API는 Agents, Sessions, Events, Resources, Environments, Vaults, Credentials, Files, Skills 9개 리소스 그룹으로 구성되므로, 타입 파일을 리소스 그룹별로 분리하는 것이 유지보수성 측면에서 유리한 편이다.
types/
├── agent.ts ← Agent, Tool, McpServer 타입
├── environment.ts ← Environment, NetworkConfig 타입
├── session.ts ← Session, SessionStatus 타입
├── events.ts ← Event 판별 유니온, ContentBlock 타입
├── custom-tools.ts ← 커스텀 도구 레지스트리 타입
└── index.ts ← 통합 export
이 구조에서 events.ts가 가장 복잡도가 높다. 6종 이상의 이벤트 타입, 각 이벤트별 고유 페이로드, ContentBlock의 하위 유니온까지 포함되기 때문이다. 반면 environment.ts는 현재 "cloud" 타입과 "unrestricted" 네트워킹만 존재해 가장 단순하다.
TypeScript AI Function Calling 타입 정의를 프로젝트에 적용할 때 고려할 트레이드오프가 있다. 타입을 촘촘하게 정의할수록 컴파일 안전성은 높아지지만, API 베타 단계에서 스키마가 변경되면 타입 수정 범위가 넓어진다는 점이다. 현재 베타 헤더 managed-agents-2026-04-01이 GA로 전환되면 도구 타입 문자열 자체가 바뀔 가능성도 배제할 수 없다.
실용적 접근은 핵심 판별자(type 필드)만 리터럴로 좁히고, 나머지 필드는 인터페이스로 느슨하게 두되 점진적으로 강화하는 방식이다. Agent 생성과 이벤트 스트리밍의 타입 안전성이 확보되면, 다음 단계로 MCP 서버 프로토콜의 타입 정의나 멀티에이전트 오케스트레이션 패턴을 고민해볼 만하다. Claude MCP 서버 연동의 타입 설계, AI 에이전트 자동화 워크플로의 상태 관리, Anthropic 에이전트 SDK의 제네릭 활용까지 확장하면 프로덕션 수준의 TypeScript AI Function Calling 타입 정의 체계가 완성되는 것이다.
관련 글
- TypeScript Claude API 멀티턴 대화 타입 4계층 완전 정리 — Managed Agents 세션 구현 가이드 – Claude Managed Agents API의 Agent·Environment·Session·Events 4개 핵심 타입으로 멀티턴 대화…
- TypeScript Zod transform pipe 완벽 가이드 — API 응답 변환 7가지 실전 패턴 – Zod의 .transform()과 .pipe()를 조합하면 API 응답 데이터를 스키마 파싱 단계에서 원하는 형태로 변환할 수 있다. v4…
- TypeScript fetch API 에러 핸들링 7단계 — 재시도·타임아웃 실전 패턴 – fetch()는 HTTP 4xx/5xx에서 reject하지 않는다. TypeScript에서 네트워크 오류, 타임아웃, JSON 파싱 실패까…