OpenResponses API (HTTP)

OpenClaw 게이트웨이는 OpenResponses 호환 POST /v1/responses 엔드포인트를 제공할 수 있습니다.

이 엔드포인트는 기본적으로 비활성화되어 있습니다. 먼저 설정에서 활성화해야 합니다.

  • POST /v1/responses
  • 게이트웨이와 동일한 포트 (WS + HTTP 다중화): http://<gateway-host>:<port>/v1/responses

내부적으로 요청은 일반 게이트웨이 에이전트 실행(openclaw agent와 동일한 코드 경로)으로 처리되므로, 라우팅/권한/설정이 게이트웨이 설정과 동일하게 적용됩니다.

인증, 보안, 라우팅

운영 동작은 OpenAI Chat Completions와 동일합니다:

  • 일반 게이트웨이 인증 설정에 따라 Authorization: Bearer <token> 사용
  • 이 엔드포인트를 게이트웨이 인스턴스에 대한 완전한 운영자 접근으로 취급
  • model: "openclaw:<agentId>", model: "agent:<agentId>" 또는 x-openclaw-agent-id로 에이전트 선택
  • 명시적 세션 라우팅을 위해 x-openclaw-session-key 사용

gateway.http.endpoints.responses.enabled로 이 엔드포인트를 활성화하거나 비활성화할 수 있습니다.

세션 동작

기본적으로 엔드포인트는 요청마다 무상태(매 호출마다 새 세션 키 생성)입니다.

요청에 OpenResponses user 문자열이 포함된 경우, 게이트웨이가 해당 값에서 안정적인 세션 키를 생성하므로 반복 호출이 에이전트 세션을 공유할 수 있습니다.

요청 형식 (지원)

요청은 항목 기반 입력의 OpenResponses API를 따릅니다. 현재 지원 사항:

  • input: 문자열 또는 항목 객체 배열.
  • instructions: 시스템 프롬프트에 병합됨.
  • tools: 클라이언트 도구 정의 (함수 도구).
  • tool_choice: 클라이언트 도구 필터링 또는 강제.
  • stream: SSE 스트리밍 활성화.
  • max_output_tokens: 최선 노력의 출력 제한 (프로바이더에 따라 다름).
  • user: 안정적인 세션 라우팅.

수신되지만 현재 무시됨:

  • max_tool_calls
  • reasoning
  • metadata
  • store
  • previous_response_id
  • truncation

항목 (input)

message

역할: system, developer, user, assistant.

  • systemdeveloper는 시스템 프롬프트에 추가됩니다.
  • 가장 최근의 user 또는 function_call_output 항목이 “현재 메시지”가 됩니다.
  • 이전 user/assistant 메시지는 컨텍스트를 위한 히스토리로 포함됩니다.

function_call_output (턴 기반 도구)

도구 결과를 모델에 다시 전송합니다:

{
  "type": "function_call_output",
  "call_id": "call_123",
  "output": "{\"temperature\": \"72F\"}"
}

reasoningitem_reference

스키마 호환성을 위해 수신되지만 프롬프트 생성 시 무시됩니다.

도구 (클라이언트 측 함수 도구)

tools: [{ type: "function", function: { name, description?, parameters? } }]로 도구를 제공하세요.

에이전트가 도구를 호출하기로 결정하면, 응답에 function_call 출력 항목이 반환됩니다. 그런 다음 턴을 계속하기 위해 function_call_output을 포함한 후속 요청을 보내세요.

이미지 (input_image)

base64 또는 URL 소스를 지원합니다:

{
  "type": "input_image",
  "source": { "type": "url", "url": "https://example.com/image.png" }
}

허용되는 MIME 타입 (현재): image/jpeg, image/png, image/gif, image/webp, image/heic, image/heif. 최대 크기 (현재): 10MB.

파일 (input_file)

base64 또는 URL 소스를 지원합니다:

{
  "type": "input_file",
  "source": {
    "type": "base64",
    "media_type": "text/plain",
    "data": "SGVsbG8gV29ybGQh",
    "filename": "hello.txt"
  }
}

허용되는 MIME 타입 (현재): text/plain, text/markdown, text/html, text/csv, application/json, application/pdf.

최대 크기 (현재): 5MB.

현재 동작:

  • 파일 콘텐츠가 디코딩되어 사용자 메시지가 아닌 시스템 프롬프트에 추가되므로, 세션 히스토리에 영구 저장되지 않습니다(임시).
  • PDF는 텍스트가 추출됩니다. 텍스트가 적은 경우, 첫 페이지들이 이미지로 래스터화되어 모델에 전달됩니다.

