채팅 서버
채팅 서버 (Chat Server)
OpenAI 호환 Chat Completions API로 에이전트를 노출해서, 이미 OpenAI를 말하는 어떤 도구든 Docker Agent 에이전트를 구동하게 해요.
출처: 문서
본문
개요 (Overview)
docker agent serve chat 명령은 /v1/chat/completions 와 /v1/models 에서 OpenAI 호환 Chat Completions API로 하나 이상의 에이전트를 노출하는 HTTP 서버를 시작해요. 이미 OpenAI 프로토콜을 말하는 어떤 클라이언트 — 예: Open WebUI, curl, OpenAI Python SDK, LangChain — 도 커스텀 통합 없이 Docker Agent 에이전트를 구동할 수 있어요.
# Single agent — exposed as the model `root`
$ docker agent serve chat agent.yaml
# Multi-agent config — every agent in the team becomes a model
$ docker agent serve chat ./team.yaml
# Pick a specific agent from a multi-agent config
$ docker agent serve chat ./team.yaml --agent reviewer
# Run an agent straight from the registry
$ docker agent serve chat myorg/agent:tag --listen 127.0.0.1:9090
# Require a Bearer token, sourced from an env var
$ docker agent serve chat agent.yaml --api-key-env CHAT_BEARER_TOKEN
Tip 채팅 서버 vs API 서버 (When to use chat server vs. API server) Docker Agent를 기존 OpenAI 호환 도구(챗 UI, IDE 통합, OpenAI SDK 클라이언트)에 끼워 넣고 싶을 때 채팅 서버를 사용하세요. 세션, 에이전트 실행, 도구 호출 확인, 스트리밍 런타임 이벤트를 완전히 제어하고 싶을 때는 API 서버를 사용하세요.
엔드포인트 (Endpoints)
OpenAI 호환 엔드포인트는 OpenAI API 표면과 일치하도록 /v1 접두사 아래에 살아요. OpenAPI 사양은 인증 없이 발견될 수 있도록 최상위에 제공돼요.
| Method | Path | Description |
|---|---|---|
| GET | /v1/models |
이 서버가 모델로 노출하는 에이전트 나열 |
| POST | /v1/chat/completions |
메시지 보내고 완성 받기 (일반 또는 스트리밍) |
| GET | /openapi.json |
채팅 서버용 OpenAPI 사양 |
POST /v1/chat/completions 의 모델 식별자는 에이전트 이름 이에요. 단일 에이전트 구성에서는 보통 root; 다중 에이전트 구성에서는 각 이름 있는 에이전트가 자체 선택 가능한 모델이 돼요.
빠른 시작 (Quick Start)
# 1. Start the server
$ docker agent serve chat agent.yaml
Listening on 127.0.0.1:8083
OpenAI-compatible chat completions endpoint: http://127.0.0.1:8083/v1/chat/completions
# 2. List exposed agents (models)
$ curl http://127.0.0.1:8083/v1/models
{ "object": "list", "data": [{ "id": "root", "object": "model", "owned_by": "docker-agent" }]}
# 3. Send a chat request
$ curl http://127.0.0.1:8083/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "root",
"messages": [{"role": "user", "content": "Hello!"}]
}'
스트리밍 (Streaming)
요청 본문에 "stream": true 를 설정하면 OpenAI 형식 chat.completion.chunk 델타의 Server-Sent Events(SSE) 스트림을 받아요:
$ curl -N http://127.0.0.1:8083/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "root",
"stream": true,
"messages": [{"role": "user", "content": "Stream a poem"}]
}'
OpenAI Python SDK에서 구동 (Drive it from the OpenAI Python SDK)
와이어 형식이 OpenAI 호환이므로, 어떤 OpenAI 클라이언트든 채팅 서버의 base_url 을 가리키고 에이전트 이름을 모델로 사용해요:
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8083/v1",
api_key="not-needed-when-no-api-key-flag", # required by the SDK, ignored if no auth
)
resp = client.chat.completions.create(
model="root",
messages=[{"role": "user", "content": "Hello!"}],
)
print(resp.choices[0].message.content)
서버 측 대화 캐싱 (Server-side Conversation Caching)
기본적으로 서버는 무상태(stateless)예요: 모든 요청은 OpenAI의 API와 정확히 같이 전체 메시지 기록을 포함해야 해요. --conversations-max 를 양수 값으로 설정해 서버 측 캐싱을 활성화한 뒤, 각 요청에 안정적인 X-Conversation-Id 헤더를 보내요:
$ docker agent serve chat agent.yaml --conversations-max 100 --conversation-ttl 30m
$ curl http://127.0.0.1:8083/v1/chat/completions \
-H 'Content-Type: application/json' \
-H 'X-Conversation-Id: my-thread-1' \
-d '{
"model": "root",
"messages": [{"role": "user", "content": "Remember my name is Alice"}]
}'
$ curl http://127.0.0.1:8083/v1/chat/completions \
-H 'Content-Type: application/json' \
-H 'X-Conversation-Id: my-thread-1' \
-d '{
"model": "root",
"messages": [{"role": "user", "content": "What is my name?"}]
}'
캐시된 대화는 --conversation-ttl 만큼 비활성 후, 또는 캐시가 --conversations-max 항목에 닿으면(가장 오래된 항목이 먼저 퇴출) 제거돼요.
실패 안전 캐싱 (Failure-safe caching)
요청이 실패하면 — 예를 들어 모델이 에러를 반환하거나 --request-timeout 이 만료되면 — 대화 캐시가 갱신되지 않아요. 서버는 각 요청을 처리하기 전에 캐시된 세션을 클론하고 턴이 성공적으로 완료될 때만 갱신된 세션을 커밋해요. 이는 다음을 의미해요:
- 실패한 턴은 대화를 요청 전과 같은 상태로 둬요.
- 클라이언트는 실패 후 같은
X-Conversation-Id로 안전하게 재시도할 수 있어요. - 일시적 에러가 대화 기록을 손상시키지 않아요.
인증 (Authentication)
채팅 서버는 기본적으로 루프백 바인딩을 사용해요. 비루프백 --listen 주소는 --api-key, --api-key-env, 또는 명시적 --insecure-no-auth 재정의를 필요로 해요. --api-key-env 로 선택된 환경 변수는 설정되고 비어 있지 않아야 해요.
Bearer 토큰을 요구하려면 --api-key(리터럴 값) 또는 --api-key-env(값을 담는 환경 변수의 이름)를 전달해요:
$ docker agent serve chat agent.yaml --api-key-env CHAT_BEARER_TOKEN
그러면 클라이언트는 /v1/* 에 대한 모든 요청에 Authorization: Bearer *** 헤더를 보내야 해요. 키가 설정되면 /v1/models 와 /v1/chat/completions 모두 보호돼요.
Warning 공개 노출 (Public exposure) 기본 수신 주소는 127.0.0.1:8083 이에요.
--api-key,--api-key-env,--insecure-no-auth가 제공되지 않으면 비루프백 바인딩은 거부돼요. 인증되지 않은 재정의는 신뢰된 인증 경계 뒤에서만 사용하세요.
도구 안전 (Tool safety)
채팅 서버는 --safety, 에이전트 구성, 런타임 구성, restricted 순으로 안전 정책을 해결해요. 캐시된 대화는 이전 정책과 서버 정책 중 더 제한적인 것을 유지하므로, 서버 정책이 더 엄격해진 후에도 연속이 권한을 되찾을 수 없어요.
CORS
CORS는 기본적으로 비활성화돼요. 브라우저 기반 클라이언트가 서버를 호출하게 하려면 --cors-origin 을 허용되어야 하는 정확한 origin(스킴 + 호스트 + 포트)으로 설정해요:
$ docker agent serve chat agent.yaml --cors-origin https://my-ui.example.com
CLI 플래그 (CLI Flags)
docker agent serve chat <agent-file> | <registry-ref> [flags]
| Flag | Default | Description |
|---|---|---|
-a, --agent <name> |
(all agents) | 노출할 에이전트 이름. 생략하면 구성의 모든 에이전트가 별개 모델로 노출. |
-l, --listen <addr> |
127.0.0.1:8083 | 수신 주소 |
--cors-origin <origin> |
(none) | 허용된 CORS origin (예: https://example.com). 비어 있으면 CORS 비활성화. |
--api-key <token> |
(none) | 클라이언트가 제시해야 하는 필수 Bearer 토큰 (Authorization: Bearer ***). 비어 있으면 인증 비활성화. |
--api-key-env <name> |
(none) | 필수 API 키를 이 비어 있지 않은 환경 변수에서 읽기 |
--insecure-no-auth |
false | 인증 없는 비루프백 바인딩 허용. 신뢰된 인증 경계 뒤에서만 사용. |
--safety <policy> |
restricted | 도구 안전 정책. CLI 값이 에이전트/런타임 구성을 재정의. |
--max-request-size <bytes> |
1048576 (1 MiB) | 최대 요청 본문 크기(바이트). 본문이 이 한도를 넘는 요청은 HTTP 413(Request Entity Too Large)으로 거부 — 이걸 만나면 Troubleshooting: HTTP 413 참고. |
--request-timeout <dur> |
5m | 요청별 타임아웃(모델 + 도구 호출 + 스트리밍 포함). |
--conversations-max <n> |
0 | 최대 N개 대화에 대해 서버 측 캐시, X-Conversation-Id 로 키 매김. 0이면 비활성화 — 클라이언트가 기록을 재전송해야 함. |
--conversation-ttl <dur> |
30m | 캐시된 대화가 제거되는 유휴 TTL. |
--max-idle-runtimes <n> |
4 | 에이전트당 풀링되는 최대 유휴 런타임 수. 0이면 풀링 비활성화. |
모든 런타임 구성 플래그(--working-dir, --env-from-file, --models-gateway, --hook-*, …)도 받아들여져요.
Note
--max-request-size의 범위 이것은 단일 직렬화된 인바운드 HTTP 요청 본문에 대한 유한하면서 프로세스 전체에 걸친 상한이에요 — 모델 컨텍스트 창 한도가 아니고, 올려도 제공자/모델이 받아들이는 것 또는 로컬 첨부 파일/프롬프트 파일이 얼마나 클 수 있는지를 늘리지 않아요. 더 큰 상한은 서버가 인증되지 않거나 악의적인 클라이언트로부터 요청당 더 많은 메모리를 버퍼링한다는 뜻이므로, 배포의 노출과 저울질하세요. 이 서버 앞에 역방향 프록시나 게이트웨이가 있으면 이 플래그와 무관하게 자체 더 낮은 상한을 강제할 수 있어요. 전체 진단은 Troubleshooting: HTTP 413 참고.
이미지 입력 (Image Inputs)
메시지는 텍스트 옆에 OpenAI 스타일 image_url 콘텐츠 부분을 포함할 수 있어요:
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,..." }}
data: URL은 이미지 바이트를 JSON 본문에 직접 임베드하므로, base64 인코딩된 크기가 다른 요청 콘텐츠처럼 위의 --max-request-size 에 포함돼요. 원격 http(s):// URL은 채팅 서버 자체가 가져오는 대신 선택된 모델 제공자에게 전달돼요 — 동작 여부는 그 제공자와 모델에 달려 있어요: 일부는 원격 URL을 직접 받고, 다른 것들은 data: URL만 받으며, 이미지 지원이 없는 제공자/모델은 그 부분을 버려요. 원격 이미지 URL이 보편적으로 가져와지거나 렌더링될 거라고 가정하지 말고, 구성한 특정 제공자/모델에 대해 검증하세요.
Open WebUI 통합 (Open WebUI Integration)
Open WebUI는 어떤 OpenAI 호환 엔드포인트와도 통신할 수 있어요. Docker Agent를 연결하려면:
- 채팅 서버를, 선택적으로 인증과 함께 시작해요:
$ docker agent serve chat agent.yaml \
--listen 127.0.0.1:8083 \
--cors-origin http://localhost:3000 \
--api-key-env OPEN_WEBUI_TOKEN
- Open WebUI에서 OpenAI 호환 연결을 추가해요:
- API Base URL:
http://127.0.0.1:8083/v1 - API Key:
OPEN_WEBUI_TOKEN의 값
- API Base URL:
- 구성의 각 에이전트가 선택 가능한 모델로 나타나요.
Note 참고 (See also) Docker Agent 네이티브 HTTP API(세션, 도구 호출 확인, 런타임 이벤트)는 API Server 참고. 전체 CLI 플래그 문서는 CLI Reference 참고.