API 서버
API 서버 (API Server)
에이전트를 프로그래매틱 접근, 웹 프론트엔드, 통합을 위한 HTTP API로 노출해요.
출처: 문서
본문
에이전트를 프로그래매틱 접근, 웹 프론트엔드, 통합을 위한 HTTP API로 노출해요.
개요 (Overview)
docker agent serve api 명령은 Server-Sent Events(SSE) 스트리밍이 있는 REST 스타일 API로 에이전트를 노출하는 HTTP 서버를 시작해요. 웹 UI를 만들거나, CI/CD 파이프라인과 통합하거나, 에이전트를 다른 서비스에 연결하는 데 사용해요.
# Start the API server
$ docker agent serve api agent.yaml
# Custom listen address
$ docker agent serve api agent.yaml --listen 0.0.0.0:8080
# With session persistence
$ docker agent serve api agent.yaml --session-db ./sessions.db
# Auto-refresh from OCI registry every 10 minutes
$ docker agent serve api myorg/coder --pull-interval 10
팁 — API 서버 vs chat 서버를 언제 쓸까: 세션, 에이전트 실행, 도구 호출 확인, 스트리밍 런타임 이벤트를 완전히 제어하고 싶으면 API 서버를 사용해요 — 이것이 Docker Agent의 네이티브 프로토콜이에요. Docker Agent를 기존 OpenAI 호환 도구(챗 UI, IDE 통합, OpenAI SDK 클라이언트)에 꽂고 싶으면 Chat Server를 사용하세요.
엔드포인트 (Endpoints)
모든 엔드포인트는 /api 접두사 아래 있어요.
에이전트 (Agents)
| Method | Path | 설명 |
|---|---|---|
| GET | /api/agents |
사용 가능한 모든 에이전트 나열 |
| GET | /api/agents/:id |
에이전트의 전체 구성 가져오기 |
GET /api/agents 응답의 각 에이전트 항목은 다음을 포함해요:
| 필드 | 타입 | 설명 |
|---|---|---|
name |
string | 에이전트 식별자(확장자 없는 구성 파일 이름). |
description |
string | 루트 에이전트의 description 필드. |
multi |
boolean | 구성이 둘 이상의 에이전트를 정의하면 true. |
commands |
array of string | 루트 에이전트에 정의된 명명된 command 키의 정렬된 목록. 명령이 없으면 생략. |
세션 (Sessions)
| Method | Path | 설명 |
|---|---|---|
| GET | /api/sessions |
모든 세션 나열 |
| POST | /api/sessions |
새 세션 생성. 선택적 title 필드 허용 — 설정하면 저장되고 LLM 제목 생성은 건너뛰어요. |
| GET | /api/sessions/:id |
ID로 세션 가져오기(메시지, 토큰, 권한) |
| GET | /api/sessions/:id/status |
가벼운 런타임 상태(streaming, title, agent, tokens). 첨부된 런타임 필요. |
| GET | /api/sessions/:id/snapshot |
한 호출로 전체 상태(저장된 필드 + 런타임 상태 + last_event_seq). 갭 없는 재동기화용 — Reconnecting without gaps 참조. |
| GET | /api/sessions/:id/events |
시퀀스 번호와 replay가 있는 라이브 세션 이벤트 스트림(SSE). --listen으로 첨부된 run, 또는 세션이 하나 이상의 아웃오브밴드 이벤트(예: 백그라운드 작업의 elicitation, POST .../elicitation으로 응답)를 발생시킨 후 사용 가능 — 그러면 온디맨드 세션 범위 이벤트 로그가 생성돼 그런 아웃오브밴드 이벤트를 담아요. |
| DELETE | /api/sessions/:id |
세션 삭제 |
| PATCH | /api/sessions/:id/title |
세션 제목 업데이트 |
| PATCH | /api/sessions/:id/permissions |
세션 권한 업데이트 |
| POST | /api/sessions/:id/fork |
사용자 메시지에서 세션 포크 — 부모의 [0, message_index) 메시지로 새 세션 생성(Session Forking 참조). |
| POST | /api/sessions/:id/messages |
메시지를 세션 기록에 직접 추가(모델 우회). 세션에 활성 run이 있으면 409 Conflict 반환(Agent Execution 참조). |
| PATCH | /api/sessions/:id/messages/:msg_id |
ID로 기존 메시지 업데이트. 세션에 활성 run이 있으면 409 Conflict 반환. |
| POST | /api/sessions/:id/resume |
일시 중지된 세션 재개(도구 확인 후). |
| POST | /api/sessions/:id/tools/toggle |
자동 승인(YOLO) 모드 토글 |
| POST | /api/sessions/:id/elicitation |
MCP 도구 elicitation 요청에 응답. elicitation_request 이벤트의 elicitation_id를 전달해 특정 동시 요청을 대상으로 해요. 생략하면 유일한 보류 요청을 해결해요. |
| POST | /api/sessions/:id/steer |
실행 중인 턴에 메시지 주입(현재 것 선점). |
| POST | /api/sessions/:id/followup |
현재 턴이 끝난 후 실행할 메시지 큐(Idempotency-Key 지원 — Idempotent follow-ups 참조). |
| GET | /api/sessions/:id/models |
세션의 현재 에이전트에 사용 가능한 모델 나열 |
에이전트 실행 (Agent Execution)
| Method | Path | 설명 |
|---|---|---|
| POST | /api/sessions/:id/agent/:agent |
세션에 대한 루트 에이전트 실행(SSE 스트림) |
| POST | /api/sessions/:id/agent/:agent/:name |
특정 명명된 에이전트 실행(SSE 스트림) |
| GET | /api/agents/:id/:agent_name/tools/count |
현재 :agent_name에 사용 가능한 도구 수(지연 도구셋 반영). |
경로 파라미터:
:agent— 에이전트 식별자..yaml확장자 없는 구성 파일 이름.docker agent serve api에 전달된 파일 이름과 일치해야 해요. 예를 들어docker agent serve api my-assistant.yaml로 서버를 시작하면 에이전트 식별자는my-assistant예요. YAML 파일 디렉토리를 서빙하면 각 파일이 확장자 없는 파일 이름으로 식별되는 별도 에이전트가 돼요.:name(선택) — 멀티 에이전트 구성에 정의된 특정 하위 에이전트 이름. 생략하면 요청이 루트 에이전트를 대상으로 해요. 예를 들어root,coder,reviewer라는 에이전트를 정의하는 구성에서/api/sessions/:id/agent/my-config/coder를 사용해 coder 하위 에이전트를 직접 실행할 수 있어요.
예제:
# Single-agent config: my-assistant.yaml
# Start: docker agent serve api my-assistant.yaml
# Run the root agent:
curl -N -X POST http://localhost:8080/api/sessions/$SID/agent/my-assistant \
-H "Content-Type: application/json" \
-d '{"messages":[{"role": "user", "content": "Hello!"}]}'
# Multi-agent config: team.yaml (defines agents: root, coder, reviewer)
# Start: docker agent serve api team.yaml
# Run the root agent:
curl -N -X POST http://localhost:8080/api/sessions/$SID/agent/team \
-H "Content-Type: application/json" \
-d '{"messages":[{"role": "user", "content": "Review this PR"}]}'
# Run a specific sub-agent (reviewer):
curl -N -X POST http://localhost:8080/api/sessions/$SID/agent/team/reviewer \
-H "Content-Type: application/json" \
-d '{"messages":[{"role": "user", "content": "Review this PR"}]}'
헬스 (Health)
| Method | Path | 설명 |
|---|---|---|
| GET | /api/ping |
헬스 체크 — {"status": "ok"} 반환 |
OAuth
| Method | Path | 설명 |
|---|---|---|
| POST | /api/mcp-oauth/callback |
OAuth deeplink 콜백을 보류 중인 unmanaged OAuth 흐름에 전달. 성공 경로: ?state=<state>&code=<code>; authorization-server 오류 경로: ?state=<state>&error=<error>&error_description=<desc>. state가 없거나 code/error 둘 다 없으면 400, 그 state를 기다리는 흐름이 없으면 404 반환. Remote MCP OAuth 참조. |
스트리밍 응답 (Streaming Responses)
에이전트 실행 엔드포인트(POST /api/sessions/:id/agent/:agent)는 Server-Sent Events(SSE)를 반환해요. 요청 본문은 messages 배열과 선택적 model 필드가 있는 JSON 객체예요. model을 설정하면 턴이 시작되기 전에 세션에 영구 per-agent 재정의를 적용해요(이후 턴이 재사용). 빈 model 또는 생략된 model은 기존 재정의를 그대로 둬요. (각 이벤트는 런타임 이벤트를 나타내는 JSON 객체예요 — :agent가 .yaml 확장자 없는 구성 파일 이름임을 기억하세요):
# Send a message and stream the response
# (assuming the server was started with: docker agent serve api my-agent.yaml)
$ curl -N -X POST http://localhost:8080/api/sessions/$SID/agent/my-agent \
-H "Content-Type: application/json" \
-d '{"messages":[{"role": "user", "content": "Hello!"}]}'
# Same call, but switch the agent's model for this turn (and persist it):
$ curl -N -X POST http://localhost:8080/api/sessions/$SID/agent/my-agent \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Hello!"}],"model":"openai/gpt-4o"}'
# Response (SSE stream):
data: {"type": "stream_started", "session_id": "...", "agent": "root"}
data: {"type": "agent_choice", "content": "Hello! How", "agent": "root"}
data: {"type": "agent_choice", "content": " can I help", "agent": "root"}
data: {"type": "agent_choice", "content": " you today?", "agent": "root"}
data: {"type": "stream_stopped", "session_id": "...", "agent": "root"}
이벤트 유형:
stream_started/stream_stopped— 에이전트 실행 라이프사이클agent_choice— 스트리밍된 텍스트 콘텐츠(부분 응답)tool_call— 에이전트가 도구 실행 요청tool_call_confirmation— 사용자 승인을 기다리는 도구 호출tool_call_response— 도구 실행 결과plan_changed— 공유 플랜이 plan toolset을 통해 생성·업데이트·삭제됨. 페이로드는 플랜의scope,name,action,version을 담아요 — 내용은 절대 담지 않아요. 공유 플랜은 의도적으로 process-global이에요: 같은 프로세스가 서빙하는 모든 활성 스트림이 같은 공유 플랜 알림자에 구독해 어떤 세션이 변경을 수행했든 이벤트를 받고, 페이로드는 변경한 세션을 식별하지 않아요(협업 속성은 플랜의 author 메타데이터를 읽으세요).error— 실행 중 오류
일반적 워크플로우 (Typical Workflow)
- 에이전트 나열 —
GET /api/agents로 사용 가능한 에이전트 발견 - 세션 생성 —
POST /api/sessions로 대화 시작 - 메시지 전송 —
POST /api/sessions/:id/agent/:agent로 사용자 메시지 전송 - 응답 스트리밍 — 에이전트가 처리하며 SSE 이벤트 읽기
- 확인 처리 — 도구 호출이 승인을 필요로 하면
POST /api/sessions/:id/resume - 계속 — 같은 세션에 후속 메시지 전송
# 1. List available agents
$ curl http://localhost:8080/api/agents
[{"name": "my-agent", "multi":false, "description": "A helpful assistant", "commands": ["deploy", "review"]}]
# 2. Create a session
$ curl -X POST http://localhost:8080/api/sessions \
-H "Content-Type: application/json" -d '{}'
{"id": "abc-123", "title": "", "created_at": "..."}
# Create a session with a pre-supplied title (skips LLM title generation)
$ curl -X POST http://localhost:8080/api/sessions \
-H "Content-Type: application/json" -d '{"title":"deploy check"}'
{"id": "def-456", "title": "deploy check", "created_at": "..."}
# title preserved; LLM title generation skipped
# 3. Run the agent with a message
$ curl -N -X POST http://localhost:8080/api/sessions/abc-123/agent/my-agent \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"What files are in the current directory?"}]}'
CLI 플래그 (CLI Flags)
docker agent serve api <agent-file> | <agents-dir> [ flags ]
| 플래그 | 기본값 | 설명 |
|---|---|---|
-l, --listen |
127.0.0.1:8080 |
수신할 주소 |
--auth-token |
(없음) | 모든 API 요청에 필요한 Bearer 토큰. 비우면 인증 비활성화(루프백 인터페이스에서만 수신할 때 안전). --listen이 네트워크 도달 인터페이스에 바인딩될 때 권장. |
--max-request-size <bytes> |
1048576 (1 MiB) |
최대 요청 본문 크기(바이트). 이 한도를 초과하는 본문 요청은 HTTP 413(Request Entity Too Large)로 거부 — 이 오류가 나면 Troubleshooting: HTTP 413 참조. |
--session-workingdir-root |
(없음 — 무제한) | POST /api/sessions가 받아들이는 working_dir을 이 디렉토리로 한정: 심링크 해석 후 요청 디렉토리는 루트 또는 그 하위여야 해요. 기본적으로 임의의 깨끗한 호스트 디렉토리를 받아들여요(임의 워크스페이스를 여는 로컬 단일 사용자 데몬의 의도된 동작) — 하지만 ..를 포함한 원시 값은 항상 거부돼요. API가 임의 호스트 경로에 도달해서는 안 되는 호출자(다중 사용자 또는 네트워크 노출 배포)를 서빙할 때마다 루트를 설정하세요. |
-s, --session-db |
session.db |
SQLite 세션 데이터베이스 경로 |
--pull-interval |
0 (비활성화) |
매 N분마다 OCI 참조 자동 가져오기 |
--fake |
(없음) | 카세트 파일에서 AI 응답 재생(테스트) |
--record |
(없음) | AI API 상호작용을 카세트 파일에 기록. one이 구성되면 --models-gateway로 경유. |
--mcp-oauth-redirect-uri |
(없음) | unmanaged MCP OAuth 흐름의 OAuth redirect_uri로 광고되는 공개 HTTPS URL. 설정하면 Docker Agent가 PKCE와 code exchange를 프로세스 내에서 구동하고 전체 authorize URL을 elicitation으로 클라이언트에 보내요. Remote MCP 참조. |
참고 — --max-request-size가 다루는 것과 다루지 않는 것: 이것은 직렬화된 인바운드 HTTP 요청 본문 하나의 유한한 process-wide 상한이에요. 모델 컨텍스트 윈도우 한도가 아니며, 올린다고 provider/model이 받아들이는 것 또는 로컬 첨부/프롬프트 파일이 얼마나 클 수 있는지를 늘리지 않아요. 더 큰 상한은 또한 서버가 인증되지 않거나 악성 클라이언트로부터 요청당 더 많은 메모리를 버퍼링한다는 뜻이므로 배포 노출과 저울질하세요. 이 서버 앞에 리버스 프록시나 게이트웨이가 있으면 이 플래그와 무관하게 자체 더 낮은 상한을 적용할 수 있어요. 전체 진단은 Troubleshooting: HTTP 413 참조.
팁 — 라이브 프로파일링(고급): 프로덕션 진단을 위해 CAGENT_PPROF_ADDR 환경 변수(또는 숨겨진 --pprof-addr 플래그)를 127.0.0.1:6060 같은 TCP 주소로 설정하세요. Docker Agent는 /debug/pprof/에 Go pprof HTTP 서버를 시작하고 go tool pprof로 조회할 수 있어요. 루프백 주소를 사용하세요 — 비 루프백 바인딩은 보안 경고를 로그해요. 이 플래그는 의도적으로 --help에서 숨겨져 있어요.
팁 — 멀티 에이전트 구성: docker agent serve api를 여러 에이전트 YAML 파일이 있는 디렉토리에 가리킬 수 있어요. 각 파일은 /api/agents로 접근 가능한 별도 에이전트가 돼요. OCI 레지스트리에서 에이전트를 자동 새로 고침하려면 --pull-interval과 결합하세요.
세션 영속성 (Session Persistence)
세션은 SQLite 데이터베이스(기본: 현재 디렉토리의 session.db)에 저장돼요. 이는 다음을 뜻해요:
- 세션이 서버 재시작에도 유지돼요.
- 여러 서버 인스턴스가 데이터베이스를 공유할 수 있어요.
- 커스텀 경로는
--session-db로 지정해요.
도구 호출 승인 (Tool Call Approval)
기본적으로 도구 호출은 승인이 필요해요. API 워크플로우에서:
- 에이전트가 도구 호출 → 서버가
tool_call_confirmation이벤트를 방출 - 클라이언트가 검토하고 결정과 함께
POST /api/sessions/:id/resume전송 - 승인/거부에 따라 실행 계속
자동화된 워크플로우용 자동 승인은 POST /api/sessions/:id/tools/toggle로 토글해요.
실행 중인 TUI를 --listen으로 구동 (Driving a running TUI with --listen)
같은 세션 API를 대화형 run이 노출해 외부 프로세스가 구동할 수 있어요 — 후속 프롬프트 전송, 진행 관찰, 제목 읽기 — 터미널을 스크래핑하지 않고요. 일반 run을 시작하고 --listen을 추가하세요:
# Expose this run's control plane on a TCP port...
$ docker agent run agent.yaml --listen 127.0.0.1:8080
# ...or on a unix socket (no port to allocate; access is gated by file
# permissions). npipe:// (Windows) and fd:// are also accepted.
$ docker agent run agent.yaml --listen unix:///tmp/my-run.sock
run은 대화형 TUI를 유지하고 제어판이 그 옆에서 실행돼요. HTTP로 전달된 후속은 TUI에 타이핑된 것처럼 정확히 처리돼요: 에이전트가 유휴일 때도 턴을 시작하고, 첫 턴에 세션 제목을 생성하고, 결과 이벤트를 터미널과 연결된 모든 API 클라이언트 둘 다에 스트리밍해요.
# Send a follow-up to the attached run (SID is the --session id):
$ curl -X POST http://127.0.0.1:8080/api/sessions/$SID/followup \
-H 'Content-Type: application/json' \
-d '{"messages":[{"content":"Now add tests"}]}'
참고 — run 발견: --listen으로 시작된 각 run은 그 주소와 세션 id를 포함한 발견 레코드를 <data-dir>/runs/<pid>.json에 써요. 감독 프로세스가 세션 id, pid, 또는 주소로 살아있는 run을 찾을 수 있어요.
경고 — 이 제어판은 고정 1 MiB 요청 본문 상한과 내장 인증이 없어요: 위의 독립형 docker agent serve api 프로세스와 달리, 첨부된 run의 --listen 제어판은 --max-request-size도 --auth-token도 노출하지 않아요: 모든 요청은 고정·비구성 가능한 1 MiB 본문으로 제한되고(초과 시 HTTP 413 반환 — Troubleshooting: HTTP 413 참조), 요구할 bearer 토큰이 없어요. 구성 가능한 상한, 내장 bearer 인증, 또는 네트워크 도달 리스너가 필요하면 독립형 docker agent serve api 배포를 대신 실행하세요. 그렇지 않으면 --listen을 루프백, 유닉스 소켓, 또는 인증 리버스 프록시 뒤에 두세요.
세션 이벤트 스트림과 재연결 (Session event stream and reconnection)
GET /api/sessions/:id/events는 세션 런타임 이벤트의 Server-Sent Events 스트림이에요 — stream_started, agent_choice, tool_call, session_title, token_usage, stream_stopped 등. 에이전트 실행 엔드포인트가 반환하는 요청별 스트림과 달리 session-scoped이고 턴을 넘어 유지되므로 클라이언트가 세션을 평생 지켜볼 수 있어요. --listen으로 첨부된 run에서 사용 가능하고 — 세션이 아웃오브밴드 이벤트(예: 백그라운드 작업의 elicitation_request)를 발생시키는 첫 순간에 온디맨드 세션 범위 이벤트 로그가 생성되므로 — 적어도 하나를 생산한 어떤 API 생성 세션에서도 사용 가능해요(위 Sessions 엔드포인트 표 참조). 두 종류의 로그는 범위가 달라요: --listen run은 전체 런타임 이벤트 스트림을 로그에 넣고, API 생성 세션의 온디맨드 로그는 세션의 아웃오브밴드 이벤트만 담아요 — 턴을 실행하는 에이전트 실행 요청의 요청별 SSE 스트림으로 흐르는 모든 일반 턴 이벤트는 아닐 수 있어요.
각 이벤트는 SSE id: 필드에 단조 시퀀스 번호를 담고, 서버는 최근 이벤트를 버퍼링해요. 이것은 스트림을 재개 가능하게 해요:
- 드롭 후 재개 — 표준
Last-Event-ID헤더(브라우저 EventSource 클라이언트가 자동으로 보냄) 또는?since=<seq>쿼리 파라미터로 재연결해요. 그 지점보다 새로운 버퍼링된 이벤트는 라이브 테일링이 재개되기 전에 재생되므로 아무것도 놓치지 않아요. - 갭 신호 — 재개 지점이 이미 버퍼 밖으로 벗어났으면 서버는 재생 전에 (id 없는) 단일
{"type":"gap"}이벤트를 보내요. 클라이언트는 스냅샷을 다시 가져와 재동기화한 다음 테일링을 계속해야 해요. - 세션 종료 — 세션이 서버 측에서 종료되면(예:
DELETE /api/sessions/:id) 서버가 종료{"type":"session_exited"}이벤트를 보내고 스트림을 닫아요. 받은 클라이언트는 멈춰야 해요.session_exited없이 닫히는 스트림은 드롭된 연결이에요 — run 프로세스 자체의 종료도 포함 — 그래서 마지막 id로 재연결하세요. run이 사라졌으면 재연결은 그냥 실패해요.
갭 없이 재연결 (Reconnecting without gaps)
GET /api/sessions/:id/snapshot은 한 응답으로 세션의 전체 상태를 반환해요 — 저장된 필드(메시지, 토큰, 권한), 라이브 런타임 상태(streaming, 현재 에이전트), 그리고 last_event_seq: 가장 최근 이벤트의 시퀀스 번호. 이벤트 스트림과 짝지으면 정확하고 갭 없는 재동기화가 돼요:
# 1. Read the full state and the stream position it corresponds to.
$ SEQ=$(curl -s http://127.0.0.1:8080/api/sessions/$SID/snapshot | jq .last_event_seq)
# 2. Tail everything that happens after that point (replaying anything that
# occurred between the two calls).
$ curl -N "http://127.0.0.1:8080/api/sessions/$SID/events?since=$SEQ"
이 snapshot-then-tail 패턴은 클라이언트(또는 방금 재시작한 클라이언트)가 폴링 없이 세션 상태를 재구성하고 올바르게 유지하게 해줘요.
준비 대기 (Waiting for readiness)
GET /api/sessions/:id/status는 세션의 런타임 상태를 보고해요. ?wait=<duration>(예: ?wait=10s)을 추가하면 그 특정 세션의 런타임이 첨부되고 후속을 받을 준비가 될 때까지 블록한 다음 상태를 반환하거나, 시간 초과 시 503을 반환해요. 이것은 어떤 세션이든 준비되면 즉시 발화하는 GET /api/ready와 달리 session-scoped예요.
세션 포킹 (Session Forking)
POST /api/sessions/:id/fork는 기록이 지정된 사용자 메시지까지(그것은 제외) 부모의 사본인 새 세션을 만들어요. 클라이언트가 대화를 "분기"할 수 있게 — 예를 들어 이전 질문으로 되감고 다른 프롬프트를 시도 — 그 전에 온 공유 기록을 잃지 않고요.
요청 본문:
{ "user_message_index": 1 }
user_message_index는 부모의 평평한 사용자 표시 메시지 목록에서 user-role 메시지만 세는 0 기반 서수예요. 대상 사용자 메시지는 포크에서 제외되므로 클라이언트가 채팅 입력에 미리 채워 사용자가 편집·재제출하게 할 수 있어요.
예제:
# Fork a session before the second user message (ordinal 1)
$ curl -X POST http://localhost:8080/api/sessions/$SID/fork \
-H 'Content-Type: application/json' \
-d '{"user_message_index": 1}'
# Returns: api.SessionResponse for the new forked session
# New session title: "<parent title> (fork 1)", "(fork 2)", etc.
검증:
- 범위 밖 서수(음수, 또는 user-message 수에 도달/초과)는 400 Bad Request 반환.
- 서브 세션 안의 사용자 메시지로 해석되는 서수는 400 Bad Request 반환. 서브 세션은 멀티 에이전트 구성이 하위 에이전트에 작업을 위임할 때 생성되는 중첩 세션이고, 그 메시지는 부모 세션의 메시지 목록에 임베드되어 포크 경계로 쓸 수 없어요.
멱등 후속 (Idempotent follow-ups)
POST /api/sessions/:id/followup은 선택적 Idempotency-Key 헤더를 받아들여 네트워크 시간 초과 후 요청을 안전하게 재시도하게 해요. 세션에서 이미 본 키로 반복하면 후속을 다시 전달하지 않고 승인돼요:
$ curl -X POST http://127.0.0.1:8080/api/sessions/$SID/followup \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a-...' \
-d '{"messages":[{"content":"Ship it"}]}'
# => {"status":"queued_streaming","duplicate":false}
# A retry with the same key => {"status":"duplicate","duplicate":true}
응답 상태는 queued_streaming(턴이 실행 중이거나 시작), queued_idle(유휴 헤드리스 세션에 전달, 다음 턴에 실행), 또는 duplicate예요.
참고 — 함께 보기: 대화형 사용은 Terminal UI. 에이전트 간 통신은 A2A Protocol과 ACP. MCP 통합은 MCP Mode. OpenAI 호환 chat-completions API는 Chat Server.