PDF 파싱은 Node 친화적인 pdfjs-dist 레거시 빌드(워커 없음)를 사용합니다. 최신 PDF.js 빌드는 브라우저 워커/DOM 전역 객체를 필요로 하므로 게이트웨이에서는 사용하지 않습니다.

URL 페치 기본값:

  • files.allowUrl: true
  • images.allowUrl: true
  • maxUrlParts: 8 (요청당 URL 기반 input_file + input_image 총 파트 수)
  • 요청에 보안 가드가 적용됩니다 (DNS 확인, 사설 IP 차단, 리다이렉트 제한, 타임아웃).
  • 입력 유형별 호스트명 허용 목록을 선택적으로 지원합니다 (files.urlAllowlist, images.urlAllowlist).
    • 정확한 호스트: "cdn.example.com"
    • 와일드카드 서브도메인: "*.assets.example.com" (apex는 매칭하지 않음)

파일 + 이미지 제한 (설정)

기본값은 gateway.http.endpoints.responses에서 조정할 수 있습니다:

{
  gateway: {
    http: {
      endpoints: {
        responses: {
          enabled: true,
          maxBodyBytes: 20000000,
          maxUrlParts: 8,
          files: {
            allowUrl: true,
            urlAllowlist: ["cdn.example.com", "*.assets.example.com"],
            allowedMimes: [
              "text/plain",
              "text/markdown",
              "text/html",
              "text/csv",
              "application/json",
              "application/pdf",
            ],
            maxBytes: 5242880,
            maxChars: 200000,
            maxRedirects: 3,
            timeoutMs: 10000,
            pdf: {
              maxPages: 4,
              maxPixels: 4000000,
              minTextChars: 200,
            },
          },
          images: {
            allowUrl: true,
            urlAllowlist: ["images.example.com"],
            allowedMimes: [
              "image/jpeg",
              "image/png",
              "image/gif",
              "image/webp",
              "image/heic",
              "image/heif",
            ],
            maxBytes: 10485760,
            maxRedirects: 3,
            timeoutMs: 10000,
          },
        },
      },
    },
  },
}

생략 시 기본값:

  • maxBodyBytes: 20MB
  • maxUrlParts: 8
  • files.maxBytes: 5MB
  • files.maxChars: 200k
  • files.maxRedirects: 3
  • files.timeoutMs: 10초
  • files.pdf.maxPages: 4
  • files.pdf.maxPixels: 4,000,000
  • files.pdf.minTextChars: 200
  • images.maxBytes: 10MB
  • images.maxRedirects: 3
  • images.timeoutMs: 10초
  • HEIC/HEIF input_image 소스는 수신 후 프로바이더 전달 전에 JPEG으로 정규화됩니다.

보안 참고:

  • URL 허용 목록은 페치 전과 리다이렉트 hop마다 적용됩니다.
  • 호스트명 허용 목록에 추가해도 사설/내부 IP 차단은 우회되지 않습니다.
  • 인터넷에 노출된 게이트웨이의 경우, 앱 수준 가드 외에도 네트워크 이그레스 제어를 적용하세요. 보안을 참고하세요.

스트리밍 (SSE)

stream: true를 설정하면 Server-Sent Events (SSE)를 수신합니다:

  • Content-Type: text/event-stream
  • 각 이벤트 라인은 event: <type>data: <json>
  • 스트림은 data: [DONE]으로 종료

현재 발생하는 이벤트 유형:

  • response.created
  • response.in_progress
  • response.output_item.added
  • response.content_part.added
  • response.output_text.delta
  • response.output_text.done
  • response.content_part.done
  • response.output_item.done
  • response.completed
  • response.failed (오류 시)

사용량

usage는 기본 프로바이더가 토큰 수를 보고할 때 채워집니다.

오류

오류는 다음과 같은 JSON 객체를 사용합니다:

{ "error": { "message": "...", "type": "invalid_request_error" } }

일반적인 경우:

  • 401 인증 누락/잘못됨
  • 400 잘못된 요청 본문
  • 405 잘못된 메서드

예시

비스트리밍:

curl -sS http://127.0.0.1:18789/v1/responses \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'x-openclaw-agent-id: main' \
  -d '{
    "model": "openclaw",
    "input": "hi"
  }'

스트리밍:

curl -N http://127.0.0.1:18789/v1/responses \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'x-openclaw-agent-id: main' \
  -d '{
    "model": "openclaw",
    "stream": true,
    "input": "hi"
  }'