세션 이벤트 스트림
이벤트를 전송하고, 응답을 스트리밍하며, 실행 도중 세션을 중단하거나 방향을 전환합니다.
Claude Managed Agents와의 통신은 이벤트 기반입니다. 세션을 추적하려면 스트림을 열고, 세션을 지시하려면 이벤트를 전송하며, 세션이 입력을 기다리며 일시 중지되면 응답합니다.
이벤트 유형
이벤트는 두 방향으로 흐릅니다. 사용자가 에이전트에 이벤트를 전송하고, 세션은 사용자에게 이벤트를 다시 전송합니다.
- 전송하는 이벤트:
user.*이벤트는 세션을 시작하고 진행 중인 세션을 조정합니다.system.message이벤트는 시스템 수준 컨텍스트를 추가합니다. - 수신하는 이벤트: 세션 이벤트, span 이벤트, 에이전트 이벤트는 세션의 상태와 에이전트의 진행 상황을 보고합니다.
이러한 이벤트 유형 문자열은 {domain}.{action} 명명 규칙을 따릅니다. 전체 목록은 레퍼런스의 이벤트 유형을 참조하세요.
Webhook 이벤트 유형은 별개이며, 일부 이름은 스트림의 이름과 다릅니다. 예를 들어 webhook은 session.status_idle 대신 session.status_idled를 사용합니다.
이벤트 스트리밍
에이전트가 작업하는 동안 실시간 업데이트를 받으려면 세션에서 이벤트를 스트리밍하세요. 스트림은 열린 이후에 발생한 이벤트만 전달하므로, 경쟁 조건(race condition)을 피하려면 이벤트를 전송하기 전에 스트림을 여세요.
# 먼저 스트림을 연 다음 사용자 메시지를 보냅니다
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": "Summarize the repo README"}],
},
],
)
for event in stream:
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
break
case "session.error":
error_message = event.error.message if event.error else "unknown"
print(f"\n[Error: {error_message}]")
break세션은 session.error 이벤트를 통해 오류를 보고합니다. 해당 필드는 이벤트 유형을 참조하세요.
에이전트의 응답 텍스트는 버퍼링된 agent.message 이벤트로 도착하며, 각 이벤트는 이를 생성한 모델 요청이 완료된 후에만 발생합니다. 모델이 아직 생성 중인 텍스트를 렌더링하려면 이벤트 델타로 응답 미리 보기를 참조하세요.
이벤트 누락 없이 재연결하기
이벤트를 놓치지 않고 기존 세션에 재연결하려면 새 스트림과 이벤트 기록을 결합하세요.
- 새 스트림을 엽니다.
- 전체 이벤트 기록을 조회하여 이미 확인한 이벤트 ID 집합을 초기화합니다.
- 라이브 스트림을 추적하면서 기록 목록에서 이미 반환된 이벤트는 건너뜁니다.
with client.beta.sessions.events.stream(session.id) as stream:
# 스트림이 열려 버퍼링 중입니다. 라이브 추적 전에 기록을 조회합니다.
history = client.beta.sessions.events.list(session.id)
seen_event_ids = {past_event.id for past_event in history}
# 이미 본 이벤트는 건너뛰고 라이브 이벤트를 추적합니다
for event in stream:
if event.type == "event_start" or event.type == "event_delta":
# 이 연결에서는 델타 미리보기가 활성화되어 있지 않습니다.
continue
if event.id in seen_event_ids:
continue
seen_event_ids.add(event.id)
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
break이벤트 전송
에이전트의 작업을 시작하거나 계속하려면 user.message 이벤트를 전송하세요.
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Analyze the performance of the sort function in utils.py",
},
],
},
],
)세션 기록의 모든 이벤트에는 이벤트 처리가 완료될 때 설정되는 processed_at 타임스탬프가 포함됩니다. 사용자가 전송한 이벤트의 경우, 이벤트가 이전 이벤트 뒤에서 아직 대기 중인 동안 processed_at는 None입니다. 예외는 user.define_outcome, user.custom_tool_result, user.tool_result로, 이들은 수신 즉시 처리되며 processed_at가 이미 채워진 상태로 반환됩니다.
세션이 유휴 상태가 되면 응답하기
session.status_idle 이벤트는 에이전트가 중지되어 입력을 기다리고 있음을 의미합니다. 해당 이벤트의 stop_reason.type이 그 이유를 알려줍니다.
stop_reason.type | 세션이 중지된 이유 | 해야 할 일 |
|---|---|---|
end_turn | 에이전트가 턴을 마쳤거나 사용자가 중단했습니다. | 에이전트에게 맡길 작업이 더 있으면 user.message를 전송하세요. |
requires_action | 커스텀 도구 호출이나 확인 요청 등 하나 이상의 도구 호출에 사용자의 응답이 필요합니다. | 차단 중인 각 도구 호출에 응답하세요. |
budget_reached | 세션의 추적된 정가 비용이 예산에 도달했습니다. | 예산을 변경하거나 제거하세요. |
예산에 도달하여 일시 중지된 세션은 어떤 이벤트를 전송해도 재개되지 않습니다. 예산으로 인해 일시 중지된 작업은 예산을 소비된 정가 비용보다 높은 값으로 변경하거나 예산을 제거하면 자동으로 재개됩니다. 작업이 재개되면 세션은 예산으로 인해 일시 중지된 워크플로 실행마다 workflow_run.status_running 이벤트를 발생시킵니다. 중단(interrupt)으로 일시 중지된 실행은 일시 중지 상태로 유지됩니다. 예산에 도달한 세션 재개하기를 참조하세요. 일시 중지를 나타내는 이벤트와 세션이 여전히 수락하는 이벤트는 세션이 예산에 도달했을 때를 참조하세요.
세션을 일시 중지시키는 도구 호출에 응답하기
세션은 에이전트가 커스텀 도구를 호출할 때, 그리고 권한 정책에 따라 도구 호출에 사용자의 확인이 필요할 때 일시 중지됩니다. 두 경우 모두 동일한 순서를 따릅니다.
- 세션이 도구 호출을
agent.custom_tool_use,agent.tool_use또는agent.mcp_tool_use이벤트로 발생시킵니다. - 세션이
stop_reason.type이requires_action인session.status_idle이벤트와 함께 일시 중지됩니다. 차단 중인 이벤트 ID는stop_reason.event_ids배열에 있습니다. - 차단 중인 각 이벤트 ID에 대해
user.custom_tool_result또는user.tool_confirmation이벤트를 전송합니다. 커스텀 도구 결과는 2단계를 기다릴 필요가 없습니다. - 차단 중인 모든 이벤트가 해결되면 세션은 다시
running상태로 전환됩니다.
멀티에이전트 세션에서는 서브에이전트의 차단 이벤트가 기본 스레드에도 게시됩니다. 도구 권한 및 커스텀 도구를 참조하세요.
커스텀 도구 결과 반환하기
agent.custom_tool_use 이벤트에는 도구 이름과 입력이 포함되어 있습니다. 사용자의 시스템에서 도구를 실행하세요. 그런 다음 custom_tool_use_id 매개변수에 이벤트 ID를 전달하고 결과 콘텐츠와 함께 user.custom_tool_result 이벤트를 전송하세요.
session.status_idle을 기다리지 않고 agent.custom_tool_use 이벤트가 도착하는 즉시 결과를 전송할 수 있습니다. 세션은 해당 호출에 대해 여전히 requires_action 중지 이유와 함께 session.status_idle을 발생시키며, 클라이언트는 이를 무시해도 됩니다. 동일한 호출에 대한 두 번째 결과는 수락되지만 아무런 효과가 없습니다.
일시 중지된 세션에 재연결하면, 최신 session.status_idle 이벤트의 stop_reason.event_ids에 응답해야 할 호출이 나열됩니다.
다음 예제는 각 호출이 도착할 때마다 응답합니다.
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
match event.type:
case "agent.custom_tool_use":
# 도구를 실행합니다
result = call_tool(event.name, 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 "session.status_idle":
if event.stop_reason and event.stop_reason.type == "end_turn":
break에이전트에 열려 있는 워크플로 실행이 있으면, 세션이 running 상태를 유지하는 동안 커스텀 도구 호출이 도착할 수 있습니다. requires_action 유휴 이벤트는 세션의 스레드 중 어느 것도 작업 중이지 않을 때만 도착합니다. 이를 기다리지 말고, 각 호출의 agent.custom_tool_use 이벤트가 도착하면 응답하세요. 실행 추적하기의 샘플에서 방법을 확인할 수 있습니다.
도구 호출 확인하기
tool_use_id 매개변수에 이벤트 ID를 전달하여 user.tool_confirmation 이벤트를 전송하세요. result를 "allow" 또는 "deny"로 설정하세요. 어떤 호출이 확인을 기다리는지, 그리고 거부 사유를 설명하는 방법은 확인 요청에 응답하기를 참조하세요.
다음 예제는 대기 중인 모든 호출을 승인합니다.
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앞의 예제는 세션이 유휴 상태가 된 후 각 호출을 승인합니다. 에이전트에 열려 있는 워크플로 실행이 있으면, 세션이 running 상태를 유지하는 동안 도구 호출이 사용자의 확인을 기다릴 수 있습니다. 유휴 이벤트를 기다리지 마세요. evaluated_permission가 ask인 agent.tool_use 또는 agent.mcp_tool_use 이벤트가 도착하면 응답하세요. 실행 추적하기의 샘플은 이 방식으로 커스텀 도구 호출에 응답하며, 해당 소개 부분에서 확인을 추가하는 방법을 설명합니다.
유휴 세션 재개하기
세션은 상호작용 사이에도 유지됩니다. 세션을 재개하려면 평소처럼 user.message 이벤트를 전송하세요.
# 새 user.message 이벤트를 전송하여 이전에 생성된 세션을 재개합니다.
# 프로덕션에서는 재개하려는 세션의 저장된 ID를 전달하세요.
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Now run the tests against the changes you made earlier.",
},
],
},
],
)대화 기록은 세션이 명시적으로 삭제되지 않는 한 보존됩니다. 세션이 유휴 상태가 되면 해당 샌드박스의 체크포인트가 생성됩니다. 체크포인트는 파일 시스템, 설치된 패키지, 에이전트가 생성한 모든 파일을 포함한 전체 샌드박스 상태를 보존합니다.
에이전트 중단하기
실행 도중 에이전트를 중지하려면 user.interrupt 이벤트를 전송한 다음, 방향을 전환하기 위해 user.message 이벤트를 이어서 전송하세요.
# 에이전트가 현재 파일을 분석 중입니다...
# 새로운 지시로 중단합니다:
client.beta.sessions.events.send(
session.id,
events=[
{"type": "user.interrupt"},
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Instead, focus on fixing the bug in line 42.",
},
],
},
],
)호출은 이벤트가 대기열에 추가되는 즉시 반환됩니다. 그런 다음 중단은 다음 순서로 적용됩니다.
- 에이전트가 중단을 적용합니다. 그때까지 중단 이벤트의
processed_at는None로 유지되며 세션은running상태를 유지합니다. 진행 중인 모델 응답은 즉시 중지되지만, 도구 호출이 실행 중인 동안에는 중단이 적용되는 데 더 오래 걸릴 수 있습니다. user.interrupt이벤트가 스트림에 나타나고, 중단된 턴은session.status_idle이벤트와 함께 종료됩니다.- 에이전트는 중단 후 전송한
user.message로 다음 턴을 시작합니다.
유휴 이벤트의 stop_reason.type은 end_turn으로, 스스로 완료된 턴과 동일한 값입니다. 열려 있는 워크플로 실행이 있는 경우, 중단은 그중 어느 것도 종료하지 않습니다. 실행 중인 실행은 세션을 running 상태로 유지할 수 있으므로, 2단계의 session.status_idle 이벤트가 도착하지 않을 수 있습니다. 실행이 열려 있는 세션 중단하기를 참조하세요.
과거 이벤트 조회하기
세션의 전체 이벤트 기록을 가져옵니다.
events = client.beta.sessions.events.list(session.id)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")특정 이벤트 유형만 반환하려면 types 필터를 전달하세요.
events = client.beta.sessions.events.list(
session.id,
types=["agent.tool_use", "agent.tool_result"],
)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")시스템 메시지 전송하기
지원되는 모델에서는 system.message 이벤트를 전송하여 에이전트에 권한 있는 시스템 수준 컨텍스트를 제공할 수 있습니다. 이 컨텍스트는 함께 전송된 턴과 이후의 모든 턴에 적용됩니다. 세션 도중 에이전트에 업데이트된 시스템 수준 지침이 필요할 때 사용하세요. 예를 들어 다른 페르소나, 수정된 제약 조건, 런타임에 가져온 컨텍스트 등이 있습니다.
이벤트의 content는 1–1000개의 텍스트 항목을 허용합니다. 콘텐츠는 role: "system" 턴으로 세션의 시스템 컨텍스트에 추가됩니다. 이는 에이전트 정의의 system 필드로 설정되는 최상위 시스템 프롬프트를 대체하지 않습니다.
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "system.message",
"content": [
{
"type": "text",
"text": "The user's current timezone is America/New_York.",
},
],
},
],
)지원되는 모델
system.message는 다음 모델에서 지원됩니다.
- Claude Fable 5.1
- Claude Mythos 5.1
- Claude Fable 5
- Claude Mythos 5
- Claude Opus 5.5
- Claude Opus 5
- Claude Opus 4.8
- Claude Sonnet 5.5
- Claude Haiku 5.5
에이전트의 기본 모델이 대화 도중 시스템 주입을 지원하지 않으면, 이벤트는 model_does_not_support_mid_conversation_system 유효성 검사 오류와 함께 거부됩니다. system.message는 기본 스레드에만 전달되므로 서브에이전트 모델은 검사되지 않습니다.
도구 호출이 대기 중일 때의 시스템 메시지
세션이 requires_action 중지 이유로 유휴 상태인 동안에는 system.message가 동일한 요청에서 도구 결과 이벤트 뒤에 와야 합니다. 단독으로 전송하거나 user.message와 함께 전송하면, 대기 중인 도구 이벤트가 해결될 때까지 거부됩니다.
다음 단계
모델이 아직 생성 중인 에이전트의 응답 텍스트를 렌더링합니다.
Claude Console에서 세션을 검사하고 토큰 사용량과 정가 비용을 확인합니다.
폴링 없이 주요 이벤트가 발생할 때 알림을 받습니다.
세션이 전송하거나 수신할 수 있는 모든 이벤트 유형을 찾아봅니다.
Was this page helpful?