OpenAI SDK
Kiln은 OpenAI Chat Completions API를 제공하므로 공식 OpenAI 클라이언트가 중간 어댑터 없이 그대로 연결됩니다. 바꾸는 값은 base URL, 키, 모델 ID 세 가지입니다.
설치
bash
pip install openaibash
npm install openaibash
go get github.com/openai/openai-go/v3연결
python
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.bricksum.com/v1",
api_key=os.environ["KILN_API_KEY"], # sk-bk-...
)
resp = client.chat.completions.create(
model="qwen3-32b",
messages=[{"role": "user", "content": "Write a haiku about kilns."}],
max_tokens=800,
)
print(resp.choices[0].message.content)javascript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.bricksum.com/v1",
apiKey: process.env.KILN_API_KEY, // sk-bk-...
});
const resp = await client.chat.completions.create({
model: "qwen3-32b",
messages: [{ role: "user", content: "Write a haiku about kilns." }],
max_tokens: 800,
});
console.log(resp.choices[0].message.content);go
package main
import (
"context"
"fmt"
"os"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
)
func main() {
client := openai.NewClient(
option.WithBaseURL("https://api.bricksum.com/v1"),
option.WithAPIKey(os.Getenv("KILN_API_KEY")),
)
resp, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "qwen3-32b",
MaxTokens: openai.Int(800),
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage("Write a haiku about kilns."),
},
})
if err != nil {
panic(err)
}
fmt.Println(resp.Choices[0].Message.Content)
}툴 호출
tool_choice를 "auto"로 둔 왕복 한 번입니다. 모델이 툴을 요청하면 코드가 실행하고, 그 결과를 tool 메시지로 돌려보냅니다. 모든 툴에는 description이 있어야 하며, 없는 툴은 모델 서버가 400으로 거부합니다.
python
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.bricksum.com/v1", api_key=os.environ["KILN_API_KEY"])
tools = [{"type": "function", "function": {
"name": "get_weather",
"description": "Current weather for a city", # required
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
}}]
messages = [{"role": "user", "content": "What's the weather in Seoul?"}]
first = client.chat.completions.create(model="qwen3-32b", messages=messages,
tools=tools, tool_choice="auto", max_tokens=800)
reply = first.choices[0].message
# The model may answer without a tool call, and one reply can carry several.
if reply.tool_calls:
messages.append(reply)
for call in reply.tool_calls:
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps({"temp_c": 27})})
final = client.chat.completions.create(model="qwen3-32b", messages=messages, max_tokens=800)
print(final.choices[0].message.content)
else:
print(reply.content)javascript
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.bricksum.com/v1", apiKey: process.env.KILN_API_KEY });
const tools: OpenAI.ChatCompletionTool[] = [{ type: "function", function: {
name: "get_weather",
description: "Current weather for a city", // required
parameters: { type: "object", properties: { city: { type: "string" } }, required: ["city"] },
}}];
const messages: OpenAI.ChatCompletionMessageParam[] = [
{ role: "user", content: "What's the weather in Seoul?" },
];
const first = await client.chat.completions.create({ model: "qwen3-32b", messages, tools, tool_choice: "auto", max_tokens: 800 });
// The model may answer without a tool call, and one reply can carry several.
const calls = first.choices[0].message.tool_calls ?? [];
if (calls.length > 0) {
messages.push(first.choices[0].message);
for (const call of calls) {
if (call.type !== "function") continue;
messages.push({ role: "tool", tool_call_id: call.id, content: JSON.stringify({ temp_c: 27 }) });
}
const final = await client.chat.completions.create({ model: "qwen3-32b", messages, max_tokens: 800 });
console.log(final.choices[0].message.content);
} else {
console.log(first.choices[0].message.content);
}Kiln에서 다른 점
- usage.cost는 OpenAI 스키마에 없음 Kiln은 모든 응답의 usage 객체에 USD 단위 cost를 더해 보냅니다. OpenAI 클라이언트는 usage를 OpenAI 스키마대로 타입 지정하고 그 스키마에는 이 필드가 없으므로, 타입을 넓히기 전까지 TypeScript가 resp.usage.cost를 거부합니다. 값 자체는 어느 쪽이든 응답에 담겨 옵니다.
- reasoning 토큰도 max_tokens에 포함 모델은 답하기 전에 reasoning을 수행하며 그 토큰도 과금되고 max_tokens 안에 포함됩니다. 예산이 작으면 message가 빈 채로 finish_reason이 "length"로 돌아오므로 둘 다 들어갈 여유를 두세요. 예제의 800은 이 모델에서 측정하지 않은 시작값이므로, content가 비고 finish_reason이 "length"이면 늘리세요.
base URL, 인증, 모든 엔드포인트가 공유하는 요청 파라미터, 응답 형식, 스트리밍, 에러 코드는 어떤 SDK를 쓰든 같습니다. 이 내용은 API 레퍼런스에 한 번만 정리돼 있습니다. 위 호출이 도달하는 엔드포인트는 Chat completions입니다. 모델 ID는 API가 지금 서빙 중인 것이어야 합니다. 목록을 조회하는 방법과 원하는 ID가 목록에 없을 때 할 일은 모델 페이지에 있습니다. SDK와 무관하게 이 모델이 지원하지 않는 기능은 OpenAI에서 옮겨오기 페이지에 정리돼 있습니다.
참고
이 페이지의 스니펫은 2026-09-21에 openai 3.16.2 (Python), openai 7.20.0 (Node), openai-go v3.64.0 환경에서 Kiln API로 직접 실행해 확인했습니다. 확인하지 않은 부분: 그 실행은 gpt-oss-120b에서 했습니다. 페이지는 이제 qwen3-32b을 사용하며, 이 모델로는 아직 다시 실행하지 않았습니다. 툴 호출 탭에서 모든 툴 호출에 답하는 반복문은 그 실행 이후에 추가됐으며 API로 실행하지 않았습니다.