마이그레이션
Messages API 또는 Claude Agent SDK로 구축한 기존 에이전트를 Claude Managed Agents로 이전합니다.
Claude Managed Agents는 직접 작성한 에이전트 루프를 관리형 인프라로 대체합니다. 이 페이지에서는 Messages API로 구축한 커스텀 루프 또는 Claude Agent SDK에서 마이그레이션할 때 무엇이 달라지는지 다룹니다.
Messages API 에이전트 루프에서 마이그레이션
while 루프 안에서 messages.create를 호출하고, 도구 호출을 직접 실행하며, 결과를 대화 기록에 추가하는 방식으로 에이전트를 구축했다면, 그 코드의 대부분은 사라집니다.
더 이상 관리하지 않아도 되는 것
| 이전 | 이후 |
|---|---|
| 대화 기록 배열을 유지하고 매 턴마다 다시 전달합니다. | 세션이 서버 측에 기록을 저장합니다. 이벤트를 보내고, 이벤트를 받습니다. |
tool_use 콘텐츠 블록을 순회하며 각 도구를 실행하고 tool_result 메시지로 다시 루프를 돕니다. | 사전 구축된 도구는 샌드박스 안에서 자동으로 실행됩니다. agent.custom_tool_use 이벤트를 통해 커스텀 도구만 처리하면 됩니다. |
| 에이전트가 생성한 코드를 실행하기 위한 샌드박스를 직접 프로비저닝합니다. | 세션 샌드박스가 코드 실행, 파일 작업, bash를 처리합니다. |
| 루프가 언제 끝나는지 직접 결정합니다. | 에이전트가 더 이상 할 일이 없으면 세션이 session.status_idle을 내보냅니다. |
코드 비교
이전 (Messages API 루프, 단순화):
messages = [{"role": "user", "content": task}]
while True:
response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=messages,
tools=tools,
)
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason == "end_turn":
break
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
messages.append(
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
}
],
}
)이후 (Claude Managed Agents):
agent = client.beta.agents.create(
name="Task Runner",
model="claude-opus-5",
tools=[{"type": "agent_toolset_20260401"}],
)
session = client.beta.sessions.create(
agent={"type": "agent", "id": agent.id, "version": agent.version},
environment_id=environment.id,
)
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": task}]}],
)
for event in stream:
if event.type == "session.status_idle":
break여전히 제어할 수 있는 것
- 시스템 프롬프트와 모델: 동일한 필드이며, 이제 에이전트 정의에 위치합니다.
- 커스텀 도구: 여전히 JSON Schema로 선언합니다. 실행은 인라인 처리에서
agent.custom_tool_use이벤트에 응답하는 방식으로 옮겨집니다. 세션 이벤트 스트림을 참조하세요. - 웹 검색 및 웹 가져오기 설정: 동일한
allowed_domains,blocked_domains,max_content_tokens,user_location필드이며, 이제 매 요청마다 설정하는 대신 에이전트 툴셋의configs배열에 있는web_search및web_fetch항목에 한 번만 설정합니다.max_uses,citations,cache_control필드는 사용할 수 없습니다. 웹 검색 및 웹 가져오기 도메인 제한을 참조하세요. - 컨텍스트: 시스템 프롬프트, 파일 리소스 또는 스킬을 통해 여전히 컨텍스트를 주입할 수 있습니다.
Claude Agent SDK에서 마이그레이션
Claude Agent SDK로 구축했다면, 이미 에이전트, 도구, 세션이라는 개념으로 작업하고 있는 것입니다. 차이점은 실행 위치입니다. SDK는 여러분이 운영하는 프로세스에서 실행되는 반면, Managed Agents는 Anthropic의 인프라에서 실행됩니다. 마이그레이션의 대부분은 SDK 구성 객체를 API 측의 대응 항목에 매핑하는 작업입니다.
달라지는 것
| Agent SDK | Managed Agents |
|---|---|
실행마다 생성하는 ClaudeAgentOptions(...) | client.beta.agents.create(...)를 한 번 호출합니다. Agent는 서버 측에 영속화되고 버전 관리됩니다. 에이전트 설정을 참조하세요. |
async with ClaudeSDKClient(...) 또는 query(...) | client.beta.sessions.create(...)를 호출한 다음 이벤트를 보내고 받습니다. |
SDK가 자동으로 디스패치하는 @tool 데코레이터 함수 | Agent에 {"type": "custom", ...}으로 선언합니다. 클라이언트가 agent.custom_tool_use 이벤트를 처리하고 user.custom_tool_result로 응답합니다. 도구를 참조하세요. |
| 내장 도구가 여러분의 프로세스에서 여러분의 파일 시스템을 대상으로 실행됨 | {"type": "agent_toolset_20260401"}이 동일한 도구를 세션 샌드박스 안에서 /workspace를 대상으로 실행합니다. |
cwd, add_dirs가 로컬 경로를 가리킴 | 파일을 세션 리소스로 업로드하거나 마운트합니다. |
system_prompt 및 CLAUDE.md 계층 구조 | Agent의 단일 system 문자열입니다. 에이전트를 변경하는 각 업데이트는 새로운 서버 측 버전을 생성합니다. 세션을 특정 버전에 고정하여 배포 없이 승격하거나 롤백할 수 있습니다. 에이전트 설정을 참조하세요. |
mcp_servers를 한 곳에서 구성하고 인증함 | Agent에 서버를 선언하고, Session의 Vault를 통해 자격 증명을 제공합니다. |
permission_mode, can_use_tool | 도구별 permission_policy를 사용합니다. always_ask 도구에 대해서는 user.tool_confirmation 이벤트를 보냅니다. |
코드 비교
이전 (Agent SDK):
from claude_agent_sdk import (
ClaudeAgentOptions,
ClaudeSDKClient,
create_sdk_mcp_server,
tool,
)
@tool("get_weather", "Get the current weather for a city.", {"city": str})
async def get_weather(args: dict) -> dict:
return {"content": [{"type": "text", "text": f"{args['city']}: 18°C, clear"}]}
options = ClaudeAgentOptions(
model="claude-opus-5",
system_prompt="You are a concise weather assistant.",
mcp_servers={
"weather": create_sdk_mcp_server("weather", "1.0", tools=[get_weather])
},
)
async with ClaudeSDKClient(options=options) as agent:
await agent.query("What's the weather in Tokyo?")
async for msg in agent.receive_response():
print(msg)이후 (Managed Agents):
from anthropic import Anthropic
client = Anthropic()
agent = client.beta.agents.create(
name="weather-agent",
model="claude-opus-5",
system="You are a concise weather assistant.",
tools=[
{
"type": "custom",
"name": "get_weather",
"description": "Get the current weather for a city.",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}
],
)
environment = client.beta.environments.create(
name="weather-env",
config={"type": "cloud", "networking": {"type": "unrestricted"}},
)
session = client.beta.sessions.create(
agent={"type": "agent", "id": agent.id, "version": agent.version},
environment_id=environment.id,
)
def get_weather(city: str) -> str:
return f"{city}: 18°C, clear"
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": "What's the weather in Tokyo?"}],
}
],
)
for event in stream:
if event.type == "agent.message":
print(
"".join(block.text for block in event.content if block.type == "text")
)
elif event.type == "agent.custom_tool_use":
result = get_weather(**event.input)
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.custom_tool_result",
"custom_tool_use_id": event.id,
"content": [{"type": "text", "text": result}],
}
],
)
elif (
event.type == "session.status_idle"
and event.stop_reason
and event.stop_reason.type == "end_turn"
):
breakAgent와 Environment는 한 번 생성되어 여러 세션에서 재사용됩니다. 도구 함수는 여전히 여러분의 프로세스에서 실행됩니다. 차이점은 SDK가 대신 디스패치해 주는 대신, 여러분이 agent.custom_tool_use 이벤트를 읽고 결과를 명시적으로 보낸다는 것입니다.
클라이언트로 옮겨지는 기능
Anthropic이 에이전트 루프를 실행하는 대신, SDK가 자동으로 처리하던 몇 가지가 클라이언트의 책임이 됩니다.
| SDK 기능 | Managed Agents 접근 방식 |
|---|---|
| 플랜 모드 | 먼저 계획 전용 세션을 실행한 다음, 두 번째 세션에서 계획을 실행합니다. |
| 출력 스타일, 슬래시 명령 | user.message를 보내기 전 또는 agent.message를 받은 후 클라이언트에서 적용합니다. |
PreToolUse / PostToolUse 훅 | 클라이언트는 이미 응답하기 전에 모든 agent.custom_tool_use 이벤트를 확인하므로, 로직을 그곳에 두세요. 내장 도구의 경우 permission_policy: always_ask를 사용하세요. |
max_turns | 클라이언트 측에서 턴을 셉니다. |
마이그레이션 체크리스트
- 에이전트에 필요한 네트워킹과 런타임을 갖춘 환경을 생성하세요.
- 시스템 프롬프트와 도구 선택을 에이전트 정의로 옮기세요.
- 루프를
sessions.create및sessions.events.stream으로 교체하세요. - 에이전트가 읽는 로컬 파일은 Files API를 통해 업로드하고
resources로 마운트하세요. - 커스텀 도구 핸들러는
agent.custom_tool_use이벤트에 대한 응답으로 실행을 이벤트 루프 안으로 옮기세요. - 프로덕션 트래픽을 새 흐름으로 전환하기 전에 테스트 세션으로 검증하세요.
모델 버전 간 마이그레이션
새로운 Claude 모델이 출시되면, Claude Managed Agents 통합의 마이그레이션은 일반적으로 필드 하나만 변경하면 됩니다. 에이전트 정의의 model을 업데이트하면 다음에 생성하는 세션부터 변경 사항이 적용됩니다.
ant beta:agents update --agent-id "$AGENT_ID" < agent.yamlname: Task Runner
model: claude-opus-5
system: You are a task automation agent. Complete the task you are given end to end.
tools:
- type: agent_toolset_20260401Messages API 마이그레이션 가이드에 문서화된 대부분의 모델 수준 동작 변경은 여러분 측에서 조치가 필요하지 않습니다.
- 요청 파라미터 변경(
max_tokens기본값,thinking구성)은 Claude Managed Agents 런타임이 처리합니다. 이 필드들은 에이전트 정의에 노출되지 않습니다. - 어시스턴트 메시지 프리필은 이벤트 기반 세션 모델에 존재하지 않으므로, 최신 모델에서 이 기능이 제거된 것은 아무 영향이 없습니다.
- 도구 인수 JSON 이스케이프는
agent.custom_tool_use이벤트를 받기 전에 런타임이 파싱합니다. 원시 문자열이 아닌 구조화된 데이터를 보게 됩니다.
Messages API 가이드의 동작 설명(모델이 무엇을 다르게 하는지)은 여전히 적용됩니다. 마이그레이션 단계(요청 코드를 어떻게 변경하는지)는 적용되지 않습니다.
Was this page helpful?