OpenAI Agents API는 오래 도는 AI Agent를 어떻게 다루나. Context, Tools, Subagents, JSON 상태 관리 (2026)
9월 10일 공개 베타는 「또 하나의 chat」이 아니다. Codex를 며칠 돌리던 harness를 넘겼다. Session은 이어지고, 문맥은 compact되며, subagent는 자기 문맥을 가진다. 긴 일이 어떻게 사는지에만 쓴다. 어떤 JSON을 저장하고, 무엇이 압축되며, 끊긴 뒤 어느 items를 읽는지.
읽기 전 한눈
| 대상 | 무엇을 하나 | 무엇을 쥐나 |
|---|---|---|
| Session | 시간과 창을 넘는 이어지는 인스턴스 | session_id |
| Turn | 한 입력이 여는 비동기 작업 | turn_id / 종료 이벤트 |
| Items | 저장된 메시지와 도구 호출 | 끊긴 뒤 재생 |
| Compact | 창 한도에 가까우면 자동 압축 | 핵심 필드는 직접 보관 |
| Subagent | 독립 문맥, 병렬 작업 | 동시 실행 상한 |
유휴 session은 성공이 아니다. turn 이벤트와 items를 본다. 마지막 문장이 아니다.
긴 일은 Session에 산다. 더 긴 prompt가 아니다
Agents API의 답은 구체적이다. durable session을 만들고 이후 입력은 같은 session_id로 보낸다. 문맥 한도에 가까우면 harness가 앞선 내용을 자동 compact한다. 독립 하위 일은 subagent에 넘길 수 있다. 채팅 전문을 직접 짜지 않는다.
- 이어 달리기:
session_id를 업무 대화에 묶는다. 같은 건에 두 번째 session을 열지 않는다. - 끊김: 스트림은 다시 재생하지 않는다. session과 items를 가져온다. 클라이언트가 지난 홉을 안다고 가정하지 않는다.
- 돈과 번호: compact는 세부를 버린다. 주문 번호, 금액, 승인은 당신 JSON에 둔다.
Session과 도구 JSON의 이음은 OpenAI Agents API 완전 해설. 루프를 맡길지는 Agents API vs Responses API. Agent와 Function Calling이 아직 한 단어라면 AI Agent 완전 가이드.
Session은 이어지고 Turn은 비동기로 돈다
생성 때 모델, 도구, 환경, multi_agent를 한 번에 선언한다. 공식 생성은 POST /v1/agents/sessions, 헤더는 OpenAI-Beta: agents=v1. 호스트 샌드박스는 openai_hosted:
{
"agent": {
"model": "gpt-6-astra",
"instructions": "Look up orders. Confirm before any refund. Delegate independent lookups to subagents.",
"tools": [
{
"type": "function",
"name": "lookup_order",
"parameters": {
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^[A-Z]-\\d{4}$" }
},
"required": ["order_id"],
"additionalProperties": false
}
},
{ "type": "web_search" }
],
"multi_agent": { "enabled": true, "max_concurrent_subagents": 3 }
},
"environment": { "type": "openai_hosted", "workspace_directory": "/workspace" },
"input": [
{
"role": "user",
"content": [{ "type": "input_text", "text": "Look up A-1042 and keep the case open." }]
}
]
}
같은 session에 agent.session.input.message를 보낸다. 유휴면 새 turn. 도는 중이면 현재 turn을 조향한다. 취소는 agent.session.input.cancel. session과 저장된 일은 남는다:
{
"events": [
{
"type": "agent.session.input.message",
"input": [
{
"role": "user",
"content": [
{ "type": "input_text", "text": "Warehouse marked A-1042 packed. Continue." }
]
}
]
}
]
}
결말을 본다. 「지금 유휴인가」가 아니다. 공식 이벤트는 agent.session.turn.completed, failed, cancelled. turn 완료는 모든 도구 성공이 아니다. 함수 결과가 필요하면 required_actions를 읽는다.
도구 사슬은 시간을 넘는다. 되돌림은 여전히 JSON
긴 일에서도 모델은 인자만 채운다. 함수 차례가 오면 harness가 멈추고 turn_id / call_id로 결과를 돌려준다. 네 시간 뒤에도 모양은 같다:
{
"type": "tool_result",
"turn_id": "turn_4",
"call_id": "call_3c91",
"success": true,
"output": "{\"order_id\":\"A-1042\",\"status\":\"packed\"}"
}
function은 당신이 실행한다. MCP와 web_search는 harness가 돌릴 수 있다. subagent는 MCP와 웹 검색을 이어받는다. function 도구는 이어받지 않는다. 자사 주문의 부작용은 주 Agent에 남긴다.
문은 여전히 Schema. 넓은 object는 긴 일에서 더 위험하다. compact 뒤 모델이 번호를 틀리기 쉽다. MCP 행은 다른 도구 표. 경계는 MCP Tool Schema vs Function Calling.
Compact가 줄이는 것은 창이지 장부가 아니다
공식은 이렇게 쓴다. 한도에 가까우면 Agents API가 앞선 문맥을 자동 compact하여 일이 여러 창을 넘게 한다. 압축기를 직접 쓰지 않는다. Responses의 context_management / /responses/compact와는 다른 층이다.
- Agents API: session이 스스로 누른다. items를 가져와 주문 번호가 남았는지 본다.
- Responses: compact를 직접 켜거나 compact 엔드포인트를 부른다. 암호화된 compaction item을 다음 창 입력으로 넘긴다. 손으로 자르지 않는다.
- 양쪽: 압축은 세부를 버린다. 금액, 확인, 배포는 호스트가 쓴다.
order_id를 대화에만 두면 장부를 요약에 넘긴 것이다. 문으로서의 Schema는 AI에 JSON Schema가 필요한 이유.
Subagent: 병렬이지만 문맥은 갈린다
multi_agent.enabled를 켜면 harness가 생성, 전달, 대기, 중단을 준다. 이 도구를 직접 선언하지 않는다. items에 편성 동작이 나타난다:
{
"data": [
{
"type": "function_call",
"turn_id": "turn_4",
"call_id": "call_3c91",
"name": "lookup_order",
"arguments": "{\"order_id\":\"A-1042\"}"
},
{
"type": "create_subagent_call",
"agent_id": "agent_main",
"task": "Compare A-1042 packing notes with the invoice."
}
]
}
- 독립 문맥: subagent마다 하나. 주 Agent는 create / message / wait / interrupt로 닫는다.
- 동시 실행에 상한: 기본은 6(조정자 제외). 운영에서는 더 작은 수를 고정한다.
- 끝난 항목 ≠ 하위 일 종료:
create_subagent_call완료는 파견된 것뿐이다.agent.session.subagent.created와 그 subagent의 items를 본다.
handoff는 감사 가능한 JSON이어야 한다. 「청구팀에 넘겨」라는 문장이 아니다. Schema로 담는 법은 JSON Schema와 Agent 워크플로.
상태는 당신이 쥔다. compact에게 기억시키지 마라
OpenAI는 session 설정, 대화, 저장된 일을 가진다. 끊긴 뒤 다시 세울 업무 객체는 여전히 당신 것이다:
{
"session_id": "sess_8f21",
"order_id": "A-1042",
"last_turn_id": "turn_4",
"last_call_id": "call_3c91",
"awaiting": "tool_result",
"compact_checkpoint": "after_turn_3"
}
이 객체는 Session도, SDK session도, Responses conversation도, sandbox도 아니다. 하나를 지워도 나머지는 남는다. 데이터 거주는 당분간 미국만. 자체 호스트 샌드박스여도 ZDR이 되지 않는다.
창을 넘는 일을 끝내는 다섯 걸음
데모 영상에서 거꾸로 그리지 마라. 대상을 걷는다:
- session을 한 번 만든다.
session_id를 대화에 쓴다. 도구 표와 Schema는 한 번에 조인다. - 구독한 뒤 다음 입력을 보낸다. 스트림을 먼저 열고
agent.session.input.message를 친다. 이른 이벤트를 잃지 않는다. - required_actions에서 멈추면 되돌린다. 같은
turn_id/call_id를 쓴다. 새 session으로 재시도하지 않는다. - 끊기면 items를 가져온다. 스트림은 재생하지 않는다.
order=asc로 나열하고 번호와 열린 호출을 맞춘다. - compact 뒤 장부를 다시 본다. 요약에
A-1042가 없으면 다음 홉이 번호를 만든다.
다섯 걸음은 모두 대상 위에 있다. 하나를 빼면 창이 아직 비었다고 거는 것이다.
긴 일을 되짚으려면 JSON 두 줄을 펼친다
실패의 대부분은 모델이 둔해진 것이 아니다. 대상이 어긋난 것이다.
- session items와 로컬 상태를 포맷하고
session_id/call_id가 맞는지 본다. - JSONPath 추출로
order_id,turn_id, subagent의agent_id를 뽑는다. - compact 전후 items를 JSON Diff. 번호가 흘렀으면 먼저 압축을 본다.
- 주 Agent items와 어떤 subagent items는 따로 나열한다. 한 페이지에 섞이면 편성이 다른 주체에 붙는다.
- 주문, session, 사내 MCP를 공개 포맷터에 붙이지 마라. JSONSort는 브라우저에서 로컬로 돈다.
두 궤적이 다시 세워져야 일이 이어진 것이다. 아니면 다시 추측한 것이다.
흔한 함정
- 유휴를 성공으로 본다.
turn.completed/failed/cancelled를 본 뒤 도구 결과를 본다. - 끊긴 뒤 스트림 재생을 기다린다. 공식은 재생하지 않는다고 쓴다. session과 items를 가져온다.
- 주문 번호를 대화에만 둔다. compact 뒤 요약이
A-1042를 버릴 수 있다. - multi_agent를 켜고 상한을 두지 않는다. 기본 6도 토큰과 부작용을 부채꼴로 키운다.
- subagent에게 function을 돌리게 한다. 하위 에이전트는 function 도구를 쓰지 못한다. 조회는 주 Agent에 남긴다.
- Session과 Conversation을 한 자원으로 본다. 하나를 지워도 다른 것은 남는다.
FAQ
오래 도는 것은 더 긴 prompt인가?
아니다. durable session, 자동 compact, 당신이 보관하는 업무 JSON이다. 더 긴 시스템 프롬프트는 창 한도를 올리지 못한다.
Agents compact와 Responses compact를 섞어도 되나?
섞지 마라. Agents session은 스스로 누른다. Responses는 context_management 또는 /responses/compact. 자원 둘, 다음 창 입력 둘.
끊긴 뒤 어떻게 복구하나?
저장한 session_id로 session과 items를 가져온다. 스트림은 놓친 이벤트를 재생하지 않는다. last_turn_id와 열린 call_id를 맞춘 뒤 되돌리거나 다음 메시지를 보낸다.
subagent가 lookup_order를 호출할 수 있나?
없다. 공식은 function 도구 미지원을 쓴다. MCP, 웹 검색, 환경의 파일 / 명령은 이어받는다. 자사 주문 조회는 주 Agent에 남긴다.
자체 호스트 샌드박스면 Zero Data Retention인가?
아니다. 공식은 당분간 미국 거주만, ZDR 미지원을 쓴다. self-hosted를 골라도 ZDR이 되지 않는다.
결론
오래 도는 것은 더 똑똑한 모델이 아니다. 이어지는 Session, 자동 compact, 당신이 쥐는 JSON 상태다. 도구 인자, turn 이벤트, subagent items는 그 사슬 위의 대상일 뿐이다.
끊긴 뒤 A-1042를 다시 세울 수 있는지를 먼저 쓴다. 되면 일은 살아 있다. 모델은 바뀐다. session_id와 Schema를 먼저 고정한다.
더 읽기
- OpenAI Agents API 완전 해설 Session, Tool Calling, Schema의 이음
- Agents API vs Responses API 누가 루프를 도나
- AI Agent란 무엇인가. 완전 가이드 런타임과 JSON 계약
- AI에 JSON Schema가 필요한 이유 Schema / Function Calling / Structured Output
- JSON Schema와 Agent 워크플로 도구와 상태를 Schema로 담기
- JSONSort 로컬 도구상자 포맷, 검증, Diff
- 모든 글 JSON과 AI 개발 메모
변경 기록: 최초 게시