Claude Managed Agents와의 통신은 이벤트 기반입니다. 사용자 이벤트를 에이전트에 전송하고, 에이전트 및 세션 이벤트를 다시 수신하여 상태를 추적합니다.
모든 Managed Agents API 요청에는 managed-agents-2026-04-01 베타 헤더가 필요합니다. SDK는 베타 헤더를 자동으로 설정합니다.
이벤트는 양방향으로 흐릅니다.
user.* 이벤트는 세션을 시작하고 진행 중에 방향을 조정하며, system.message는 턴 사이에 에이전트의 시스템 프롬프트를 업데이트합니다.세션, 스팬, 에이전트, 사용자, 시스템 이벤트 유형 문자열은 {domain}.{action} 명명 규칙을 따릅니다. 스트림 전용 델타 미리보기 이벤트(event_start, event_delta)는 예외입니다. 전체 목록은 참조 문서의 이벤트 유형을 참조하세요.
모든 영속화된 이벤트에는 이벤트가 서버 측에서 기록된 시점을 나타내는 processed_at 타임스탬프가 포함됩니다. processed_at이 null이면 이벤트가 하네스에 의해 큐에 추가되었으며 이전 이벤트 처리가 완료된 후 처리됨을 의미합니다.
기본적으로 에이전트의 응답 텍스트는 버퍼링된 agent.message 이벤트로 스트림에 도달하며, 각 이벤트는 이를 생성한 모델 요청이 완료된 후에만 발생합니다. 이벤트 델타를 사용하면 모델이 아직 생성 중인 동안 해당 텍스트를 라이브 미리보기로 점진적으로 렌더링할 수 있습니다. 미리보기는 응답이 아닙니다. 미리보기는 최선의 노력으로 제공되는 표시 보조 수단이며, 버퍼링된 agent.message가 항상 권위 있는 기록입니다. 미리보기를 무시하는 클라이언트도 완전하고 정확한 스트림을 수신합니다.
미리보기는 스트림 연결별로 옵트인됩니다. GET /v1/sessions/{session_id}/events/stream에 event_deltas[] 쿼리 매개변수를 추가하고, 미리보기를 원하는 각 이벤트 유형마다 한 번씩 반복하세요. 허용되는 값은 agent.message와 agent.thinking이며, 다른 값은 400 오류를 반환합니다. 세션 수준 이벤트 스트림만 이 매개변수를 지원합니다. 세션 스레드 이벤트 스트림은 이를 거부합니다.
미리보기된 이벤트가 시작되면 스트림은 다가오는 이벤트의 유형과 id를 포함하는 event_start를 발생시킵니다:
{
"type": "event_start",
"event": {
"type": "agent.message",
"id": "sevt_01abc..."
}
}agent.message의 경우, 시작 이후 점진적 텍스트를 포함하는 event_delta 이벤트가 이어집니다. 각 델타는 event_id에서 확장하는 이벤트를, delta.index에서 확장하는 콘텐츠 블록을 지정합니다:
{
"type": "event_delta",
"event_id": "sevt_01abc...",
"delta": {
"type": "content_delta",
"index": 0,
"content": {
"type": "text",
"text": "Here is the summary"
}
}
}agent.thinking 이벤트가 미리보기될 때는 event_start만 발생합니다. event_delta 이벤트는 뒤따르지 않으며, 콘텐츠는 평소와 같이 버퍼링된 agent.thinking 이벤트로 도착합니다.
영속화된 이벤트와 달리 event_start와 event_delta는 자체 id나 processed_at이 없습니다. 이들이 포함하는 유일한 식별자는 미리보기하는 이벤트의 id입니다.
이벤트 델타는 메시지 스트리밍과 다른 와이어 형식을 사용하며, 이 차이는 의도적입니다. 미리보기된 agent.message는 단일 event_start 다음에 event_delta 이벤트만 받습니다. 콘텐츠 블록별 시작 또는 중지 이벤트가 없으며 미리보기된 이벤트 자체에 대한 중지 이벤트도 없습니다. 델타 유형은 content_block_delta가 아니라 content_delta입니다. Messages API용으로 작성된 누산기 코드는 그대로 적용되지 않습니다.
Python, TypeScript, Go SDK에는 이벤트의 id로 미리보기를 키 지정하고 index 관리를 대신 처리하는 누산기 헬퍼가 포함되어 있습니다. 수동 패턴은 모든 언어에서 작동합니다. 다른 SDK에서는 생성된 이벤트 유형에 이를 적용하세요.
수동 패턴에서는 미리보기를 임시 버퍼로, 버퍼링된 이벤트를 기록으로 취급하세요. 버퍼는 (event_id, index)로 키 지정하세요. 모델 요청별로 조정하세요. 턴은 단일 session.status_running 이벤트로 시작되며, 정상적으로 완료되는 턴에서 각 모델 요청은 순서대로 span.model_request_start, event_start, event_delta 이벤트들, 버퍼링된 agent.message, 마지막으로 span.model_request_end(스팬 이벤트 탭 참조)를 생성합니다. 각 이벤트가 도착할 때마다 처리하세요:
event_start에서 알려진 id를 기록하세요. 식별자는 항상 일치합니다. event_start.event.id, 모든 event_delta.event_id, 버퍼링된 agent.message의 id는 동일한 값입니다.event_delta에서 delta.content.text를 (event_id, delta.index) 항목에 추가하고 진행 중인 텍스트를 렌더링하세요. index에 대한 첫 번째 델타가 해당 항목을 생성합니다.agent.message가 도착하면 id로 매칭하고, 누적된 미리보기를 폐기한 다음 메시지의 콘텐츠를 대신 렌더링하세요.span.model_request_end에서 버퍼링된 이벤트로 조정되지 않은 미리보기를 모두 닫으세요. 해당 미리보기에 대한 델타는 더 이상 오지 않습니다. 턴이 오류를 발생시키거나 중단되면 버퍼링된 이벤트가 도착하지 않을 수 있지만, span.model_request_end는 여전히 도착합니다.# 이벤트 ID를 키로 하는 미리보기 스냅샷. accumulate_managed_agents_event는 각
# event_start / event_delta를 agent.message 스냅샷으로 접습니다. 버퍼링된
# agent.message가 이를 대체합니다.
previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}
# 이 연결에서 agent.message 미리보기를 옵트인합니다
with client.beta.sessions.events.stream(
session.id, event_deltas=["agent.message"]
) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Describe the repo in one sentence."}],
},
],
)
for event in stream:
match event.type:
case "event_start":
snapshot = accumulate_managed_agents_event(None, event)
if snapshot is not None:
previews[event.event.id] = snapshot
print(f"event_start {event.event.type} {event.event.id}")
case "event_delta":
preview = accumulate_managed_agents_event(previews.get(event.event_id), event)
if preview is not None:
previews[event.event_id] = preview
text = "".join(block.text for block in preview.content)
print(f"event_delta preview: {text!r}")
case "agent.message":
# 버퍼링된 이벤트가 기록입니다: 미리보기를 대체하고 닫습니다
preview = accumulate_managed_agents_event(previews.pop(event.id, None), event)
text = "".join(block.text for block in preview.content)
print(f"agent.message {event.id} {text!r}")
case "span.model_request_end":
# 더 이상 델타가 오지 않습니다. 버퍼링된 이벤트가
# 도착하지 않은 미리보기를 모두 닫습니다.
for event_id in previews:
print(f"span.model_request_end closing preview for {event_id}")
previews.clear()
case "session.status_idle":
break미리보기는 응답성에 맞춰 조정되어 있습니다. 다음 제약 조건을 고려하여 구축하세요:
agent.message는 여전히 완전하게 도착합니다. 누적된 미리보기를 최종 결과로 취급하지 마세요.agent.message도 포함됩니다. 놓친 델타를 다시 요청할 방법은 없습니다.agent.thinking: agent.thinking 미리보기는 사고 블록이 시작되었다는 신호로 event_start만 발생시키며, event_delta 이벤트는 뒤따르지 않습니다.event_start와 event_delta는 라이브 스트림에만 존재합니다. 세션의 이벤트 기록(GET /v1/sessions/{session_id}/events)에는 나타나지 않습니다.에이전트가 커스텀 도구를 호출할 때:
agent.custom_tool_use 이벤트를 발생시킵니다.stop_reason: requires_action을 포함하는 session.status_idle 이벤트와 함께 일시 중지됩니다. 차단 이벤트 ID는 stop_reason.event_ids 배열에 있습니다.user.custom_tool_result 이벤트를 전송하세요. 이벤트 ID를 custom_tool_use_id 매개변수에 결과 콘텐츠와 함께 전달하세요.running 상태로 전환됩니다.with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# 커스텀 도구 사용 이벤트를 조회하고 실행합니다
tool_event = events_by_id[event_id]
result = call_tool(tool_event.name, tool_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}],
},
],
)
case "end_turn":
break권한 정책이 도구 실행 전에 확인을 요구할 때:
agent.tool_use 또는 agent.mcp_tool_use 이벤트를 발생시킵니다.stop_reason: requires_action을 포함하는 session.status_idle 이벤트와 함께 일시 중지됩니다. 차단 이벤트 ID는 stop_reason.event_ids 배열에 있습니다.user.tool_confirmation 이벤트를 전송하고, 이벤트 ID를 tool_use_id 매개변수에 전달하세요. result를 "allow" 또는 "deny"로 설정하세요. 거부 이유를 설명하려면 deny_message를 사용하세요.running 상태로 전환됩니다.with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# 대기 중인 도구 호출을 승인합니다
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.tool_confirmation",
"tool_use_id": event_id,
"result": "allow",
},
],
)
case "end_turn":
break세션은 상호작용 간에 유지됩니다. 세션이 명시적으로 삭제되지 않는 한 대화 기록은 보존됩니다. 세션이 유휴 상태가 되면 샌드박스가 체크포인트되어 파일 시스템, 설치된 패키지, 에이전트가 생성한 모든 파일을 포함한 전체 샌드박스 상태가 보존됩니다. 이를 통해 비활성 상태에서 깔끔하게 재개할 수 있습니다.
세션 기록은 삭제될 때까지 유지되지만, 체크포인트는 세션의 마지막 활동 이후 30일 동안만 보존됩니다. 워크플로에서 전체 샌드박스 상태(파일, 설치된 도구 등)가 30일 이상 유지되어야 하는 경우, 체크포인트가 만료되기 전에 주기적으로 user.message 이벤트를 전송하여 비활성 타이머를 재설정하세요.
세션을 재개하려면 평소와 같이 user.message 이벤트를 전송하세요:
# 프로덕션에서는 재개하려는 세션의 저장된 ID를 전달하세요.
ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
events:
- type: user.message
content:
- type: text
text: Now run the tests against the changes you made earlier.
YAMLsystem.message는 현재 Claude Opus 4.8에서만 지원됩니다. 에이전트에 구성된 모델 중 대화 중 시스템 주입을 지원하지 않는 모델이 있으면 이벤트는 model_does_not_support_mid_conversation_system 유효성 검사 오류와 함께 거부됩니다.
턴 사이에 에이전트의 시스템 프롬프트를 업데이트하려면 system.message 이벤트를 전송하세요. 에이전트 정의의 system 필드(세션 생성 시 고정됨)와 달리, system.message를 사용하면 세션이 진행되는 동안 시스템 프롬프트를 변경할 수 있습니다. 에이전트가 세션 중간에 업데이트된 시스템 수준 지침이 필요할 때 사용하세요. 예를 들어 다른 페르소나, 수정된 제약 조건, 또는 런타임에 가져온 컨텍스트로 앞으로의 모델 동작을 형성해야 하는 경우입니다.
ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
events:
- type: system.message
content:
- type: text
text: "The user's current timezone is America/New_York."
YAMLsystem.message는 세션이 stop_reason: requires_action으로 유휴 상태일 때는 전송할 수 없습니다. content는 1~1000개의 텍스트 항목을 허용합니다.
세션 객체에는 누적 토큰 통계가 있는 usage 필드가 포함됩니다. 세션이 유휴 상태가 된 후 세션을 가져와 최신 합계를 읽고, 이를 사용하여 비용을 추적하거나 예산을 적용하거나 소비량을 모니터링하세요.
{
"id": "sesn_01...",
"status": "idle",
"usage": {
"input_tokens": 5000,
"output_tokens": 3200,
"cache_creation_input_tokens": 2000,
"cache_read_input_tokens": 20000
}
}input_tokens는 캐시되지 않은 입력 토큰을 보고하고 output_tokens는 세션의 모든 모델 호출에 걸친 총 출력 토큰을 보고합니다. cache_creation_input_tokens 및 cache_read_input_tokens 필드는 프롬프트 캐싱 활동을 반영합니다. 캐시 항목은 5분 TTL을 사용하므로 해당 기간 내의 연속된 턴은 캐시 읽기의 이점을 얻어 토큰당 비용이 줄어듭니다.
콘솔은 에이전트 세션의 시각적 타임라인 뷰를 제공합니다. 콘솔의 Claude Managed Agents 섹션으로 이동하여 다음을 확인하세요:
session.error 이벤트를 통해 전달됩니다Was this page helpful?